你也可以通过我的独立博客 —— www.huliujia.com 获取本篇文章
简易编译器实现(一)使用Flex创建词法分析器一文介绍了编译器的概念和七个阶段,并说明了如何使用Flex创建词法分析器。本篇文章介绍如何使用Bison创建语法分析器,并实现基本的运算能力。本文继续使用简易编译器实现(一)使用Flex创建词法分析器中提出的集合运算语言AlphaGun作为演示的例子。
语法分析
语法分析器使用词法分析器输出的token流作为输入,把token流转换成树状的中间表示,通常会转换成语法树,本文中使用的例子比较简单,所以会对结果进行直接计算。复杂的语言通常会先构建语法树,然后在语法树的基础上做一系列的处理。如果输入的token流不符合语法分析器的规定的语法,语法分析器还可以报语法错误。
和词法分析器自动生成类似,我们可以利用Bison来自动生成语法分析器,提高开发速度,降低迭代成本和维护成本。本文主要介绍Bison的使用。
Bison的语法
Bison语法规则和Flex一样分为3个部分,第一部分是C语言声明、token声明、类型声明。由"%{“和”}%"围住的C语言部分会被直接拷贝到生成的语法分析器代码前面。第二部分是使用BNF语法编写的语法规则,为了编写方便,Bison对BNF做了一定的简化。第三部分是要执行的main函数。
下面是为集合运算语言AlphaGun编写的Bison规则,代码量比较大,可以直接翻到下面看解释
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#define NAME_SIZE 100
#define CHAR_SET_SIZE 26
extern int yylineno; /* from lexer */
int yylex();
void yyerror(char *s, ...)
{
va_list ap;
va_start(ap, s);
fprintf(stderr, "%d: error: ", yylineno);
vfprintf(stderr, s, ap);
fprintf(stderr, "\n");
}
struct Symbol
{
char name;
char value[CHAR_SET_SIZE];
};
struct Symbol symbol_table[26];
char temp_char_set[CHAR_SET_SIZE];
char factor_char_set[CHAR_SET_SIZE];
char expr_char_set[CHAR_SET_SIZE];
struct