/* -*- C++ -*- */ %{ #include "ast.hh" using namespace ast; #include using namespace std; int yylex(void); void yyerror(char *msg); int lex_get_line (void); extern DProg *dprog; %} %union { char *str; int integer; basic_type_t basic_type; BinRel *binrel; binop_t binop; RExpr *rexpr; BExpr *bexpr; WhenExpr *when_expr; WhereExpr *where_expr; Fun *fun; Values *values; Range *range; Expr *expr; MatrixExpr *matrix; FunCallExpr *fun_call; Update *update; list *type_list; list *string_list; list *expr_list; list *rexpr_list; list *when_expr_list; list *update_list; list *decl_list; Declaration *decl; }; %type type_list %type update_list %type update %type var_list %type fun %type values %type range %type when_expr_list %type when_expr %type where_expr %type expr %type expr_list dimension_list %type bexpr %type rexpr %type rexpr_list %type binrel all_binrel %type matrix %type fun_call %type basic_type %type decl_list globals parameters locals %type declaration %type ID %type INTEGER %token ID INTEGER %token GLOBALS PARAMETERS LOCALS %token IN END %token VAL MATRIX FUN %token CHAR INT FLOAT %token WHERE WHEN TRUE %type GTE LTE '=' NEQ %left GTE LTE '=' NEQ %left AND OR %left '!' %left '+' '-' %left '*' '/' %% top: update_list WHERE rexpr_list { dprog = new DProg(lex_get_line(), new list, new list, new list, $1, $3); } | globals parameters locals IN update_list WHERE rexpr_list END { dprog = new DProg(lex_get_line(), $1, $2, $3, $5, $7); } ; globals: GLOBALS decl_list { $$ = $2; } | GLOBALS /* empty */ { $$ = new list; } | /* empty */ { $$ = new list; } ; parameters: PARAMETERS decl_list { $$ = $2; } | PARAMETERS /* empty */ { $$ = new list; } | /* empty */ { $$ = new list; } ; locals: LOCALS decl_list { $$ = $2; } | LOCALS /* empty */ { $$ = new list; } | /* empty */ { $$ = new list; } ; decl_list: declaration { $$ = new list; $$->push_front($1); } | declaration decl_list { $$ = $2; $$->push_front($1); } ; declaration: VAL ID ':' basic_type { $$ = new ValDeclaration(lex_get_line(), $2, $4); } | FUN ID '(' type_list ')' ':' basic_type { $$ = new FunDeclaration(lex_get_line(), $2, $4, $7); } | MATRIX ID '[' dimension_list ']' ':' basic_type { $$ = new MatrixDeclaration(lex_get_line(), $2, $4, $7); } ; type_list: basic_type ',' type_list { $$ = $3; $$->push_front($1); } | basic_type { $$ = new list; $$->push_front($1); } | /*empty*/ { $$ = new list; } ; dimension_list: expr { $$ = new list; $$->push_front($1); } | expr ',' dimension_list { $$ = $3; $$->push_front($1); } ; update_list: update { $$ = new list; $$->push_front($1); } | update update_list { $$ = $2; $$->push_front($1); } ; update: ID '[' var_list ']' '=' fun { $$ = new Update(lex_get_line(), TYPE_INT, $1, $3, $6); } | basic_type ID '[' var_list ']' '=' fun { $$ = new Update(lex_get_line(), $1, $2, $4, $7); } ; basic_type: CHAR { $$ = TYPE_CHAR; } | INT { $$ = TYPE_INT; } | FLOAT { $$ = TYPE_FLOAT; } ; var_list: ID { $$ = new list; $$->push_back($1); } | ID ',' var_list { $$ = $3; $$->push_front($1); } ; fun: values { $$ = $1; } | range { $$ = $1; } | expr { $$ = new SimpleFun(lex_get_line(), $1); } ; values: ID '{' when_expr_list '}' { $$ = new Values(lex_get_line(), $1, $3); } ; range: ID '{' where_expr '}' { $$ = new Range(lex_get_line(), $1, $3); } ; when_expr_list: when_expr { $$ = new list; $$->push_front($1); } | when_expr ',' when_expr_list { $$ = $3; $$->push_front($1); } ; when_expr: fun { $$ = new WhenExpr(lex_get_line(), $1); } | fun WHEN bexpr { $$ = new WhenExpr(lex_get_line(), $1, $3); } ; where_expr: fun WHERE rexpr_list { $$ = new WhereExpr(lex_get_line(), $1, $3); } ; bexpr: expr all_binrel expr { $$ = new RelBExpr(lex_get_line(), $1, $2, $3); } | bexpr AND bexpr { $$ = new ANDBExpr(lex_get_line(), $1, $3); } | bexpr OR bexpr { $$ = new ORBExpr(lex_get_line(), $1, $3); } | '(' bexpr ')' { $$ = $2; } | '!' bexpr { $$ = new NOTBExpr(lex_get_line(), $2); } | TRUE { $$ = new TrueExpr(lex_get_line()); } ; rexpr_list: rexpr { $$ = new list; $$->push_front($1); } | rexpr AND rexpr_list { $$ = $3; $$->push_front($1); } ; rexpr: expr binrel ID binrel expr { $$ = new RExpr(lex_get_line(), $1, $2, $3, $4, $5); } ; all_binrel: '=' { $$ = new BinRelEQ(lex_get_line()); } | NEQ { $$ = new BinRelNEQ(lex_get_line()); } | binrel { $$ = $1; } ; binrel: '<' { $$ = new BinRelLT(lex_get_line()); } | LTE { $$ = new BinRelLTE(lex_get_line()); } | '>' { $$ = new BinRelGT(lex_get_line()); } | GTE { $$ = new BinRelGTE(lex_get_line()); } ; expr: ID { $$ = new IDExpr(lex_get_line(), $1); } | INTEGER { $$ = new IntegerExpr(lex_get_line(), $1); } | matrix { $$ = $1; } | fun_call { $$ = $1; } | expr '+' expr { $$ = new BinOpExpr(lex_get_line(), $1, BINOP_PLUS, $3); } | expr '-' expr { $$ = new BinOpExpr(lex_get_line(), $1, BINOP_MINUS, $3);} | expr '*' expr { $$ = new BinOpExpr(lex_get_line(), $1, BINOP_MULT, $3); } | expr '/' expr { $$ = new BinOpExpr(lex_get_line(), $1, BINOP_DIV, $3); } | '(' expr ')' { $$ = $2; } | '-' expr { $$ = new NEGExpr(lex_get_line(), $2); } ; /* binop: '+' { $$ = BINOP_PLUS; } | '-' { $$ = BINOP_MINUS; } | '*' { $$ = BINOP_MULT; } | '/' { $$ = BINOP_DIV; } ; */ matrix: ID '[' expr_list ']' { $$ = new MatrixExpr(lex_get_line(), $1, $3); } ; fun_call: ID '(' ')' { $$ = new FunCallExpr(lex_get_line(), $1, new list); } | ID '(' expr_list ')' { $$ = new FunCallExpr(lex_get_line(), $1, $3); } ; expr_list: expr { $$ = new list; $$->push_back($1); } | expr ',' expr_list { $$ = $3; $$->push_front($1); } ; %% void yyerror (char *errmsg) { extern char *yytext; std::cerr << "parse error in line " << lex_get_line() << ": error before `" << yytext << "'\n"; }