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

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

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

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

コンパイラ

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

Q&A

解決済

1回答

1215閲覧

C言語 自作コンパイラ read

urashiba

総合スコア1

C

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

コンパイラ

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

0グッド

0クリップ

投稿2022/07/18 10:53

前提

c,lex,yaccを用いてコンパイラを作成しています。

実現したいこと

現在のプログラムではread文を実行すると「>」と表示され、そこに自分で任意の値を入力することになっています。しかしここに例えば「a>」というように変数名(何文字でも)を含めるようにしたいです。「プロンプト」に「>」を設定しているのはわかるのですが、どうやって変数名を取り出してくればよいのでしょうか。

該当のソースコード

a.yacc

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

a.lex

1alpha [a-zA-Z] 2digit [0-9] 3white [\n\t ] 4%% 5while { return WHILE; } 6if { return IF; } 7read { return READ; } 8print { return PRINT; } 9printx { return PRINTX; } 10{alpha}({alpha}|{digit})* { return IDENT; } 11{digit}+ { return NUM; } 12[-+()=;{}<>*/%] { return yytext[0]; } 13{white} { ; } 14

a.c

1#include <stdio.h> 2struct stab { 3 int val; 4 char name[20]; } stab[100]; 5int stabuse = 0; 6struct node { 7 int type, left, right; } ntab[400]; 8int ntabuse = 1; 9#define T_STLIST 1 10#define T_ASSIGN 2 11#define T_READ 3 12#define T_PRINT 4 13#define T_ADD 5 14#define T_SUB 6 15#define T_MUL 7 16#define T_DIV 8 17#define T_REM 9 18#define T_NUM 10 19#define T_VAR 11 20#define T_WHILE 12 21#define T_IF 13 22#define T_LT 14 23#define T_GT 15 24int lookup(char*); 25int node(int, int, int); 26void dotree(int); 27extern char *yytext; 28#include "y.tab.c" 29#include "lex.yy.c" 30int main() { 31 yyparse(); 32 return 0; 33} 34int lookup(char *s) { 35 int i; 36 for(i = 0; i < stabuse; ++i) 37 if(strcmp(stab[i].name, s) == 0) return i; 38 if(stabuse >= 99) { 39 printf("table overflow.\n"); exit(1); } 40 strcpy(stab[stabuse].name, s); return stabuse++; 41} 42int node(int t, int l, int r) { 43 int i = ntabuse++; 44 ntab[i].type = t; 45 ntab[i].left = l; 46 ntab[i].right = r; 47 return i; 48} 49void emittree(int i) 50{ 51 switch(ntab[i].type) { 52 case T_STLIST: if(ntab[i].left) emittree(ntab[i].left); 53 emittree(ntab[i].right); 54 break; 55 case T_READ: printf(" movq $.Lprompt,%%rdi\n"); 56 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 57 printf(" call printf\n"); 58 printf(" leaq %d(%%rbp),%%rsi\n", -(ntab[i].left+1)*8); 59 printf(" movq $.Lread,%%rdi\n"); 60 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 61 printf(" call scanf\n"); 62 break; 63 case T_PRINT: emittree(ntab[i].left); 64 printf(" popq %%rsi\n"); 65 printf(" movq $.Lprint,%%rdi\n"); 66 printf(" movq $0,%%rax\n"); /* 浮動小数点レジスタを使わない */ 67 printf(" call printf\n"); 68 break; 69 case T_NUM: printf(" pushq $%d\n", ntab[i].left); 70 break; 71 case T_VAR: printf(" pushq %d(%%rbp)\n", -(ntab[i].left+1)*8); 72 break; 73 case T_ASSIGN: emittree(ntab[i].right); 74 printf(" popq %d(%%rbp)\n", -(ntab[i].left+1)*8); 75 break; 76 case T_ADD: emittree(ntab[i].left); 77 emittree(ntab[i].right); 78 printf(" popq %%rdx\n"); 79 printf(" popq %%rax\n"); 80 printf(" addq %%rdx,%%rax\n"); 81 printf(" pushq %%rax\n"); 82 break; 83case T_MUL: emittree(ntab[i].left); 84 emittree(ntab[i].right); 85 printf(" popq %%rdx\n"); 86 printf(" popq %%rax\n"); 87 printf(" imulq %%rdx\n"); 88 printf(" pushq %%rax\n"); 89 break; 90 case T_SUB: emittree(ntab[i].left); 91 emittree(ntab[i].right); 92 printf(" popq %%rdx\n"); 93 printf(" popq %%rax\n"); 94 printf(" subq %%rdx,%%rax\n"); 95 printf(" pushq %%rax\n"); 96 break; 97 case T_DIV: emittree(ntab[i].left); 98 emittree(ntab[i].right); 99 printf(" popq %%rbx\n"); 100 printf(" popq %%rax\n"); 101 printf(" movq $0,%%rdx\n"); 102 printf(" idivq %%rbx\n"); 103 printf(" pushq %%rax\n"); 104 printf("\n"); 105 break; 106case T_REM: emittree(ntab[i].left); 107 emittree(ntab[i].right); 108 printf(" popq %%rcx\n"); 109 printf(" popq %%rax\n"); 110 printf(" movq $0,%%rdx\n"); 111 printf(" idivq %%rcx\n"); 112 printf(" pushq %%rdx\n"); 113 printf("\n"); 114 break; 115 case T_LT: emittree(ntab[i].left); 116 emittree(ntab[i].right); 117 printf(" popq %%rcx\n"); 118 printf(" popq %%rax\n"); 119 printf(" cmp %%rcx,%%rax\n"); 120 printf(" jge "); 121 break; 122 case T_GT: emittree(ntab[i].left); 123 emittree(ntab[i].right); 124 printf(" popq %%rcx\n"); 125 printf(" popq %%rax\n"); 126 printf(" cmp %%rcx,%%rax\n"); 127 printf(" jle "); 128 break; 129} 130void dotree(int i) { 131 int stk; 132 printf(" .section .rodata\n"); 133 printf(".Lprompt: .string\"> \"\n"); /* プロンプト */ 134 printf(".Lread: .string\"%%ld\"\n"); /* 読み取り用書式 */ 135 printf(".Lprint: .string\"%%ld\\n\"\n"); /* 書き出し用書式 */ 136 printf(".Lprintx: .string \"%%x\\n\"\n"); 137 printf(" .text\n"); 138 printf(".global main\n"); 139 printf("main:\n"); 140 printf(" pushq %%rbp\n"); 141 printf(" movq %%rsp,%%rbp\n"); 142 stk = (8*stabuse + 15) / 16; /* 変数の個数*8 で 16 の倍数へ切り上げ */ 143 stk *= 16; 144 printf(" subq $%d,%%rsp\n", stk); 145 emittree(i); 146 printf(" leave\n"); 147 printf(" ret\n"); 148}

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

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

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

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

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

