tinyc.y
TINYCの構文解析
BNF記法による構文
文の列 ::= [文] 文; 文 ::= ラベル文 | int定義 | goto文 | 代入文 | if文 | while文 | do文 | out文 | halt文 ラベル文 ::= 名前; int定義 ::= int [整数定義,] 整数定義; 整数定義 ::= 名前 | 名前 = 数字列 | 名前 = - 数字列 goto文 ::= goto ラベル; if文 ::= if(式){文の列} | if(式){文の列}else{文の列} while文 ::= while(式){文} do文 ::= do{文の列}while(式) 代入文 ::= 名前 = 式; out文 ::= out(式); halt文 ::= halt;
演算子
優先順位の高い順
優先順位 | 演算子 | トークン | 結合 | |
---|---|---|---|---|
1 | ! | 右 | 論理否定 | |
1 | ~ | 右 | ビット毎の反転 | |
1 | - | NEG | 右 | 符号反転 |
2 | * | 左 | 乗算 | |
3 | + | 左 | 加算 | |
3 | - | 左 | 減算 | |
4 | << | SHL | 左 | 左シフト |
4 | >> | SHR | 左 | 右シフト |
5 | >= | GE | 左 | 大なりイコール |
5 | <= | LE | 左 | 小なりイコール |
5 | > | 左 | 大なり | |
5 | < | 左 | 小なり | |
6 | == | 左 | 等しい | |
6 | != | 左 | 等しくない | |
7 | & | 左 | ビット毎の論理積 | |
8 | ^ | 左 | ビット毎の排他的論理和 | |
9 | | | 左 | ビット毎の論理和 | |
10 | && | AND | 左 | 論理積 |
11 | || | OR | 左 | 論理和 |
ソースコード
%{ #include <stdio.h> int yylex(); int yyerror(char *s); %} %union {char *s; int n;} %token <s> NAME NUMBER %destructor { free($$); } NAME NUMBER %token <n> IF WHILE DO %type <n> if0 %token GOTO ELSE INT IN OUT HALT %left OR %left AND %left '|' %left '^' %left '&' %left EQ NE %left GE LE '<' '>' %left SHL SHR %left '+' '-' %left '*' %right '!' '~' NEG %% statements : statement | statements statement ; statement : label | intdef | goto | if | while | do | halt | out | assign ; label : NAME ':' {printf("%s:\n",$1);} ; intdef: INT intlist ';' ; intlist: integer | intlist ',' integer ; integer: NAME {printf("%s: 0\n",$1);} | NAME '=' NUMBER {printf("%s: %s\n",$1,$3);} | NAME '=' '-' NUMBER {printf("%s: -%s\n",$1,$4);} ; goto: GOTO NAME ';' {printf("\tJMP %s\n",$2);} ; if: if0 {printf("_%03dF:\n",$1);} | if0 {printf("\tJMP _%03dT\n_%03dF:\n",$1,$1);} ELSE '{' statements '}' {printf("_%03dT:\n",$1);} ; if0: IF '(' expr ')' {printf("\tJZ _%03dF\n",$1);} '{' statements '}' {$$=$1;} ; while: WHILE {printf("_%03dT:\n",$1);} '(' expr ')' {printf("\tJZ _%03dF\n",$1);} '{' statements '}' {printf("\tJMP _%03dT\n_%03dF:\n",$1,$1);} ; do: DO {printf("_%03dT:\n",$1);} '{' statements '}' WHILE '(' expr ')' ';' {printf("\tJNZ _%03dT\n",$1);} ; assign: NAME '=' expr ';' {printf("\tPOP %s\n",$1);} ; halt : HALT ';' {printf("\tHALT\n");} ; out: OUT '(' expr ')' ';' {printf("\tOUT\n");} ; expr: NAME {printf("\tPUSH %s\n",$1);} | NUMBER {printf("\tPUSHI %s\n",$1);} | IN {printf("\tIN\n");} | '!' expr {printf("\tNOT\n");} | '~' expr {printf("\tBNOT\n");} | '-' expr %prec NEG {printf("\tNEG\n");} | expr '+' expr {printf("\tADD\n");} | expr '-' expr {printf("\tSUB\n");} | expr '*' expr {printf("\tMUL\n");} | expr AND expr {printf("\tAND\n");} | expr OR expr {printf("\tOR\n");} | expr '&' expr {printf("\tBAND\n");} | expr '|' expr {printf("\tBOR\n");} | expr '^' expr {printf("\tBXOR\n");} | expr SHL expr {printf("\tSHL\n");} | expr SHR expr {printf("\tSHR\n");} | expr EQ expr {printf("\tEQ\n");} | expr NE expr {printf("\tNE\n");} | expr GE expr {printf("\tGE\n");} | expr LE expr {printf("\tLE\n");} | expr '<' expr {printf("\tLT\n");} | expr '>' expr {printf("\tGT\n");} | '(' expr ')' ; %% int yyerror(char *s){ printf("%s\n",s); } int main(){ yyparse(); }
- 注1
- 「&&」や「||」の実装は厳密にはC言語と異なる.例えば,「a && b」は,aが偽(0)なら,演算結果はbの値にかかわらず偽(0)なのでbを参照しないが,TINYCでは,bも参照する.
最終更新時間:2020年11月07日 11時38分04秒