編譯原理:用Flex和 Bison實現一個功能更為強大的計算器
阿新 • • 發佈:2019-01-29
用Flex和 Bison實現一個功能更為強大的計算器,包含以下運算:
a)加、減、乘、除運算
b)乘方、開方運算
c)位運算
– 與 & 、或 |、非 ~...
d)階乘運算 !對數運算log
1.進一步完善計算器功能,實現對以下語法結構的分析。還可以進一步擴充功能。
12+23*34+sin(45)/cos(56)-67
1.Calc.lex源程式如下:
%{ /* * 一個簡單計算器的Lex詞法檔案 */ #include <stdlib.h> void yyerror(char*); /* #include "calc.tab.h" */ %} %% /* a-z為變數 */ [a-z] { yylval = *yytext - 'a'; return VARIABLE; } /* 整數 */ [0-9]+ { yylval = atoi(yytext); return INTEGER; } /* 運算子 */ [-+()=/*^&|~[!SCTL#\n] {return *yytext;} /* 空白被忽略 */ [ \t] ; /* 其他字元都是非法的 */ . yyerror("無效的輸入字元"); %% int yywrap(void) { return 1; }
(2)calc.y的源程式如下:
%token INTEGER VARIABLE %left '+' '-' %left '*' '/' %left '^' '[' %left '!' '&' %left '|' '~' %left 'S' 'C''T' %left 'L' '#' %{ #define YYSTYPE double #define w (0.017453292519943) #include <math.h> #define __STDC__ 0 void yyerror(char*); int yylex(void); double sym[26]; %} %% program: program statement '\n' | ; statement: expr {printf("%f\n", $1);} |VARIABLE '=' expr {sym[(int)$1] = $3;} ; expr: INTEGER |VARIABLE{$$ = sym[(int)$1];} |expr '+' expr {$$ = $1 + $3;} |expr '-' expr {$$ = $1 - $3;} |expr '*' expr {$$ = $1 * $3;} |expr '/' expr {$$ = $1 / $3;} |expr '^' expr {$$ = pow($1,$3);} |expr '[' expr {$$ = pow($3,1.0/$1);} |expr '!' {int i,s=1; for(i=1;i<=$1;i++) s=s*i; $$=s; } |expr '&' expr { $$ = (int)($1)&(int)($3);} |expr '|' expr { $$ = (int)($1)|(int)($3);} |'~'expr { $$ = ~(int)($2);} |'S''('expr')' { $$=sin($3*(w));} |'C''('expr')' { $$=cos($3*(w));} |'T''('expr')' { $$ = tan($3*(w));} |'L''('expr')' { $$ = log($3);} |expr '#' expr { $$ = (int)($1)%(int)($3);} |'('expr')' {$$ = $2;} ; %% void yyerror(char* s) { fprintf(stderr, "%s\n", s); } #include "lex.yy.c" int main(void) { printf("A simple calculator.\n"); printf("加(+),減(-),乘(*),除(/),乘方(^),開方([),階乘(!).\n"); printf("與(&),或(|),非(~)\n"); printf("S (sin)、C (cos)、T (tan):三角函式\n"); printf("求對數(L),求模(#)\n"); printf("START:\n"); yyparse(); return 0; }
心得體會:
經過這次的實驗,我學到了很多新的知識和好的學習方法。第一次實驗做成功了給了我很大的信心,開始很順利,後來遇到文法相關的知識,我就又收到了挫敗。不斷的失敗不斷的重複實驗,不會的問同學內部是怎麼傳值的,看書看相關的文法知識,百度,總之就是不斷重複。終於,修改了很多次,我做出來了。這離不開同學的耐心講解和一直堅持的自己。有時候別人告訴我放棄,可我還是選擇了堅持。我一定要堅守原則堅持下去。或許,有些事開始認為不可能,只有在自己堅持做了,才會取得成果!下次繼續努力吧!