yacc实现简单的计算器程序
时间: 2023-06-27 09:01:46 浏览: 166
为了使用 `yacc` 实现简单的计算器程序,我们需要编写 `lex` 文件和 `yacc` 文件。首先,我们来编写 `lex` 文件。
## Lex 文件
我们需要定义一些正则表达式来匹配我们的输入。下面是一个简单的例子:
```
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
[0-9]+ { yylval = atoi(yytext); return NUM; }
[-+*/\n()] { return yytext[0]; }
. { printf("Invalid character: %s\n", yytext); }
%%
int yywrap() {
return 1;
}
```
这个文件包含了三个部分:定义、规则和后处理。
在定义部分,我们首先包含了 `stdio.h` 和 `y.tab.h` 库。`y.tab.h` 包含了我们在 `yacc` 文件中定义的 token 值,以及 `yylval`。
在规则部分,我们定义了三个规则。第一个规则匹配数字,并将其转换为整数类型的值。第二个规则匹配运算符和括号,返回对应的 token 值。第三个规则匹配任何其他字符,并打印错误消息。
在后处理部分,我们定义了一个 `yywrap()` 函数,告诉 `lex` 解析器结束输入。
## Yacc 文件
现在我们需要编写 `yacc` 文件来解析 `lex` 文件生成的 token,并执行相应的计算操作。下面是一个简单的例子:
```
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token NUM
%%
input: /* empty */
| input line
;
line: '\n'
| expression '\n' { printf("= %d\n", $1); }
;
expression: NUM
| expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| expression '*' expression { $$ = $1 * $3; }
| expression '/' expression { $$ = $1 / $3; }
| '(' expression ')' { $$ = $2; }
;
%%
int main() {
yyparse();
return 0;
}
int yyerror(char *s) {
printf("error: %s\n", s);
return 0;
}
```
这个文件包含了三个部分:定义、规则和后处理。
在定义部分,我们包含了 `stdio.h` 和 `stdlib.h` 库,并使用 `%token` 定义了 `NUM`。
在规则部分,我们定义了三个规则。第一个规则表示输入可以为空或包含多行。第二个规则表示每一行可以是一个空行或一个表达式,计算表达式的值并打印结果。第三个规则表示表达式可以是一个数字、两个表达式加减乘除、或一个括号包含的表达式。
在后处理部分,我们定义了一个 `main()` 函数用于启动解析器,以及一个 `yyerror()` 函数用于打印错误消息。
## 编译和运行
现在我们需要将 `lex` 文件和 `yacc` 文件编译成可执行文件。假设我们的 `lex` 文件名为 `calc.l`,`yacc` 文件名为 `calc.y`,则我们可以使用以下命令编译:
```
$ lex calc.l
$ yacc -d calc.y
$ gcc lex.yy.c y.tab.c -o calc
```
最后,我们可以运行 `calc` 可执行文件并输入表达式进行计算:
```
$ ./calc
1+2*(3-4)/5
= 0
```
这个程序只是一个简单的例子,您可以根据需要进行修改,增加更多的功能。
阅读全文