トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

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秒