前提・実現したいこと
大学でYaccやLEXについて学んでいます。
課題で分からなくなりましたので質問させていただきます。
電卓のプログラムが作成されており、そのコードを改良する課題です。
(1) 実行文を:で区切って、1行に複数の文を記述する(全体で1つの複文となる) 例 a=0:b=1:c=2 (ただし、複文は左の文から順に実行される) (2) 次のようなif文を使えるようにする。 if( 条件式 ) 実行文 例:if( a-b>15 ) a=a-1 条件式の演算子には、> または < が使用できるものとする。条件式が成立していたときには、実行文(複文も可)を実行する。
発生している問題・エラーメッセージ
問2の書き方が分かりません
該当のソースコード
Yacc
1%{ 2#include <stdio.h> 3#include <stdlib.h> 4#include "ch3-05.h" 5#include <string.h> 6#include <math.h> 7%} 8 9%union { 10 double dval; 11 struct symtab *symp; 12} 13 14%token <symp> NAME 15%token <dval> NUMBER 16%left '+' '-' 17%left '*' '/' 18%nonassoc UMINUS 19 20%type <dval> expression 21%% 22 23statement_list: statement '\n' 24 | statement_list statement '\n' 25 ; 26 27statement: NAME '=' expression { $1->value = $3; } 28 | expression { printf("= %g\n", $1); } 29 | statement ':' 30 | statement NAME '=' expression {$2 -> value = $4;} 31 ; 32 33expression: expression '+' expression { $$ = $1 + $3; } 34 | expression '-' expression { $$ = $1 - $3; } 35 | expression '*' expression { $$ = $1 * $3; } 36 | expression '/' expression { if($3==0.0) yyerror("Divide by Zero"); 37 else $$ = $1 / $3; } 38 | '-' expression %prec UMINUS { $$ = -$2; } 39 | '(' expression ')' { $$ = $2; } 40 | NUMBER { $$ = $1; } 41 | NAME { $$ = $1->value; } 42 | NAME '(' expression ')' { if( $1->funcptr ) $$ = ($1->funcptr)($3); 43 else { 44 printf("%s not a function.\n", $1->name); 45 } 46 } 47 ; 48 49%% 50 51/* look up a symbol table entry, add if not present */ 52struct symtab *symlook(char *s) 53{ 54 char *p; 55 struct symtab *sp; 56 57 for(sp=symtab; sp<&symtab[NSYMS]; sp++) { 58 /* is it already here? */ 59 if( sp->name && !strcmp(sp->name, s) ) return sp; 60 61 /* is it free */ 62 if( !sp->name ) { 63 sp->name = strdup(s); 64 return sp; 65 } 66 67 /* otherwise continue to next */ 68 } 69 yyerror("Too many symbols"); 70 exit(1); /* cannot continue */ 71} /* end of symlook */ 72 73void addfunc(char *name, double (*func)()) 74{ 75 struct symtab *sp = symlook(name); 76 sp->funcptr = func; 77} 78 79int main() 80{ 81 extern double sqrt(), exp(), log(), sin(), cos(); 82 83 addfunc("sqrt", sqrt); 84 addfunc("exp", exp); 85 addfunc("log", log); 86 addfunc("sin", sin); 87 addfunc("cos", cos); 88 89 yyparse(); 90 91 return 0; 92} 93
Lex
1%{ 2#include "y.tab.h" 3#include "ch3-05.h" 4#include <math.h> 5%} 6 7%% 8 9([0-9]+|([0-9]*.[0-9]+)([eE][-+]?[0-9]+)?) { 10 yylval.dval = atof(yytext); 11 return NUMBER; } 12 13[ \t] ; /* ignore white space */ 14 15[A-Za-z][A-Za-z0-9]* { /* return symbol pointer */ 16 struct symtab *sp = symlook(yytext); 17 yylval.symp = sp; 18 return NAME; 19 } 20 21"$" { return 0; /* end of input */ } 22 23 24\n |":" 25. return yytext[0]; 26%% 27void yyerror(char *errmsg) 28{ 29 fprintf(stderr,"ERROR: %s at %s\n", errmsg, yytext); 30} 31yywrap() { } 32
試したこと
問1は”:”が入った際の処理を書くことで解決できましたが
問2では実行文にIFを入れなければならないのでつまずいてしまいました。
どのような書き方をすれば改良できるのでしょうか?
またプログラミング言語のYaccやLEXはどのように学習すればよいのでしょうか?
現在教授のレジュメのみで学習しているのですが、あまり深く学べていません。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/18 15:49