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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1093閲覧

LEX,Yaccでの電卓環境構築

Amateur0845

総合スコア6

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/01/17 14:11

前提・実現したいこと

大学で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はどのように学習すればよいのでしょうか?
現在教授のレジュメのみで学習しているのですが、あまり深く学べていません。

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

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

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

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

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

guest

回答2

0

ベストアンサー

ch3-05.h の内容がないので、struct symtab がどう定義されているか
よくわかりませんが、次の修正で何とかなりませんか?

yacc

diff

1 #include <math.h> 2+double cond = 1; 3 %} 4 5+%token IF 6 %token <symp> NAME 7 %token <dval> NUMBER 8+%left '<' '>' 9 %left '+' '-' 10 11-statement_list: statement '\n' 12- | statement_list statement '\n' 13+statement_list: statement '\n' { cond = 1; } 14+ | statement_list statement '\n' { cond = 1; } 15 ; 16 17-statement: NAME '=' expression { $1->value = $3; } 18- | expression { printf("= %g\n", $1); } 19+statement: NAME '=' expression { if (cond) $1->value = $3; } 20+ | expression { if (cond) printf("= %.15g\n", $1); } 21 | statement ':' 22- | statement NAME '=' expression {$2 -> value = $4;} 23+ | statement NAME '=' expression {if (cond) $2 -> value = $4;} 24+ | IF '(' expression ')' { cond = $3; } 25 ; 26 27 | expression '/' expression { if($3==0.0) yyerror("Divide by Zero"); 28 else $$ = $1 / $3; } 29+ | expression '<' expression { $$ = $1 < $3; } 30+ | expression '>' expression { $$ = $1 > $3; }

Lex

diff

1+if { return IF; } 2+ 3 ([0-9]+|([0-9]*.[0-9]+)([eE][-+]?[0-9]+)?) {

投稿2021/01/18 05:23

kazuma-s

総合スコア8224

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

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

Amateur0845

2021/01/18 15:49

コメントありがとうございます。 正しく出力できました。 IFを1つのトークンとして考えるのですね 貴重なお時間を頂きましてありがとうございました。
guest

0

ご参考: http://160.16.241.20/lectures/95/1995-04-SoftengExpr8.pdf

課題でこういうのを参考にするのもどうかと思いますが、入手しやすい参考資料があまりないんですよね。GNU 版の bison や flex にしても日本語マニュアルや書籍は入手しづらいでしょうし、もし本物の yacc, lex を使っているなら機能の差異があるでしょうし。

投稿2021/01/17 14:38

68user

総合スコア2022

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

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

Amateur0845

2021/01/17 16:05

なかなか難しいです。 参考になりました。 ありがとうございます。
68user

2021/01/17 16:27

しょうもない訂正ですが、bison は GNU project での開発ですが、flex は GNU とは無関係でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問