/* 構文解析器の定義 (yacc -d -o qc.c qc.y で qc.c を生成する) */ %{ #include #include #include "tree.h" /* yylex.l (yylex.c) で定義 */ extern int lineNo; /* 行番号,エラーメッセージで使用する */ /* stringf.c で定義 */ void freeStrings(); /* Stringf() で確保された文字列領域を全て開放 */ /* tree.c で定義 */ Node mkNode(int type, Node left, Node right); /* ノードの生成 */ void putTree(Node tree); /* 構文木の表示 */ /* bind.c で定義 */ void bindObj(Node tree); /* 意味解析 */ void putObjs(void); /* オブジェクト構造体スタックの表示 */ void popLocals(void); /* 局所オブジェクトの解放 */ /* asm.c で定義 */ void putCode(void); /* コードの出力 */ void genStrings(void); /* 文字列定数の生成 */ /* code.c で定義 */ void initCode(void); /* 初期コードの生成 */ void genCode(Node tree); /* コード生成 */ /* optimize.c で定義 */ void optCode(void); /* コードの最適化 */ /* プロトタイプ宣言 */ void procGloDef(Node tree); /* glo_def の処理 */ /* 実行モード */ int mode = 3; /* 1:構文解析まで, 2:意味解析まで,*/ /* 3:コード生成まで, 4:最適化まで */ %} /* 出発記号 */ %start prog /* トークンの定義 */ /* 予約語 */ %token VAR RETURN IF ELSE WHILE /* 演算子 (下のものほど優先順位が高い) */ %right '=' /* = */ %left BRBR /* || */ %left AMAM /* && */ %nonassoc EQEQ EXEQ /* ==, != */ %nonassoc '<' LTEQ '>' GTEQ /* <, <=, >, >= */ %left '+' '-' /* +, - */ %left '*' '/' /* *, / */ %right '!' UMINUS /* !, (単項の)- */ /* 区切り記号 */ /* ',' ';' '(' ')' '[' ']' '{' '}' */ /* 記号とリテラル */ %token SYM NUM STR /* 記号,数値,文字列 */ /* 中間ノードのタイプにのみ使用するトークン */ /* (字句要素のタイプ (yylex() の戻り値) としては使用しない) */ /* 関数定義,関数呼出,大域変数,局所変数,単純変数,配列 */ %token Fdef Func Gvar Lvar Sclr Arry %% prog: glo_defs ; glo_defs: glo_defs glo_def { procGloDef($2); } | /* 空 */ ; glo_def: var_decl { $$ = mkNode(Gvar, $1, NUL); } | func_def { $$ = $1; } ; var_decl: VAR vars ';' { $$ = $2; } ; vars: var_item ',' vars { $$ = mkNode(',', $1, $3); } | var_item { $$ = mkNode(',', $1, NUL); } ; var_item: SYM { $$ = mkNode(Sclr, $1, NUL); } | SYM '[' NUM ']' { $$ = mkNode(Arry, $1, $3); } ; func_def: SYM '(' args ')' stmt { $$ = mkNode(Fdef, mkNode(Func, $1, $3), $5); } | SYM '(' ')' stmt { $$ = mkNode(Fdef, mkNode(Func, $1, NUL), $4);} ; args: SYM ',' args { $$ = mkNode(',', $1, $3); } | SYM { $$ = mkNode(',', $1, NUL); } ; stmt: ';' { $$ = NUL; } | var_decl { $$ = mkNode(Lvar, $1, NUL); } | exp ';' { $$ = $1; } | RETURN exp ';' { $$ = mkNode(RETURN, $2, NUL); } | RETURN ';' { $$ = mkNode(RETURN, NUL, NUL); } | '{' stmts '}' { $$ = $2; } | IF '(' exp ')' stmt { $$ = mkNode(IF, $3, mkNode(ELSE, $5, NUL)); } | IF '(' exp ')' stmt ELSE stmt { $$ = mkNode(IF, $3, mkNode(ELSE, $5, $7)); } | WHILE '(' exp ')' stmt { $$ = mkNode(WHILE, $3, $5); } ; stmts: stmt stmts { $$ = mkNode(',', $1, $2); } | /* empty */ { $$ = NUL; } ; exp: SYM '=' exp { $$ = mkNode('=', mkNode(Sclr, $1, NUL), $3); } | SYM '[' exp ']' '=' exp { $$ = mkNode('=', mkNode(Arry, $1, $3), $6); } | exp BRBR exp { $$ = mkNode(BRBR, $1, $3); } | exp AMAM exp { $$ = mkNode(AMAM, $1, $3); } | 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 { $$ = mkNode('!', $2, NUL); } | '-' exp %prec UMINUS { $$ = mkNode(UMINUS, $2, NUL); } | SYM '(' exps ')' { $$ = mkNode(Func, $1, $3); } | SYM '(' ')' { $$ = mkNode(Func, $1, NUL); } | SYM '[' exp ']' { $$ = mkNode(Arry, $1, $3); } | SYM { $$ = mkNode(Sclr, $1, NUL); } | NUM { $$ = $1; } | STR { $$ = $1; } | '(' exp ')' { $$ = $2; } ; exps: exp ',' exps { $$ = mkNode(',', $1, $3); } | exp { $$ = mkNode(',', $1, NUL); } ; %% /* メインルーチン */ main(int argc, char *argv[]) { int i; for (i=0; i='1' && *(argv[i]+1)<='4') mode = *(argv[i]+1) - '0'; } if (mode >= 3) initCode(); yyparse(); if (mode >= 3) { genStrings(); /* 文字列定数の生成 */ if (mode >= 4) optCode(); /* コードの最適化 */ putCode(); /* コードの出力 */ } freeStrings(); /* Stringf() で確保された文字列領域を全て開放 */ exit(0); } /* glo_def の処理 */ void procGloDef(Node t) { if (mode <= 1) putTree(t); /* 構文解析結果の出力 */ else { bindObj(t); /* 意味解析 */ if (mode <= 2) { putTree(t); putObjs(); } /* 意味解析結果の出力 */ else genCode(t); /* コード生成 */ popLocals(); /* 局所Objectの解放 */ } } /* エラー処理.yyparse() の中から呼び出される */ yyerror(char *str) { fprintf(stderr,"line %d: %s\n", lineNo, str); freeStrings(); /* Stringf() で確保された文字列領域を全て開放 */ exit(1); }