%{ // LSys.y generates LSys.tab.cpp & LSys.tab.hpp #include #include #include #include #include using namespace boost; using namespace std; #include "LSysNode.h" #include "LSysLexer.h" #include "PreProcess.h" PreProcessor preProcessor; LSysLexer lSysLexer(preProcessor); #pragma warning( disable : 4065 ) void LSyserror(const char *error); int LSyslex(); #include "LSysDef.h" %} %token USYMBOL LSYMBOL STRING NUMBER COMMENT AXIOM ARROW OROR ANDAND LESS GREATER ASSIGN LEQUAL GEQUAL EQUAL NEQUAL %left OROR %left ANDAND %left '-' '+' %left '*' '/' %nonassoc UMINUS %% lfile: declarations rulelist { shared_ptr sym(new SymLFile()); sym->declarations = SYM_AS($1); sym->rules = SYM_AS($2); // process lfile ... sym->DebugPrint(); // evaluate debugvar Defines::iterator it = sym->declarations->defines.find("Debugvar"); if (it != sym->declarations->defines.end()) { EvalValue res; cout << "Evalulating Debugvar: "; it->second->Evaluate(res, sym->declarations->defines); switch (res.kind) { case EvalValue::kNumber: cout << res.d; break; case EvalValue::kString: cout << "\"" << res.s << "\""; break; case EvalValue::kInvalid: cout << "Invalid expression"; break; default: cout << "Critical error: unknown type after evaluation"; } cout << endl; } $$ = SYM(sym); } declarations: declaration { shared_ptr sym(new SymDeclarations()); sym->Declare(SYM_AS($1)); $$ = SYM(sym); } | declarations declaration { shared_ptr sym(SYM_AS($1)); sym->Declare(SYM_AS($2)); $$ = $1; } ; declaration: axiom { $$ = $1; } | var_declaration ';' { $$ = $1; } ; var_declaration: SYMBOL ASSIGN expression { shared_ptr sym(new SymDeclaration()); sym->var = SYM_AS($1)->val; sym->val = $3; sym->type = SymDeclaration::declConst; $$ = SYM(sym); } axiom: AXIOM ':' modulelist ';' { shared_ptr sym(new SymDeclaration()); sym->val = $3; sym->type = SymDeclaration::declAxiom; $$ = SYM(sym); } rulelist: rule { shared_ptr sym(new SymLRules()); sym->rules.push_back(SYM_AS($1)); $$ = SYM(sym); } | rulelist rule { SYM_AS($1)->rules.push_back(SYM_AS($2)); $$ = $1; } ; // left context of rules rule: rule_sub { $$ = $1; } | modulelist LESS rule_sub { SYM_AS($3)->lc = SYM_AS($1); $$ = $3; } ; /* TODO: add multiple rhs for stochastic systems */ rule_sub: modulelist rightcontext condition ARROW modulelist ';' { shared_ptr sym(new SymLRule()); sym->lhs = SYM_AS($1); sym->rc = SYM_AS($2); sym->cond = SYM_AS($3); sym->rhs = SYM_AS($5); // read in condition $$ = SYM(sym); } rightcontext: /* empty */ { $$ = NullSym; } | GREATER modulelist { $$ = $2; } ; condition: { $$ = NullSym; } | ':' cond_expression { $$ = $2; } ; /* TODO: add ! (logical unary not) and maybe ^ (logical xor) */ cond_expression: cond_expression OROR cond_expression { shared_ptr sym(new SymLogicalExpression()); sym->lhs = SYM_AS($1); sym->op = SymLogicalExpression::opOr; sym->rhs = SYM_AS($3); $$ = SYM(sym); } | cond_expression ANDAND cond_expression { shared_ptr sym(new SymLogicalExpression()); sym->lhs = SYM_AS($1); sym->op = SymLogicalExpression::opAnd; sym->rhs = SYM_AS($3); $$ = SYM(sym); } | '(' cond_expression ')' { $$ = $2; } | compare_expression { $$ = $1; } ; compare_expression: expression compare_operator expression { shared_ptr sym(new SymCompareExpression()); sym->lhs = SYM_AS($1); switch (SYM_AS($2)->val) { case LESS: sym->op = SymCompareExpression::opLess; break; case GREATER: sym->op = SymCompareExpression::opGreater; break; case GEQUAL: sym->op = SymCompareExpression::opGequal; break; case LEQUAL: sym->op = SymCompareExpression::opLequal; break; case EQUAL: sym->op = SymCompareExpression::opEqual; break; case NEQUAL: sym->op = SymCompareExpression::opNequal; break; default: cout << "Internal compiler error: invalid compare token matched: " << SYM_AS($2)->val << endl; } sym->rhs = SYM_AS($3); $$ = SYM(sym); } compare_operator: LESS { $$ = SYMSYM(LESS); } | GREATER { $$ = SYMSYM(GREATER); } | GEQUAL { $$ = SYMSYM(GEQUAL); } | LEQUAL { $$ = SYMSYM(LEQUAL); } | EQUAL { $$ = SYMSYM(EQUAL); } | NEQUAL { $$ = SYMSYM(NEQUAL); } modulelist: module { // create new module list with $1 inside shared_ptr sym(new SymModuleList()); sym->modules.push_back(SYM_AS($1)); $$ = SYM(sym); } | modulelist module { // append $2 to existing module list $1 SYM_AS($1)->modules.push_back(SYM_AS($2)); $$ = $1; } | '[' modulelist ']' { shared_ptr sym(new SymModuleList()); shared_ptr symt(new SymModuleTree()); symt->children = SYM_AS($2); sym->modules.push_back(symt); $$ = SYM(sym); } | modulelist '[' modulelist ']' { shared_ptr sym(new SymModuleTree()); sym->children = SYM_AS($3); SYM_AS($1)->modules.push_back(sym); $$ = $1; } ; module: modulename moduleparams { shared_ptr sym(new SymModuleDef()); sym->name = SYM_AS($1)->val; sym->type = SymModuleDef::mtModule; sym->params = SYM_AS($2); $$ = SYM(sym); } | '?' modulename moduleparams { shared_ptr sym(new SymModuleDef()); sym->name = SYM_AS($2)->val; sym->type = SymModuleDef::mtQuery; sym->params = SYM_AS($3); $$ = SYM(sym); } ; modulename: USYMBOL { $$ = $1; } /* special symbols for traditional l-system fallback */ | '+' { $$ = $1; } | '-' { $$ = $1; } ; moduleparams: /* none */ { $$ = NullSym; } | '(' expressions ')' { $$ = $2; } ; expressions: | expression { shared_ptr sym(new SymExpressions()); sym->expressions.push_back(SYM_AS($1)); $$ = SYM(sym); } | expressions ',' expression { SYM_AS($1)->expressions.push_back(SYM_AS($3)); $$ = $1; } ; expression: expression '+' expression { shared_ptr sym(new SymBinaryExpression()); sym->op = SymBinaryExpression::opAdd; sym->lhs = SYM_AS($1); sym->rhs = SYM_AS($3); $$ = SYM(sym); } | expression '-' expression { shared_ptr sym(new SymBinaryExpression()); sym->op = SymBinaryExpression::opSub; sym->lhs = SYM_AS($1); sym->rhs = SYM_AS($3); $$ = SYM(sym); } | expression '*' expression { shared_ptr sym(new SymBinaryExpression()); sym->op = SymBinaryExpression::opMul; sym->lhs = SYM_AS($1); sym->rhs = SYM_AS($3); $$ = SYM(sym); } | expression '/' expression { shared_ptr sym(new SymBinaryExpression()); sym->op = SymBinaryExpression::opDiv; sym->lhs = SYM_AS($1); sym->rhs = SYM_AS($3); $$ = SYM(sym); } | '-' expression %prec UMINUS { shared_ptr sym(new SymUnaryExpression()); sym->op = SymUnaryExpression::opMinus; sym->rhs = SYM_AS($2); $$ = SYM(sym); } | '(' expression ')' { $$ = $2} | expressionatom { $$ = $1; } ; expressionatom: const_expression { $$ = $1; } | SYMBOL { shared_ptr sym(new SymSymbolExpAtom(SYM_AS($1)->val)); $$ = SYM(sym); } const_expression: NUMBER { shared_ptr sym(new SymNumberExpAtom(SYM_AS($1)->val)); $$ = SYM(sym); } | STRING { shared_ptr sym(new SymStringExpAtom(SYM_AS($1)->val)); $$ = SYM(sym); } SYMBOL: USYMBOL | LSYMBOL %% #undef yylex void LSyserror (const char *error) { cout << "Error: " << error << " at line " << lSysLexer.lineno() << endl; } int LSyslex() { return lSysLexer.yylex(); } int main () { ifstream f("test.l"); lSysLexer.switch_streams(&f, 0); yyparse(); cin.get(); }