質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

Q&A

解決済

2回答

3145閲覧

自作コンパイラの論理積の実現で構文エラーが出る

Rauto

総合スコア2

アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UNIX

UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

0グッド

0クリップ

投稿2021/07/21 02:48

編集2021/07/21 08:30

前提・実現したいこと

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の記述を教えていただければ幸いです.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

lex/yaccはそんなに触ったことないのであやふやな回答ですが、

case T_ANDの場所だと

syntax errror で終わっているわけですから、そこまでコードは到達しないでしょう。

|cond '&&' cond { $$ = node(T_AND, $1, $3); }

文字定数に '&&' の2文字は入れられないと思います。

&& を1つのトークンとして認識させるために、lex に && { return LOG_AND } などと入れて、*.y も相応に変更する必要があると思います。

投稿2021/07/21 03:01

int32_t

総合スコア20832

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Rauto

2021/07/21 07:36

ありがとうございました!&&をトークンとしてANDに置き換えたら思い通りに動きました.また,構文エラーを勘違いして認識していることも指摘してくださりとても助かりました.本当にありがとうございます.
guest

0

イメージ説明

全角スペース入ってます

投稿2021/07/21 02:54

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問