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

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

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

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

C

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

UNIX

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

コンパイラ

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

解決済

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

Rauto
Rauto

総合スコア2

アセンブリ言語

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

C

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

UNIX

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

コンパイラ

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

2回答

0リアクション

0クリップ

1793閲覧

投稿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

alpha [a-zA-Z] digit [0-9] white [\n\t ] %% if { return IF; } read { return READ; } print { return PRINT; } {alpha}({alpha}|{digit})* { return IDENT; } {digit}+ { return NUM; } [-+()=;{}<>*/%&] { return yytext[0]; } /*新しく&を追加*/ {white} { ; }

yacc

%token NUM; %token IDENT; %token READ; %token PRINT; %token DOWHILE; %token WHILE; %token IF; %% prog : IDENT '{' stlist '}' { dotree($3); return 0; } ; stlist : { $$ = 0; } |stlist stat { $$ = node(T_STLIST, $1, $2); } ; stat : var '=' expr ';' { $$ = node(T_ASSIGN, $1, $3); } | READ var ';' { $$ = node(T_READ, $2, 0); } |PRINT expr ';' { $$ = node(T_PRINT, $2, 0); } |IF '(' log ')' stat { $$ = node(T_IF, $3, $5); } | '{' stlist '}' { $$ = $2; } ; /*以下のlogを新たに追加*/ log : cond { $$ = $1; } |cond '&&' cond { $$ = node(T_AND, $1, $3); } ; cond : expr '<' expr { $$ = node(T_LT, $1, $3); } |expr '>' expr { $$ = node(T_GT, $1, $3); } ; expr : term { $$ = $1; } | expr '+' term { $$ = node(T_ADD, $1, $3); } | expr '-' term { $$ = node(T_SUB, $1, $3); } ; term : prim { $$ = $1; } | term '*' prim { $$ = node(T_MUL, $1, $3); } | term '/' prim { $$ = node(T_DIV, $1, $3); } | term '%' prim { $$ = node(T_REM, $1, $3); } ; prim : NUM { $$ = node(T_NUM, atoi(yytext), 0); } | var { $$ = node(T_VAR, $1, 0); } | '(' expr ')' { $$ = $2; } ; var : IDENT { $$ = lookup(yytext); } ;

c

