%error-verbose %{ #include <stdio.h> #include "ast.h" extern int yylex(); IMP_ASTNode *ast_root; void yyerror(const char *s) { extern char *yytext; extern int yylineno; fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s); } %} %union { int num; char *id; struct IMP_ASTNode *node; struct IMP_ASTNodeList *node_list; } %start prog %token <num> T_NUM %token <id> T_ID %token T_EQ T_NE T_LT T_LE T_GT T_GE %token T_TRUE T_FALSE %left T_OR %left T_AND %token T_NOT %left T_PLUS T_MINUS %left T_STAR %right T_UMINUS %token T_SKIP T_END T_IF T_THEN T_ELSE T_WHILE T_DO T_VAR T_IN T_PROC T_BEGIN %token T_ASSIGN %token T_LPAREN T_RPAREN T_COM T_SEM %type <node> prog tlstm stm var aexp bexp procd procc %type <node_list> argl, varl %% prog : tlstm { ast_root = $1; } ; tlstm : T_LPAREN tlstm T_SEM tlstm T_RPAREN { $$ = imp_ast_seq($2, $4); } | tlstm T_SEM tlstm { $$ = imp_ast_seq($1, $3); } | tlstm T_SEM { $$ = $1; } | stm { $$ = $1; } | procd { $$ = $1; } stm : T_LPAREN stm T_SEM stm T_RPAREN { $$ = imp_ast_seq($2, $4); } | stm T_SEM stm { $$ = imp_ast_seq($1, $3); } | stm T_SEM { $$ = $1; } | T_SKIP { $$ = imp_ast_skip(); } | var T_ASSIGN aexp { $$ = imp_ast_assign($1, $3); } | T_IF bexp T_THEN stm T_ELSE stm T_END { $$ = imp_ast_if($2, $4, $6); } | T_IF bexp T_THEN stm T_END { $$ = imp_ast_if($2, $4, imp_ast_skip()); } | T_WHILE bexp T_DO stm T_END { $$ = imp_ast_while($2, $4); } | T_VAR var T_ASSIGN aexp T_IN stm T_END { $$ = imp_ast_let($2, $4, $6); } | procc { $$ = $1; } ; var : T_ID { $$ = imp_ast_var($1); } ; aexp : aexp T_PLUS aexp { $$ = imp_ast_aop(IMP_AST_AOP_ADD, $1, $3); } | aexp T_MINUS aexp { $$ = imp_ast_aop(IMP_AST_AOP_SUB, $1, $3); } | aexp T_STAR aexp { $$ = imp_ast_aop(IMP_AST_AOP_MUL, $1, $3); } | T_MINUS aexp %prec T_UMINUS { $$ = imp_ast_aop(IMP_AST_AOP_SUB, imp_ast_int(0), $2); } | T_LPAREN aexp T_RPAREN { $$ = $2; } | var { $$ = $1; } | T_NUM { $$ = imp_ast_int($1); } ; bexp : bexp T_OR bexp { $$ = imp_ast_bop(IMP_AST_BOP_OR, $1, $3); } | bexp T_AND bexp { $$ = imp_ast_bop(IMP_AST_BOP_AND, $1, $3); } | T_NOT bexp { $$ = imp_ast_not($2); } | aexp T_EQ aexp { $$ = imp_ast_rop(IMP_AST_ROP_EQ, $1, $3); } | aexp T_NE aexp { $$ = imp_ast_rop(IMP_AST_ROP_NE, $1, $3); } | aexp T_LE aexp { $$ = imp_ast_rop(IMP_AST_ROP_LE, $1, $3); } | aexp T_LT aexp { $$ = imp_ast_rop(IMP_AST_ROP_LT, $1, $3); } | aexp T_GE aexp { $$ = imp_ast_rop(IMP_AST_ROP_GE, $1, $3); } | aexp T_GT aexp { $$ = imp_ast_rop(IMP_AST_ROP_GT, $1, $3); } | T_LPAREN bexp T_RPAREN { $$ = $2; } | T_TRUE { $$ = imp_ast_rop(IMP_AST_ROP_EQ, imp_ast_int(1), imp_ast_int(1)); } | T_FALSE { $$ = imp_ast_rop(IMP_AST_ROP_EQ, imp_ast_int(0), imp_ast_int(1)); } ; argl : aexp { $$ = imp_ast_list($1, NULL); } | argl T_COM aexp { $$ = imp_ast_list($3, $1); } ; varl : var { $$ = imp_ast_list($1, NULL); } | argl T_COM var { $$ = imp_ast_list($3, $1); } ; procd : T_PROC T_ID T_LPAREN varl T_SEM varl T_RPAREN T_BEGIN stm T_END { $$ = imp_ast_procdecl($2, $4, $6, $9); } ; procc : T_ID T_LPAREN argl T_SEM varl T_RPAREN { $$ = imp_ast_proccall($1, $3, $5); } ; %%