トップ 一覧 検索 ヘルプ 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も参照する.