前提
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}
回答1件
あなたの回答
tips
プレビュー