cal.l
%{
#include<string.h>
#include "y.tab.h"
extern int yylval;
%}
numbers ([0-9])+
plus "+"
minus "-"
times "*"
divide "/"
lp "("
rp ")"
delim [ \r]
bs {delim}*
%%
{numbers} {sscanf(yytext, "%d", &yylval); return INTEGER;}
{plus} {return PLUS;}
{minus} {return MINUS;}
{times} {return TIMES;}
{divide} {return DIVIDE;}
{lp} {return LP;}
{rp} {return RP;}
{bs} ;
"\n" return CR;
. {printf("Error");exit(1);}
%%
lex cal.l
cal.y
%{
#include <stdio.h>
#include "lex.yy.c"
#define YYSTYPE int
int yyparse(void);
%}
%token INTEGER PLUS MINUS TIMES DIVIDE LP RP CR
%%
command2 : exp CR {printf("Result = %d\n",$1);}
exp: exp PLUS term {$$ = $1 + $3;}
|exp MINUS term {$$ = $1 - $3;}
|term {$$ = $1;}
;
term : term TIMES factor {$$ = $1 * $3;}
|term DIVIDE factor {$$ = $1/$3;}
|factor {$$ = $1;}
;
factor : INTEGER {$$ = $1;}
| LP exp RP {$$ = $2;}
;
%%
int main(int argc, char* argv[])
{
++argv, --argc; /* Skip over program name. */
if (argc > 0) {
printf("if \n");
yyin = fopen(argv[0], "r");
} else {
printf("else \n");
yyin = stdin;
}
printf("going to return yyparse() \n");
return yyparse();
}
void yyerror(char* s)
{
fprintf(stderr,"%s",s);
}
int yywrap()
{
return 1;
}
yacc -d cal.y
生成了
y.tab.c
编译
g++ -o tcal y.tab.c
y.tab.c: In function ‘int yyparse()’:
y.tab.c:1318:35: error: ‘yyerror’ was not declared in this scope
yyerror (YY_("syntax error"));
^
y.tab.c:1462:35: error: ‘yyerror’ was not declared in this scope
yyerror (YY_("memory exhausted"));
^
注释掉报错的地方
重新编译
g++ -o tcal y.tab.c
./tcal
else
going to return yyparse()
1+2*3-5
Result = 2
修改测试
尝试增加一个^符号用来计算平方
3^ = 9
4^ = 16
| factor SQUARE {$$ = $1 * $1;}
g++ -o tcal y.tab.c
In file included from cal.y:3:0:
cal.l: In function ‘int yylex()’:
cal.l:27:9: error: ‘SQUARE’ was not declared in this scope
{sq} {return SQUARE;}
^~~~~~
y.tab.c: In function ‘int yyparse()’:
y.tab.c:1326:35: error: ‘yyerror’ was not declared in this scope
yyerror (YY_("syntax error"));
^
y.tab.c:1470:35: error: ‘yyerror’ was not declared in this scope
yyerror (YY_("memory exhausted"));
^
由于yacc cal.y 没有生成h文件,而文件中有曾经
采用yacc -d cal.y生成的h文件,就导致一直使用没有更新的h文件,和刻舟求剑一样
所以,需要使用yacc -d cal.y进行生成
cal.l
%{
#include<string.h>
#include "y.tab.h"
extern int yylval;
%}
numbers ([0-9])+
plus "+"
minus "-"
times "*"
divide "/"
lp "("
rp ")"
square "\^"
delim [ \r]
bs {delim}*
%%
{numbers} {sscanf(yytext, "%d", &yylval); return INTEGER;}
{plus} {return PLUS;}
{minus} {return MINUS;}
{times} {return TIMES;}
{divide} {return DIVIDE;}
{lp} {return LP;}
{rp} {return RP;}
{square} {return SQUARE;}
{bs} ;
"\n" return CR;
. {printf("Error");exit(1);}
%%
由于^在正则表达式里有特殊意义,所以这里进行转义操作
lex cal.l
cal.y
%{
#include <stdio.h>
#include "lex.yy.c"
#define YYSTYPE int
int yyparse(void);
%}
%token INTEGER PLUS MINUS TIMES DIVIDE LP RP SQUARE CR
%%
command2 : exp CR {printf("Result = %d\n",$1);}
exp: exp PLUS term {$$ = $1 + $3;}
|exp MINUS term {$$ = $1 - $3;}
|term {$$ = $1;}
;
term : term TIMES factor {$$ = $1 * $3;}
|term DIVIDE factor {$$ = $1/$3;}
|factor {$$ = $1;}
;
factor : factor SQUARE {$$ = $1 * $1;}
| INTEGER {$$ = $1;}
| LP exp RP {$$ = $2;}
;
%%
int main(int argc, char* argv[])
{
++argv, --argc; /* Skip over program name. */
if (argc > 0) {
printf("if \n");
yyin = fopen(argv[0], "r");
} else {
printf("else \n");
yyin = stdin;
}
printf("going to return yyparse() \n");
return yyparse();
}
void yyerror(char* s)
{
fprintf(stderr,"%s",s);
}
int yywrap()
{
return 1;
}
g++ -o cal y.tab.c
注释修改编译报错
./cal
else
going to return yyparse()
1+2^
Result = 5
./cal
else
going to return yyparse()
1+2*3^+4
Result = 23
./cal
else
going to return yyparse()
1+3^^
Result = 82