The Lex files are as follows:% {# include "cal.tab.h"%}% option NOYYWRAPINTEGER [0-9] DREAL ([0-9] * "." [0-9] ) EREAL ([0-9 ] * "." [0-9] [EEDD] [ -]? [0-9] ) Real {DREAL} | {EREAL} NL / NPLUS " " Minus "-" Times "*" Divide " / "lp" ("rp") "Module"% "Power" ^ "%% [/ t]; / * Skip any blanks * / {integer} {sscanf (YYTEXT,"% D ", & yylval.integer; Return Integer;} {real} {SSCANF (YYTEXT, "% LF", & yylval.real); / * yylval = atof (yytext); it doesn't work under msvsc * / return real;
{Plus} {Return Plus;} {minus} {Return minus;} {TIMES} {Return Times;} {divide} {return}}} {module} {Return Module;} {Power} {Return Power;} {LP } {RETURN LP;} {rp} {return rp;}
{nl} {return nl;}. {return yytext [0];
%% or more is the code of the LEX file (Cal.L), lex is used to get token.
After having token, use YACC (I use Bison's BISON that can run under Windows) to handle these symbols. That is, it is written a state, and finally gets the results. Below is the code (CAL.Y) of YACC file (CAL.Y):% {include
%}% union {double real; / * real value * / int integer; / * integer value * /}% token
% Start Lines% Token Number NL% Token Plus Minus Times Divide Module Power LP RP
% TYPE
% Left Plus Minus / * Left Associative * /% LEFT TIMES DIVIDE MODULE / * LEFT Associative * /% Left Power% Left Unaryminus
%% LINES: / * NOTHING * / | LINES LINE NL | LINES ERROR NL {Yyerror (); YYERROK;}; Line: IEXPR {Printf ("% D / N", $ 1);} | Rexpr {Printf ("% LF / N ", $ 1);}; IEXPR: Integer {$$ = $ 1;} | IExpr Plus ippr {$$ = $ 1 $ 3;} | IExpr Minus IExpr {$$ = $ 1 - $ 3;} | IEXPR Times IExpr {$$ = ($ 3) $$ {IExpr Divide IExpr {IExpr Divide = $ 1 / $ 3; Else {$$ = $ 1; Printf (stderr, "% D.% D-% d.% D: Division By Zero, @ 3.First_Line, @ 3.First_Column, @ 3.Last_Line, @ 3.last_Column);}} | i = $ 1% $ 3;} | i = Power IExpr {$$ = POW $ 1, $ 3);} | minus ippr% prec unaryminus {$$ = - $ 2;} | lp ippr rp {$$ = $ 2;} | lp iExpr Error {$$ = $ 2; YYERROR ("missing ')'") YYERROK;} | Plus ippr% PREC unaryminus {$$ = $ 2;
Rexpr: Real {$$ = $ 1;} | Rexpr Plus Rexpr {$$ = $ 1 $ 3;} | Rexpr Minus Rexpr {$$ = $ 1 - $ 3;} | rexpr Times Rexpr {$$ = $ 1 * $ 3;} | Rexpr Divide Rexpr {IF ($ 3) $$ = $ 1 / $ 3; Else {$$ = $ 1; Printf (stderr, "% D.% D-% D.% D: Division By Zero", @ 3.first_Line, @ 3.First_Column, @ 3.last_line, @ 3.last_column);}} | Rexpr Power Rexpr {$$ = Pow ($ 1, $ 1);} | lp rexpr rp {$$ = $ 2;} | lp rexpr error {$ $ = $ 2; YYERROR ("missing ')'"); YYERROK;} | minus rexpr% prec unaryminus {$$ = - $ 2;} | Plus rexpr% prec unaryminus {$$ = $ 2;} | ippr Plus rexpr {$ $ 1 $ 3;} | IEXPR Minus Rexpr {$$ = (Double) $ 1 - $ 3;} | ippr Times Rexpr {$$ = (Double) $ 1 * $ 3;} | ippr DiVide Rexpr { IF ($ 3) $$ = (Double) $ 1 / $ 3; Else {$$ = $ 1; Printf (stderr, "% d.% D-% d.% d: division by zero", @ 3.first_line, @ 3 .first_column, @ 3.last_line, @ 3.last_column);}} | = i = = $ 1, $ 3);} | Rexpr Plus ippr {$$ = $ 1 (double) $ 3; } | Rexpr Minus IExpr {$$ = $ 1 - (Double) $ 3;} | Rexpr Times IExpr {$$ = $ 1 * (Double) $ 3;} | Rexpr Divide IExpr {IF ($ 3) $$ = $ 1 / (Double) $ 3;
Else {$$ = $ 1; Printf (stderr, "% d.% D-% d.% d: division by zero", @ 3.first_line, @ 3.First_Column, @ 3.last_line, @ 3.last_column; }} | Rexpr Power IEXPR {$$ = POW ($ 1, (Double) $ 3);}; %%
Void main () {yyparse ();
Int Yyerror (Char * MSG) {Printf ("Error:% s Encountered / N", MSG);
Such a calculator that supports , -, ×, /, ^, and parentheses operations. The time used will not exceed half an hour. If you use C, or C to write an operator, you can be a non-small project. This shows the charm of Lex and Yacc!
The compile command is: flex cal.l bison -d -v cal.y pause Any suggestions, questions, welcome: Buaa_Chenx@hotmail.com