urashiba

2022/07/20 08:48

すいません違いますね。ただやってる課題が同じ人間ですね。
urashiba

2022/07/20 10:50 編集

質問の内容がほぼ同じことより、なおさら同一人物ではないのは明白でしょう。ただその質問が既に存在しているのに気づかず投稿したことについては謝ります。
guest

回答1

0

ベストアンサー

これでどうでしょうか?

diff

1- case T_READ: printf(" movq $.Lprompt,%%rdi\n"); 2+ case T_READ: printf(" .section .rodata\n"); 3+ static int k = 0; 4+ printf(".Lprompt%d: .string \"%s> \"\n", ++k, stab[ntab[i].left].name); 5+ printf(" .text\n"); 6+ printf(" movq $.Lprompt%d,%%rdi\n", k);

追記
質問とは無関係ですが、質問の yacc ファイルだと
print 2 - 3 * 4; が -10 ではなく、-4 になります。

追記2
printf(".Lprompt%d: .string \"%s> \"\n", ++k, stab[ntab[i].left].name);

ntab[i].type が T_READ のとき、ntab[i].left には変数の番号が入っています。
変数の番号とは、stab[] に変数名を登録した時の番号です。
したがって、stab[ntab[i].left].name は変数名です。
printf は分かりますよね。

投稿2022/07/18 16:16

編集2022/08/01 14:15
kazuma-s

総合スコア8224

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

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

urashiba

2022/07/20 10:54

既に他に同様の質問が出ていて、それにKazuma-sさんがお答えしていたようでした。検索不足をお詫びします。ただ動作は理解できました。ありがとうございます。
urashiba

2022/08/01 07:23

本当にすみません。理解した気になっていたのですが、 printf(".Lprompt%d: .string \"%s> \"\n", ++k, stab[ntab[i].left].name); のところの動作について説明していただけますでしょうか?
urashiba

2022/08/01 16:04

なるほど、ありがとうございます。
kazuma-s

2022/08/01 17:15

'+' と '-' が、expr '+' expr と expr '-' prim のように異なっていますが、なぜこうしたんですか? '-' と '*' が、expr '-' prim と expr '*' prim のように同じ形になっていますが、 それだと演算子の優先順位が正しくなりません。もう解決したんですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問