%{ #include #include #include "syntax_tree.h" #include "debug.h" /* defined in lexer.l -> lexer.c */ extern int yylex(); /* defined in syntax_tree.c */ extern Tree mkNode(int, Tree, Tree); extern Tree mkNode3(int, Tree, Tree, Tree); /* defined in bind.c */ extern Tree bindObj(Tree); /* defined in code.c */ extern void initial_code(); extern void code(Tree); /* defined in debug.c */ extern int Mode; extern Tree putTree(int, Tree); #define PutTree(t) putTree(0,t) /* main routine */ main(int argc, char *argv[]) { for (; argc>0; argc--) { if (strcmp(argv[argc-1],"syntax")==0) Mode |= SYNTAX; if (strcmp(argv[argc-1],"semantics")==0) Mode |= SEMANTICS; if (strcmp(argv[argc-1],"optimize")==0) Mode |= OPTIMIZE; } initial_code(); yyparse(); } void yyerror(char *str) { fprintf(stderr,"%s\n", str); } %} %start prog /* tokens for node name */ /* (not used in syntax rules but in mkNode function) */ %token FUNC_DEF GVAR_DECL LVAR_DECL SCALAR ARRAY %token LIST EXP FUNC_CALL ARR_REF /* reserved word */ %token VAR RETURN IF ELSE WHILE /* literals */ %token SYM NUM STR /* operators */ %right '=' %left '|' %left '^' %left '&' %right '~' %nonassoc EQEQ EXEQ %nonassoc '<' LTEQ '>' GTEQ %left '+' '-' %left '*' '/' %right UMINUS %nonassoc '[' %% prog: ext_defs ; ext_defs: ext_defs ext_def { if (Mode & SEMANTICS) PutTree(bindObj($2)); else if (Mode & SYNTAX) PutTree($2); else { code(bindObj($2)); } } | /* empty */ ; ext_def: var_decl { $$=mkNode(GVAR_DECL,$1,NUL); } | func_def { $$=$1; } ; var_decl: VAR vars ';' { $$=$2; } ; vars: var_item ',' vars { $$=mkNode(LIST,$1,$3); } | var_item { $$=mkNode(LIST,$1,NUL); } ; var_item: SYM { $$=mkNode(SCALAR,$1,NUL); } | SYM '[' NUM ']' { $$=mkNode(ARRAY,$1,$3); } ; func_def: SYM '(' args ')' stmt { $$=mkNode3(FUNC_DEF,$1,$3,$5); } | SYM '(' ')' stmt { $$=mkNode3(FUNC_DEF,$1,NUL,$4); } ; args: SYM ',' args { $$=mkNode(LIST,$1,$3); } | SYM { $$=mkNode(LIST,$1,NUL); } ; stmt: ';' { $$=NUL; } | var_decl { $$=mkNode(LVAR_DECL,$1,NUL); } | exp ';' { $$=mkNode(EXP,$1,NUL); } | RETURN exp ';' { $$=mkNode(RETURN,$2,NUL); } | RETURN ';' { $$=mkNode(RETURN,NUL,NUL); } | '{' stmts '}' { $$=$2; } | IF '(' exp ')' stmt { $$=mkNode3(IF,$3,$5,NUL); } | IF '(' exp ')' stmt ELSE stmt { $$=mkNode3(IF,$3,$5,$7); } | WHILE '(' exp ')' stmt { $$=mkNode(WHILE,$3,$5); } ; stmts: stmt stmts { $$=mkNode(LIST,$1,$2); } | /* empty */ { $$=NUL; } ; exp: SYM '=' exp { $$=mkNode('=',mkNode(SCALAR,$1,NUL),$3); } | SYM '[' exp ']' '=' exp { $$=mkNode('=',mkNode(ARRAY,$1,$3),$6); } | exp '|' exp { $$=mkNode('|',$1,$3); } | exp '^' exp { $$=mkNode('^',$1,$3); } | exp '&' exp { $$=mkNode('&',$1,$3); } | '~' exp { $$=mkNode('~',$2,NUL); } | exp EQEQ exp { $$=mkNode(EQEQ,$1,$3); } | exp EXEQ exp { $$=mkNode(EXEQ,$1,$3); } | exp '<' exp { $$=mkNode('<',$1,$3); } | exp LTEQ exp { $$=mkNode(LTEQ,$1,$3); } | exp '>' exp { $$=mkNode('>',$1,$3); } | exp GTEQ exp { $$=mkNode(GTEQ,$1,$3); } | exp '+' exp { $$=mkNode('+',$1,$3); } | exp '-' exp { $$=mkNode('-',$1,$3); } | exp '*' exp { $$=mkNode('*',$1,$3); } | exp '/' exp { $$=mkNode('/',$1,$3); } | '-' exp %prec UMINUS { $$=mkNode(UMINUS,$2,NUL); } | SYM '[' exp ']' { $$=mkNode(ARR_REF,$1,$3);} | SYM '(' exps ')' { $$=mkNode(FUNC_CALL,$1,$3); } | SYM '(' ')' { $$=mkNode(FUNC_CALL,$1,NUL); } | '(' exp ')' { $$=$2; } | SYM { $$=$1; } | NUM { $$=$1; } | STR { $$=$1; } ; exps: exp ',' exps { $$=mkNode(LIST,$1,$3); } | exp { $$=mkNode(LIST,$1,NUL); } ; %%