简介
在本实验中,我们将探索 bison 命令,这是一个用于编译器和解释器开发的解析器生成工具。Bison 是 YACC 的一个免费软件实现,YACC 是一个强大的工具,用于从上下文无关文法规范生成解析器。我们将首先在 Ubuntu 22.04 环境中安装 bison 包,然后创建一个简单的文法文件并使用 bison 命令生成解析器。最后,我们将学习如何处理生成的解析器中的语法错误。
本实验涵盖以下步骤:
bison命令简介- 使用
bison生成解析器 - 处理
bison中的语法错误
bison 命令简介
在这一步中,我们将探索 bison 命令,这是一个用于编译器和解释器开发的解析器生成工具。Bison 是 YACC(Yet Another Compiler-Compiler)的一个免费软件实现,YACC 是一个强大的工具,用于从上下文无关文法规范生成解析器。
首先,让我们在 Ubuntu 22.04 环境中安装 bison 包:
sudo apt-get update
sudo apt-get install -y bison
示例输出:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
m4
Suggested packages:
bison-doc
The following NEW packages will be installed:
bison m4
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,141 kB of archives.
After this operation, 4,470 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
...
现在我们已经安装了 bison,接下来让我们创建一个简单的文法文件来生成解析器。在 ~/project 目录下创建一个名为 example.y 的新文件,内容如下:
%{
#include <stdio.h>
%}
%token NUM
%%
input:
| input line
;
line:
NUM '\n' { printf("Received number: %d\n", $1); }
;
%%
int main() {
yyparse();
return 0;
}
这个文法文件定义了一个简单的类似计算器的语言,可以识别并处理数字。%token NUM 行声明了一个用于数字的标记类型,而 line 规则指定了一个有效的行由一个数字和一个换行符组成。
使用 bison 生成解析器
在这一步中,我们将基于上一步创建的文法文件,使用 bison 命令生成解析器。
首先,让我们从 example.y 文件生成解析器源代码:
bison -d example.y
该命令将生成两个文件:example.tab.c 和 example.tab.h。example.tab.c 文件包含解析器的实现,而 example.tab.h 包含标记定义。
接下来,我们需要编译解析器源代码并将其与词法分析器(lexer)链接以创建最终的可执行文件。我们将使用 flex 工具生成词法分析器:
sudo apt update
sudo apt-get install -y flex
flex -o example.lex.c example.l
gcc -o example example.tab.c example.lex.c
flex 命令生成 example.lex.c 文件,其中包含词法分析器的实现。gcc 命令编译解析器和词法分析器源代码,并将它们链接以创建最终的 example 可执行文件。
现在,让我们通过运行 example 程序来测试解析器:
./example
123
Received number: 123
456
Received number: 456
如你所见,解析器正确地识别并处理了输入的数字。
处理 bison 中的语法错误
在这一步中,我们将学习如何处理由 bison 生成的解析器中的语法错误。
让我们修改 example.y 文件以包含错误处理:
%{
#include <stdio.h>
%}
%token NUM
%error-verbose
%%
input:
| input line
| input error '\n' { yyerrok; }
;
line:
NUM '\n' { printf("Received number: %d\n", $1); }
| error '\n' { yyerror("Invalid input"); }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "%s\n", s);
}
int main() {
yyparse();
return 0;
}
主要更改包括:
- 添加了
%error-verbose以提供更详细的错误信息。 - 在
input和line产生式中添加了error规则以处理语法错误。 - 实现了
yyerror函数以打印错误信息。
现在,让我们重新生成解析器并测试它:
bison -d example.y
flex -o example.lex.c example.l
gcc -o example example.tab.c example.lex.c
尝试运行 example 程序并输入一些无效的输入:
./example
abc
example.y:12: syntax error, unexpected error, expecting NUM
Invalid input
123
Received number: 123
如你所见,当我们输入 "abc" 而不是数字时,解析器正确地识别并报告了语法错误。
总结
在本实验中,我们探索了 bison 命令,这是一个用于编译器和解释器开发的解析器生成工具。我们首先学习了如何在 Ubuntu 22.04 上安装 bison 包,然后创建了一个简单的文法文件来定义一个类似计算器的语言。接着,我们使用 bison 命令生成了解析器源代码,生成了两个文件:解析器实现和头文件。最后,我们学习了如何处理生成的解析器中的语法错误。



