rendered paste body%{
// LSys.y generates LSys.tab.cpp & LSys.tab.hpp
#include <iostream>
#include <sstream>
#include <fstream>
#include <windows.h>
#include <boost/smart_ptr.hpp>
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<SymLFile> sym(new SymLFile());
sym->declarations = SYM_AS<SymDeclarations>($1);
sym->rules = SYM_AS<SymLRules>($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<SymDeclarations> sym(new SymDeclarations());
sym->Declare(SYM_AS<SymDeclaration>($1));
$$ = SYM(sym);
}
| declarations declaration {
shared_ptr<SymDeclarations> sym(SYM_AS<SymDeclarations>($1));
sym->Declare(SYM_AS<SymDeclaration>($2));
$$ = $1;
}
;
declaration: axiom { $$ = $1; }
| var_declaration ';' { $$ = $1; }
;
var_declaration: SYMBOL ASSIGN expression {
shared_ptr<SymDeclaration> sym(new SymDeclaration());
sym->var = SYM_AS<SymStr>($1)->val;
sym->val = $3;
sym->type = SymDeclaration::declConst;
$$ = SYM(sym);
}
axiom: AXIOM ':' modulelist ';' {
shared_ptr<SymDeclaration> sym(new SymDeclaration());
sym->val = $3;
sym->type = SymDeclaration::declAxiom;
$$ = SYM(sym);
}
rulelist: rule {
shared_ptr<SymLRules> sym(new SymLRules());
sym->rules.push_back(SYM_AS<SymLRule>($1));
$$ = SYM(sym);
}
| rulelist rule {
SYM_AS<SymLRules>($1)->rules.push_back(SYM_AS<SymLRule>($2));
$$ = $1;
}
;
// left context of rules
rule: rule_sub { $$ = $1; }
| modulelist LESS rule_sub {
SYM_AS<SymLRule>($3)->lc = SYM_AS<SymModuleList>($1);
$$ = $3;
}
;
/* TODO: add multiple rhs for stochastic systems */
rule_sub: modulelist rightcontext condition ARROW modulelist ';' {
shared_ptr<SymLRule> sym(new SymLRule());
sym->lhs = SYM_AS<SymModuleList>($1);
sym->rc = SYM_AS<SymModuleList>($2);
sym->cond = SYM_AS<SymBoolExpression>($3);
sym->rhs = SYM_AS<SymModuleList>($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<SymLogicalExpression> sym(new SymLogicalExpression());
sym->lhs = SYM_AS<SymBoolExpression>($1);
sym->op = SymLogicalExpression::opOr;
sym->rhs = SYM_AS<SymBoolExpression>($3);
$$ = SYM(sym);
}
| cond_expression ANDAND cond_expression {
shared_ptr<SymLogicalExpression> sym(new SymLogicalExpression());
sym->lhs = SYM_AS<SymBoolExpression>($1);
sym->op = SymLogicalExpression::opAnd;
sym->rhs = SYM_AS<SymBoolExpression>($3);
$$ = SYM(sym);
}
| '(' cond_expression ')' { $$ = $2; }
| compare_expression { $$ = $1; }
;
compare_expression: expression compare_operator expression {
shared_ptr<SymCompareExpression> sym(new SymCompareExpression());
sym->lhs = SYM_AS<SymExpression>($1);
switch (SYM_AS<SymSymbol>($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<SymSymbol>($2)->val << endl;
}
sym->rhs = SYM_AS<SymExpression>($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<SymModuleList> sym(new SymModuleList());
sym->modules.push_back(SYM_AS<SymModuleBase>($1));
$$ = SYM(sym);
}
| modulelist module {
// append $2 to existing module list $1
SYM_AS<SymModuleList>($1)->modules.push_back(SYM_AS<SymModuleBase>($2));
$$ = $1;
}
| '[' modulelist ']' {
shared_ptr<SymModuleList> sym(new SymModuleList());
shared_ptr<SymModuleTree> symt(new SymModuleTree());
symt->children = SYM_AS<SymModuleList>($2);
sym->modules.push_back(symt);
$$ = SYM(sym);
}
| modulelist '[' modulelist ']' {
shared_ptr<SymModuleTree> sym(new SymModuleTree());
sym->children = SYM_AS<SymModuleList>($3);
SYM_AS<SymModuleList>($1)->modules.push_back(sym);
$$ = $1;
}
;
module: modulename moduleparams {
shared_ptr<SymModuleDef> sym(new SymModuleDef());
sym->name = SYM_AS<SymStr>($1)->val;
sym->type = SymModuleDef::mtModule;
sym->params = SYM_AS<SymExpressions>($2);
$$ = SYM(sym);
}
| '?' modulename moduleparams {
shared_ptr<SymModuleDef> sym(new SymModuleDef());
sym->name = SYM_AS<SymStr>($2)->val;
sym->type = SymModuleDef::mtQuery;
sym->params = SYM_AS<SymExpressions>($3);
$$ = SYM(sym);
}
;
modulename: USYMBOL { $$ = $1; }
/* special symbols for traditional l-system fallback */
| '+' { $$ = $1; }
| '-' { $$ = $1; }
;
moduleparams: /* none */ { $$ = NullSym; }
| '(' expressions ')' { $$ = $2; }
;
expressions:
| expression {
shared_ptr<SymExpressions> sym(new SymExpressions());
sym->expressions.push_back(SYM_AS<SymExpression>($1));
$$ = SYM(sym);
}
| expressions ',' expression {
SYM_AS<SymExpressions>($1)->expressions.push_back(SYM_AS<SymExpression>($3));
$$ = $1;
}
;
expression: expression '+' expression {
shared_ptr<SymBinaryExpression> sym(new SymBinaryExpression());
sym->op = SymBinaryExpression::opAdd;
sym->lhs = SYM_AS<SymExpression>($1);
sym->rhs = SYM_AS<SymExpression>($3);
$$ = SYM(sym);
}
| expression '-' expression {
shared_ptr<SymBinaryExpression> sym(new SymBinaryExpression());
sym->op = SymBinaryExpression::opSub;
sym->lhs = SYM_AS<SymExpression>($1);
sym->rhs = SYM_AS<SymExpression>($3);
$$ = SYM(sym);
}
| expression '*' expression {
shared_ptr<SymBinaryExpression> sym(new SymBinaryExpression());
sym->op = SymBinaryExpression::opMul;
sym->lhs = SYM_AS<SymExpression>($1);
sym->rhs = SYM_AS<SymExpression>($3);
$$ = SYM(sym);
}
| expression '/' expression {
shared_ptr<SymBinaryExpression> sym(new SymBinaryExpression());
sym->op = SymBinaryExpression::opDiv;
sym->lhs = SYM_AS<SymExpression>($1);
sym->rhs = SYM_AS<SymExpression>($3);
$$ = SYM(sym);
}
| '-' expression %prec UMINUS {
shared_ptr<SymUnaryExpression> sym(new SymUnaryExpression());
sym->op = SymUnaryExpression::opMinus;
sym->rhs = SYM_AS<SymExpression>($2);
$$ = SYM(sym);
}
| '(' expression ')' { $$ = $2}
| expressionatom {
$$ = $1;
}
;
expressionatom: const_expression { $$ = $1; }
| SYMBOL {
shared_ptr<SymSymbolExpAtom> sym(new SymSymbolExpAtom(SYM_AS<SymStr>($1)->val));
$$ = SYM(sym);
}
const_expression: NUMBER {
shared_ptr<SymNumberExpAtom> sym(new SymNumberExpAtom(SYM_AS<SymStr>($1)->val));
$$ = SYM(sym);
}
| STRING {
shared_ptr<SymStringExpAtom> sym(new SymStringExpAtom(SYM_AS<SymStr>($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();
}