Re: [Xtcc-developer] Chat with pompon.pompon@gmail.com
Market Research Data Processing Suite
Status: Alpha
Brought to you by:
neilxdsouza
|
From: Neil D'S. <nei...@gm...> - 2010-06-06 17:07:45
|
Hi Pompon,
Thanks for this - I will test your code out - I have just finished a
massive change to the compiler - GenerateCode and PrintExpressionCode - now
write to "Code" Objects because I realised that I needed another stream to
handle array questions navigation correctly and this will save us changing
function signatures in the future should we need another output stream when
generating code.
look at the comment at the beginning. What shall we do?IfStatement::ifBody_
::elseBody_cannot be accessed from TextMapGenerator
reason: IfStatement::ifBody_ ::elseBody are protected
solution: make public or make friend with TextMapGenerator NxD: make it
public, right now lets not worry about encapsulation etc, give it what it
wants to make it compile.
And please verify if my main(){} properly performs the parsing.
NxD: It should work fine - after the call to yyparse() the parse trees are
built. Once I replace the main.cpp with this one I will come to know. Will
work on it tomorrow.
what is DummyArrayQuestion and how to deal with it?
NxD: When reading data from the disk we need to know the dimension of any
array questions based on the level of nesting inside the for loop
I came up with this idea to write the dimension of the array while saving
the data. You will notice that DummyArrayQuestion has an empty
implementation of GenerateCode,
i.e. this question is not asked to the end user. However, it does have an
implementation of WriteDataToDisk - which writes out the bounds of the array
to the disk. The DummyArrayQuestion is created in the question definitions
sections and added to the "question_list" just like an ordinary question.
When write_data_to_disk is called, it iterates over every question in
"question_list" and will invoke the DummyArrayQuestion::WriteDataToDisk
function storing the BOUNDS of the array to the data file.
is line "qscript_parser::GenerateCode()" necessary for anything
NxD: This innocent looking function is the one that generates the code in
test_statement.C - it is the code generation phase, visiting each node in
qscript_parser::tree_root and generating code.
Do you want me to integrate your parsing with my files to data_conv, so as
to avoid the intermediate config file?
If you can set it up as a symbolic link, or use the files in the
simple_compiler/include directory after an install is done, it would be
great. We should be using only 1 parser file otherwise we will be
maintaining 2 files which will lead to a mess sooner or later.
The other option is to integrate the data_conv code with the code in the
qscript folder.
For this case, we could have the following 1) Default Behaviour: When the
compiler generates code for data entry of a questionnaire it also generates
a map
2) We create a command line option to write out the datafile according to
the map. When invoked with this option the compiler will write a program
that recodes the data according to a map.
If you are not happy with my suggestion above, feel free to suggest
something better.
Rgds,
NxD
> These messages were sent while you were offline.
>
> 7:09 PM pompon: I've written text map generator according to the
> instructions from your last mail. Here it is (replacement for
> qscript/src/main.cpp - map is printed to stdout - nothing interesting by
> now):
> /*
> stmt.h: IfStatement::ifBody_ ::elseBody cannot be accessed from
> TextMapGenerator
> reason: IfStatement::ifBody_ ::elseBody are protected
> solution: make public or make friend with TextMapGenerator
> */
>
> #include "qscript_parser.h"
> #include <iostream>
> #include <fstream>
> //#include <typeinfo>
>
> #define REP(i,n) for(int i=0; i<(n); ++i)
>
> class TextMapGenerator
> {
> public:
> std::vector<AbstractQuestion*> question;
> std::vector<named_range*> range;
>
> static const char *text(DataType dt)
> {
> switch(dt)
> {
> case INT8_TYPE : return "int8" ; case INT16_TYPE : return "int16" ;
> case INT32_TYPE : return "int32" ; case FLOAT_TYPE : return "float" ;
> case DOUBLE_TYPE: return "double"; default: return "<unrecognized type>";
> }
> }
>
> void visit(AbstractStatement *stmt, int depth = 0)
> {
> if(!stmt) return;
> string pre="";//(depth,' ');
> //std::ostream &os = std::cout;
> if(AbstractQuestion *q = dynamic_cast<AbstractQuestion*>(stmt))
> {
> question.push_back(q);
> /*os << pre << "[AbstractQuestion] " << q->questionName_ << ' ';
>
> os << std::endl;*/
> }
> else if(CompoundStatement *cs = dynamic_cast<CompoundStatement*>(stmt))
> {
> //os << pre << "[CompoundStatement]" << std::endl;
> visit(cs->compoundBody_,depth+1);
> }
> else if(ForStatement *fs = dynamic_cast<ForStatement*>(stmt))
> {
> //os << pre << "[ForStatement]" << std::endl;
> visit(fs->forBody_,depth+1);
> }
> else if(IfStatement *is = dynamic_cast<IfStatement*>(stmt))
> {
> //os << pre << "[IfStatement]" << std::endl;
> visit(is->ifBody_,depth+1);
> //os << pre << "[IfStatement : else]" << std::endl;
> visit(is->elseBody_,depth+1);
> }
> else if(FunctionStatement *fs = dynamic_cast<FunctionStatement*>(stmt))
> {
> //os << pre << "[FunctionStatement]" << std::endl;
> visit(fs->functionBody_,depth+1);
> }
> else if(named_range *nr = dynamic_cast<named_range*>(stmt))
> {
> range.push_back(nr);
> //os << pre << "[named_range]" << std::endl;
> }
> //else if(dynamic_cast<FunctionDeclarationStatement*>(stmt))
> // os << pre << "[FunctionDeclarationStatement]" << std::endl;
> //else if(dynamic_cast<ExpressionStatement*>(stmt)) os << pre <<
> "[ExpressionStatement]" << std::endl;
> //else if(dynamic_cast<StubManipStatement*>(stmt)) os << pre <<
> "[StubManipStatement]" << std::endl;
> //else if(dynamic_cast<DeclarationStatement*>(stmt)) os << pre <<
> "[DeclarationStatement]" << std::endl;
> //else { os << pre << "[unknown statement] " << typeid(*stmt).name() <<
> std::endl; }
> visit(stmt->next_,depth);
> }
>
> void print(std::ostream &os)
> {
> os << question.size() << '\n';
> REP(i,question.size())
> {
> os << question[i]->questionName_ << ' ' << text(question[i]->dt);
> if(question[i]->q_type==mpn) os << ' ' << question[i]->no_mpn; else os << "
> 1";
> if(RangeQuestion *q = dynamic_cast<RangeQuestion*>(question[i]))
> {
> //os << " [RangeQuestion]";
> }
> else if(NamedStubQuestion *q =
> dynamic_cast<NamedStubQuestion*>(question[i]))
> {
> os << ' ' << q->nr_ptr->name;
> //os << " [NamedStubQuestion]";
> }
> else if(DummyArrayQuestion *q =
> dynamic_cast<DummyArrayQuestion*>(question[i]))
> {
> os << " [DummyArrayQuestion]";
> }
> else os << " <unknown question type>";
> os << '\n';
> }
>
> REP(i,range.size())
> {
> os << range[i]->name;
> REP(j,range[i]->stubs.size())
> os << ' ' << range[i]->stubs[j].code << " \"" <<
> range[i]->stubs[j].stub_text << '\"';
> os << '\n';
> }
> }
>
> };
>
> void yyrestart(FILE *);
> int yyparse();
>
> void InitStatement();
>
> int main(int argc, char* argv[])
> {
> InitStatement();
> qscript_parser::active_scope = new Scope();
> qscript_parser::active_scope_list.push_back(qscript_parser::active_scope);
>
> yyrestart(stdin);
> if(!yyparse() && !qscript_parser::no_errors)
> {
> std::cout << "{input parsed}" << std::endl;
> qscript_parser::GenerateCode();
> std::cout << "{code generated}" << std::endl;
> TextMapGenerator G; G.visit(qscript_parser::tree_root); G.print(std::cout);
> std::cout << "{text map generated}" << std::endl;
> }
> else std::cout << "There were : " << qscript_parser::no_errors << " errors
> in parse" << std::endl;
> return qscript_parser::no_errors;
> }
> 7:11 PM look at the comment at the beginning. What shall we do?
> 7:15 PM And please verify if my main(){} properly performs the parsing.
> 7:16 PM what is DummyArrayQuestion and how to deal with it?
> ------------------------------
> 8 minutes
> 7:24 PM pom...@gm...: Do you want me to integrate your parsing
> with my files to data_conv, so as to avoid the intermediate config file?
> ------------------------------
> 21 minutes
> 7:46 PM pom...@gm...: is line "qscript_parser::GenerateCode()"
> necessary for anything?
>
|