%{ #include #include #include "node.hpp" // AST NBlock *programBlock = 0; extern int grammarlex( ); extern int grammarget_lineno( void ); void grammarerror( const char *s ) { std::cerr << "ERROR in line " << grammarget_lineno( ) << ": " << s << std::endl; exit( 1 ); } %} %union { Node *node; NBlock *block; NStatement *stmt; NExpression *expr; NIdentifier *ident; NVariableDeclaration *var_decl; std::vector *vars; std::string *string; ExpressionList *exprs; int token; } %token TIDENTIFIER TINTEGER %token TLPAREN TRPAREN TLBRACE TRBRACE %token TCOMMA %token TEQUAL TMUL TPLUS %type program stmts block %type ident %type numeric expr %type stmt func_decl var_decl %type func_decl_args %type call_args %type operator %left TEQUAL %left TPLUS %left TMUL %start program %% program : stmts { programBlock = $1; } ; stmts : stmt { $$ = new NBlock( ); $$->m_statements.push_back( $1 ); } | stmts stmt { $1->m_statements.push_back( $2 ); } ; stmt : var_decl { } | func_decl { } | expr { $$ = new NExpressionStatement( *$1 ); } ; func_decl : ident ident TLPAREN func_decl_args TRPAREN block { $$ = new NFunctionDeclaration( *$1, *$2, *$4, *$6 ); delete $4; } ; func_decl_args : /* procedure */ { $$ = new VariableList( ); } | var_decl { $$ = new VariableList( ); $$->push_back( $1 ); } | func_decl_args TCOMMA var_decl { $1->push_back( $3 ); } ; var_decl : ident ident { $$ = new NVariableDeclaration( *$1, *$2 ); } | ident ident TEQUAL expr { $$ = new NVariableDeclaration( *$1, *$2, $4 ); } ; expr : numeric { } | ident { $$ = $1; } | expr operator expr { $$ = new NBinaryOperator( *$1, $2, *$3 ); } | ident TLPAREN call_args TRPAREN { $$ = new NFunctionCall( *$1, *$3 ); delete $3; } ; call_args : /* no params */ { $$ = new ExpressionList( ); } | expr { $$ = new ExpressionList( ); $$->push_back( $1 ); } | call_args TCOMMA expr { $1->push_back( $3 ); } ; operator : TMUL | TPLUS ; numeric : TINTEGER { $$ = new NInteger( atoi( $1->c_str( ) ) ); delete $1; } ; block : TLBRACE /* empty block */ TRBRACE { $$ = new NBlock( ); } | TLBRACE stmts TRBRACE { $$ = $2; } ; ident : TIDENTIFIER { $$ = new NIdentifier( *$1 ); delete $1; } ; %%