#include <stdio.h> struct stab { int val; char name[20]; } stab[100]; int stabuse = 0; struct node { int type, left, right; } ntab[400]; int ntabuse = 1; #define T_STLIST 1 #define T_ASSIGN 2 #define T_READ 3 #define T_PRINT 4 #define T_ADD 5 #define T_SUB 6 #define T_MUL 7 #define T_DIV 8 #define T_REM 9 #define T_NUM 10 #define T_VAR 11 #define T_IF 13 #define T_LT 14 #define T_GT 15 #define T_AND 17 /*ANDを追加*/ int lookup(char*); int node(int, int, int); void dotree(int); extern char *yytext; #include "y.tab.c" #include "lex.yy.c" int main() { yyparse(); return 0; } int lookup(char *s) { int i; for(i = 0; i < stabuse; ++i) if(strcmp(stab[i].name, s) == 0) return i; if(stabuse >= 99) { printf("table overflow.\n"); exit(1); } strcpy(stab[stabuse].name, s); return stabuse++; } int node(int t, int l, int r) { int i = ntabuse++; ntab[i].type = t; ntab[i].left = l; ntab[i].right = r; return i; } void dotree(int i) { int stk; printf(" .section .rodata\n"); printf(".Lprompt: .string\"> \"\n"); /* プロンプト */ printf(".Lread: .string\"%%ld\"\n"); /* 読み取り用書式 */ printf(".Lprint: .string\"%%ld\n\"\n"); /* 書き出し用書式 */ printf(" .text\n"); printf(".global main\n"); printf("main:\n"); printf(" pushq %%rbp\n"); printf(" movq %%rsp,%%rbp\n"); stk = (8*stabuse + 15) / 16; /* 変数の個数*8 で 16 の倍数へ切り上げ */ stk *= 16; printf(" subq $%d,%%rsp\n", stk); emittree(i); printf(" leave\n"); printf(" ret\n"); } void emittree(int i) { static int labelno = 1; int l; switch(ntab[i].type) { case T_STLIST: if(ntab[i].left) emittree(ntab[i].left); emittree(ntab[i].right); break; case T_READ: printf(" movq $.Lprompt,%%rdi\n"); printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ printf(" call printf\n"); printf(" leaq %d(%%rbp),%%rsi\n", -(ntab[i].left+1)*8); printf(" movq $.Lread,%%rdi\n"); printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ printf(" call scanf\n"); break; case T_PRINT: emittree(ntab[i].left); printf(" popq %%rsi\n"); printf(" movq $.Lprint,%%rdi\n"); printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ printf(" call printf\n"); break; case T_NUM: printf(" pushq $%d\n", ntab[i].left); break; case T_VAR: printf(" pushq %d(%%rbp)\n", -(ntab[i].left+1)*8); break; case T_ASSIGN: emittree(ntab[i].right); printf(" popq %d(%%rbp)\n", -(ntab[i].left+1)*8); break; case T_ADD: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rdx\n"); printf(" popq %%rax\n"); printf(" addq %%rdx,%%rax\n"); printf(" pushq %%rax\n"); break; case T_MUL: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rdx\n"); printf(" popq %%rax\n"); printf(" imulq %%rdx\n"); printf(" pushq %%rax\n"); break; case T_SUB: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rdx\n"); printf(" popq %%rax\n"); printf(" subq %%rdx,%%rax\n"); printf(" pushq %%rax\n"); break; case T_DIV: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rcx\n"); printf(" popq %%rax\n"); printf(" movq $0,%%rdx\n"); printf(" idivq %%rcx\n"); printf(" pushq %%rax\n"); break; case T_REM: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rcx\n"); printf(" popq %%rax\n"); printf(" movq $0,%%rdx\n"); printf(" idivq %%rcx\n"); printf(" pushq %%rdx\n"); break; case T_LT: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rcx\n"); printf(" popq %%rax\n"); printf(" cmp %%rcx,%%rax\n"); printf(" jge "); break; case T_GT: emittree(ntab[i].left); emittree(ntab[i].right); printf(" popq %%rcx\n"); printf(" popq %%rax\n"); printf(" cmp %%rcx, %%rax\n"); printf(" jle "); break; /*実装中の論理積*/ case T_AND:l = labelno++; /*ラベルの数を増やして用意しておく*/   printf(" movq $0,%%rdx\n"); /*後に比較に使うのでとりあえず0をrdxにいれておく*/   emittree(ntab[i].left); /*左の比較式を判定*/ printf(".L%d\n", l); /*上のT_LTおよびT_GTは失敗するとジャンプ記号を出力するので,出力先のラベルlを出力*/   emittree(ntab[i].right); /*右の比較式も同様*/ printf(".L%d\n", l);   printf(" movq $.Lprint,%%rdx\n"); /*一度も失敗しなかった場合ここにくる*/ /*ここで適当にrdxに0以外の数を渡す*/ printf(".L%d:\n", l); /*一度でも失敗したらここにジャンプ*/ printf(" cmp $0, %%rdx\n"); /*rdxと0を比較 ANDが不成立の場合一致する.*/ printf(" je "); /*一緒ならジャンプ ラベルはT_IFやT_WHILEで設定する*/ break; case T_IF: l = labelno++; emittree(ntab[i].left); printf(".L%d\n", l); emittree(ntab[i].right); printf(".L%d:\n", l); break; default: printf("NotImplemented: %d\n", ntab[i].type); break; } }

試したこと

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

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

アセンブリ言語

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

C

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

UNIX

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

コンパイラ

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