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

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

新規登録して質問してみよう
ただいま回答率
85.45%
C

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

コンパイラ

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

Q&A

1回答

1259閲覧

C自作コンパイラ do-while構文規則(C, yacc, lex)

j0ker_9

総合スコア1

C

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

コンパイラ

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

0グッド

0クリップ

投稿2022/07/03 01:51

Cの自作コンパイラにおいてdo-while文を実装したいのですが、syntax errorになってしまいます。以下のコードのdo-while文においてどのように修正すればよいか教えていただきたいです。以下に関連ファイルを載せておきます。

yacc

1%token NUM; 2%token IDENT; 3%token READ; 4%token PRINT; 5%token WHILE; 6%token IF; 7%token DO; 8%left '+' '-'; 9%left '*' '/'; 10%% 11 12prog : IDENT '{' stlist'}' { dotree($3); return 0; } 13; 14stlist : { $$ = 0; } 15| stlist stat { $$ = node(T_STLIST, $1, $2); } 16; 17stat :var '=' expr ';' { $$ = node(T_ASSIGN, $1, $3); } 18| READ var ';' { $$ = node(T_READ, $2, 0); } 19| PRINT expr ';' { $$ = node(T_PRINT, $2, 0); } 20| WHILE '(' cond ')' stat { $$ = node(T_WHILE, $3, $5); } 21| IF '(' cond ')' stat { $$ = node(T_IF, $3, $5); } 22| DO '{' expr '}' stat { $$ = node(T_DO, $3, $5); }  // do-whileを表現する構文規則 23| '{' stlist '}' { $$ = $2; } 24; 25cond : expr '<' expr { $$ = node(T_LT, $1, $3); } 26| expr '>' expr { $$ = node(T_GT, $1, $3); } 27; 28expr : term { $$ = $1; } 29| expr '+' term { $$ = node(T_ADD, $1, $3); } 30| expr '-' term { $$ = node(T_SUB, $1, $3); } 31; 32term: prim{ $$ = $1; } 33| term '*' prim { $$ = node(T_MUL, $1, $3); } 34| term '/' prim { $$ = node(T_DIV, $1, $3); } 35| term '%' prim { $$ = node(T_REM, $1, $3); } 36; 37prim : NUM { $$ = node(T_NUM, atoi(yytext), 0); } 38| var { $$ = node(T_VAR, $1, 0); } 39| '(' expr ')' { $$ = $2; } 40; 41var : IDENT { $$ = lookup(yytext); } 42;

test.uec

1main { 2 read x; 3 i = 0; 4 do{ // ここのdo-whileを実装したいです。 5 i = i + x; 6 x = x - 1; 7 }while(x > 0); 8 print i;

lex

1alpha [a-zA-Z] 2digit [0-9] 3white [\n\t ] 4%% 5while { return WHILE; } 6if { return IF; } 7do { return DO; } // ここも正しいか不明 8read { return READ; } 9print { return PRINT; } 10{alpha}({alpha}|{digit})* { return IDENT; } 11{digit}+ { return NUM; } 12[-+()=;{}<>*/%] { return yytext[0]; } 13{white} { ; }

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

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

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

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

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

actorbug

2022/07/03 07:16

試せる環境がないので、間違っていたらすみません。 | DO stat WHILE '(' cond ')' ';' { $$ = node(T_DO, $5, $2); }  // do-whileを表現する構文規則
j0ker_9

2022/07/03 07:53

actorbugさんの通りにするとyaccのコンパイルエラーが解消されました! しかし、まだdo-whileを実行できません。おそらく以下のCコードに問題があるのですが、どこが問題かわかりますでしょうか?? ちなみにwhileは正常に動きますので、whileと一緒に掲載します。 --------------------------------------- case T_WHILE: l = labelno++;  //ラベル更新 printf(".L%d:\n", l);  // ラベル l を生成 emittree(ntab[i].left);  // 条件文の判定 printf(".L%d\n", l+1);  // 条件を満たさなかったら l+1 のラベルに移動 emittree(ntab[i].right);  // while文の中身を実行 printf("jmp .L%d\n", l);  // ラベル l に移動 printf(".L%d:\n", l+1);  // ラベル l+1 を生成 break; case T_DO: l = labelno++;  // ラベルを更新 printf(".L%d:\n", l);  // ラベル l を生成 emittree(ntab[i].right);  // doの部分を実行 emittree(ntab[i].left);  // whileの条件文を実行 break;  // 条件を満たさなかったら終了 printf("jmp .L%d\n", l);  // ラベル l に移動 } ----------------------------------- 長文失礼しました。問題点がわかりそうでしたら指摘をお願いいたします。
actorbug

2022/07/03 13:42 編集

正直コード生成系はさっぱりですが、emittree(ntab[i].left);直後にbreakしたら駄目なのは分かります。 現在実行中のコードと生成中のコードの区別がついていないのではないでしょうか。
actorbug

2022/07/03 20:57

yaccの記述も、どういう理屈で解釈されるか「理解」できていれば簡単に書けたはずです。 case T_DO:についても、case T_WHILE:の動作原理を「理解」できていれば簡単に書けます。 他人に頼っていたら、いつまでたっても自力で書けるようにはなりません。 まずはT_WHILEを本当の意味で「理解」できるよう努力することをお勧めします。
j0ker_9

2022/07/04 02:05

T_WHILEは上記のコメントで動作を正しく説明できていると考えています。T_WHILEの本当の意味はコメントの内容とは違うのでしょうか?
guest

回答1

0

質問の修正依頼のコメントにコードを書くのではなく、
質問を編集してコードを追記してください。
というよりも、main のファイル全体を省略せず質問に入れてください。

さて、do-while は次のようにしてできるはずですが、理解できますか?

C

1 case T_WHILE: l = labelno++; // ラベル番号更新 2 labelno++; 3 printf(".L%d:\n", l); // ラベル l 生成 4 emittree(ntab[i].left); // 分岐条件判定 5 printf(".L%d\n", l+1); // 不成立なら l+1に移動 6 emittree(ntab[i].right); // 成立していたら、中身を実行 7 printf(" jmp .L%d\n", l); // 前のラベル l に戻る 8 printf(".L%d:\n", l+1); // ラベル l+1 生成 9 break; 10 case T_DO: l = labelno++; // ラベルを更新 11 labelno++; 12 printf(".L%d:\n", l); // ラベル l を生成 13 emittree(ntab[i].left); // doの部分を実行 14 emittree(ntab[i].right); // whileの条件文を実行 15 printf(".L%d\n", l+1); // 不成立なら l+1に移動 16 printf(" jmp .L%d\n", l); // 前のラベル l に戻る 17 printf(".L%d:\n", l+1); // ラベル l+1 を生成 18 break;

投稿2022/07/19 13:55

kazuma-s

総合スコア8224

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問