学习yacc与lex--计算器实现练习
来源:互联网 发布:跑腿软件排名 编辑:程序博客网 时间:2024/05/24 03:26
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
- 学习yacc与lex--计算器实现练习
- lex/yacc实现计算器
- lex与yacc(二)计算器的实现
- Lex与Yacc学习(六)之lex & yacc (简单计算器程序) 运行
- LEX 与 YACC 学习
- 用lex和yacc实现的计算器
- 使用lex与yacc构建简单计算器
- yacc 与 Lex 学习 [2]
- Lex&yacc简单计算器
- Lex与Yacc学习(八)之变量和有类型的标记(扩展计算器)
- 神奇的lua:lex和yacc实现计算器
- Yacc 与 Lex 学习 [1]
- LEX与YACC学习资料链接
- lex和yacc 入门-- 计算器
- Lex与Yacc学习(九)之Yacc语法
- Lex与Yacc学习(十)之Yacc库
- Lex与Yacc学习(四)之Lex规范
- lex yacc 学习
- nginx架构详解
- 【BJOI2006】bzoj1001 狼抓兔子
- Stack && Queue
- Java集合框架:常用的增删改查方法
- 软件设计是怎样炼成的(3)——软件系统不是木桶型的
- 学习yacc与lex--计算器实现练习
- checkbox的选中和被选中,Linearlayout点击之后保持点击状态
- VS2013常用快捷键
- 狸猫换太子--删除无头单链表中结点
- STM32控制超声波测距模块HC-SR04
- linux内核下载地址
- oracle表空间增大方法
- 表单验证之BootstrapValidator
- Win10 TensorFlow(gpu)安装详解