前提・実現したいこと
lexとyaccを用いてc言語でコンパイラを作っています.今,条件式の論理積(&&)の機能を実装しようとしています.
しかし,構文エラーが出ます.エラーメッセージが構文エラーだけなので,どこが間違っているかの確認ができず困っています.
発生している問題・エラーメッセージ
$ ./abcc < test5.abc > test5.s syntax error
該当のソースコード
/*test5.abc*/ main { read x; read y; if(x > 0 && y > 0) { print x; } print y; }
lex
1alpha [a-zA-Z] 2digit [0-9] 3white [\n\t ] 4%% 5if { return IF; } 6read { return READ; } 7print { return PRINT; } 8{alpha}({alpha}|{digit})* { return IDENT; } 9{digit}+ { return NUM; } 10[-+()=;{}<>*/%&] { return yytext[0]; } /*新しく&を追加*/ 11{white} { ; } 12
yacc
1%token NUM; 2%token IDENT; 3%token READ; 4%token PRINT; 5%token DOWHILE; 6%token WHILE; 7%token IF; 8%% 9prog : IDENT '{' stlist '}' { dotree($3); return 0; } 10; 11stlist : { $$ = 0; } 12 |stlist stat { $$ = node(T_STLIST, $1, $2); } 13 ; 14stat : var '=' expr ';' { $$ = node(T_ASSIGN, $1, $3); } 15 | READ var ';' { $$ = node(T_READ, $2, 0); } 16 |PRINT expr ';' { $$ = node(T_PRINT, $2, 0); } 17 |IF '(' log ')' stat { $$ = node(T_IF, $3, $5); } 18 | '{' stlist '}' { $$ = $2; } 19 ; 20 21/*以下のlogを新たに追加*/ 22log : cond { $$ = $1; } 23 |cond '&&' cond { $$ = node(T_AND, $1, $3); } 24 ; 25 26 27cond : expr '<' expr { $$ = node(T_LT, $1, $3); } 28 |expr '>' expr { $$ = node(T_GT, $1, $3); } 29 ; 30expr : term { $$ = $1; } 31 | expr '+' term { $$ = node(T_ADD, $1, $3); } 32 | expr '-' term { $$ = node(T_SUB, $1, $3); } 33 ; 34term : prim { $$ = $1; } 35 | term '*' prim { $$ = node(T_MUL, $1, $3); } 36 | term '/' prim { $$ = node(T_DIV, $1, $3); } 37 | term '%' prim { $$ = node(T_REM, $1, $3); } 38 ; 39prim : NUM { $$ = node(T_NUM, atoi(yytext), 0); } 40 | var { $$ = node(T_VAR, $1, 0); } 41 | '(' expr ')' { $$ = $2; } 42 ; 43var : IDENT { $$ = lookup(yytext); } 44; 45
c
1#include <stdio.h> 2 3struct stab { 4 int val; 5 char name[20]; } stab[100]; 6 7int stabuse = 0; 8 9struct node { 10 int type, left, right; } ntab[400]; 11int ntabuse = 1; 12 13#define T_STLIST 1 14#define T_ASSIGN 2 15#define T_READ 3 16#define T_PRINT 4 17#define T_ADD 5 18#define T_SUB 6 19#define T_MUL 7 20#define T_DIV 8 21#define T_REM 9 22#define T_NUM 10 23#define T_VAR 11 24#define T_IF 13 25#define T_LT 14 26#define T_GT 15 27#define T_AND 17 /*ANDを追加*/ 28 29int lookup(char*); 30int node(int, int, int); 31void dotree(int); 32extern char *yytext; 33 34#include "y.tab.c" 35#include "lex.yy.c" 36 37int main() { 38 yyparse(); 39 return 0; 40 41} 42 43int lookup(char *s) { 44 45 int i; 46 for(i = 0; i < stabuse; ++i) 47 if(strcmp(stab[i].name, s) == 0) return i; 48 if(stabuse >= 99) { 49 printf("table overflow.\n"); exit(1); } 50 strcpy(stab[stabuse].name, s); return stabuse++; 51} 52 53int node(int t, int l, int r) { 54 int i = ntabuse++; 55 ntab[i].type = t; 56 ntab[i].left = l; 57 ntab[i].right = r; 58 return i; 59} 60 61void dotree(int i) { 62 63 int stk; 64 65 printf(" .section .rodata\n"); 66 printf(".Lprompt: .string\"> \"\n"); /* プロンプト */ 67 printf(".Lread: .string\"%%ld\"\n"); /* 読み取り用書式 */ 68 printf(".Lprint: .string\"%%ld\n\"\n"); /* 書き出し用書式 */ 69 printf(" .text\n"); 70 printf(".global main\n"); 71 printf("main:\n"); 72 printf(" pushq %%rbp\n"); 73 printf(" movq %%rsp,%%rbp\n"); 74 stk = (8*stabuse + 15) / 16; /* 変数の個数*8 で 16 の倍数へ切り上げ */ 75 stk *= 16; 76 printf(" subq $%d,%%rsp\n", stk); 77 emittree(i); 78 printf(" leave\n"); 79 printf(" ret\n"); 80 81} 82 83 84void emittree(int i) { 85 static int labelno = 1; 86 int l; 87 switch(ntab[i].type) { 88 case T_STLIST: if(ntab[i].left) emittree(ntab[i].left); 89 emittree(ntab[i].right); 90 break; 91 case T_READ: printf(" movq $.Lprompt,%%rdi\n"); 92 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 93 printf(" call printf\n"); 94 printf(" leaq %d(%%rbp),%%rsi\n", -(ntab[i].left+1)*8); 95 printf(" movq $.Lread,%%rdi\n"); 96 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 97 printf(" call scanf\n"); 98 break; 99 case T_PRINT: emittree(ntab[i].left); 100 printf(" popq %%rsi\n"); 101 printf(" movq $.Lprint,%%rdi\n"); 102 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 103 printf(" call printf\n"); 104 break; 105 case T_NUM: printf(" pushq $%d\n", ntab[i].left); 106 break; 107 case T_VAR: printf(" pushq %d(%%rbp)\n", -(ntab[i].left+1)*8); 108 break; 109 case T_ASSIGN: emittree(ntab[i].right); 110 printf(" popq %d(%%rbp)\n", -(ntab[i].left+1)*8); 111 break; 112 case T_ADD: emittree(ntab[i].left); 113 emittree(ntab[i].right); 114 printf(" popq %%rdx\n"); 115 printf(" popq %%rax\n"); 116 printf(" addq %%rdx,%%rax\n"); 117 printf(" pushq %%rax\n"); 118 break; 119 case T_MUL: emittree(ntab[i].left); 120 emittree(ntab[i].right); 121 printf(" popq %%rdx\n"); 122 printf(" popq %%rax\n"); 123 printf(" imulq %%rdx\n"); 124 printf(" pushq %%rax\n"); 125 break; 126 case T_SUB: emittree(ntab[i].left); 127 emittree(ntab[i].right); 128 printf(" popq %%rdx\n"); 129 printf(" popq %%rax\n"); 130 printf(" subq %%rdx,%%rax\n"); 131 printf(" pushq %%rax\n"); 132 break; 133 case T_DIV: emittree(ntab[i].left); 134 emittree(ntab[i].right); 135 printf(" popq %%rcx\n"); 136 printf(" popq %%rax\n"); 137 printf(" movq $0,%%rdx\n"); 138 printf(" idivq %%rcx\n"); 139 printf(" pushq %%rax\n"); 140 break; 141 case T_REM: emittree(ntab[i].left); 142 emittree(ntab[i].right); 143 printf(" popq %%rcx\n"); 144 printf(" popq %%rax\n"); 145 printf(" movq $0,%%rdx\n"); 146 printf(" idivq %%rcx\n"); 147 printf(" pushq %%rdx\n"); 148 break; 149 case T_LT: emittree(ntab[i].left); 150 emittree(ntab[i].right); 151 printf(" popq %%rcx\n"); 152 printf(" popq %%rax\n"); 153 printf(" cmp %%rcx,%%rax\n"); 154 printf(" jge "); 155 break; 156 case T_GT: emittree(ntab[i].left); 157 emittree(ntab[i].right); 158 printf(" popq %%rcx\n"); 159 printf(" popq %%rax\n"); 160 printf(" cmp %%rcx, %%rax\n"); 161 printf(" jle "); 162 break; 163 164/*実装中の論理積*/ 165 case T_AND:l = labelno++; /*ラベルの数を増やして用意しておく*/ 166 167 printf(" movq $0,%%rdx\n"); /*後に比較に使うのでとりあえず0をrdxにいれておく*/ 168 169 emittree(ntab[i].left); /*左の比較式を判定*/ 170 printf(".L%d\n", l); /*上のT_LTおよびT_GTは失敗するとジャンプ記号を出力するので,出力先のラベルlを出力*/ 171 172 emittree(ntab[i].right); /*右の比較式も同様*/ 173 printf(".L%d\n", l); 174 175 printf(" movq $.Lprint,%%rdx\n"); /*一度も失敗しなかった場合ここにくる*/ 176 /*ここで適当にrdxに0以外の数を渡す*/ 177 178 printf(".L%d:\n", l); /*一度でも失敗したらここにジャンプ*/ 179 printf(" cmp $0, %%rdx\n"); /*rdxと0を比較 ANDが不成立の場合一致する.*/ 180 printf(" je "); /*一緒ならジャンプ ラベルはT_IFやT_WHILEで設定する*/ 181 break; 182 183 184 case T_IF: l = labelno++; 185 emittree(ntab[i].left); 186 printf(".L%d\n", l); 187 emittree(ntab[i].right); 188 printf(".L%d:\n", l); 189 break; 190 191 192 193 default: printf("NotImplemented: %d\n", ntab[i].type); 194 break; 195 196 197 } 198} 199
試したこと
$ yacc t22.yacc $ lex t22.lex $ cc -o abcc t24.c -ll -ly $ ./abcc < test5.abc > test5.s syntax error
となります.これ以前に実装した他の部分は正常に動きました.例えば,if文のtest4.abc
main { read x; if(x > 0) { print 1;} }
を実行した場合,
$ ./abcc < test4.abc > test4.s $ cc test4.s $ ./a.out > 5 1 $ ./a.out > -5 $
正常に動作します.このため,間違っているのはc言語のemittree関数内のcase T_ANDの場所だと考えているのですが,何故構文エラーになるのかが分かりません.構文エラーの原因,もしくはT_ABCの記述を教えていただければ幸いです.
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/21 07:36