基于FlexBison的高级解释器设计及实现
- 格式:docx
- 大小:513.72 KB
- 文档页数:17
Bison学习Bison是一个通用的语法解析器生成器,与YACC兼容,它能够将一个LALR(1)的上下文无关文法描述规则转化一个解析该语法的C程序。
LALR(1)指的是"向前看一个符号的自底向上文法分析技术",简单来说就一种通过向前看一个字符就解析该符号片段的上下文无关文法。
关于上下文无关文法的概念,符号,开始符号,终结符,非终结符等不再多做介绍。
Bison接受一个用户定义的文法文件,文法规则通常使用机器可读的BNF表示,产生一个能够解析该文法的语法解析器。
一、使用Bison通常包含以下几个步骤:1.以Bison可识别的形式正规定义一个文法。
对于每一条文法规则,定义其对应的动作。
2.编写一个词法分析器,能够将输入的源文件转化为词法符号,并将符号传递给文法解析器。
词法解析器可以手写,也可以使用flex生成。
3.写一个控制函数来调用Bison生成的文法解析器。
4.编写错误报告和处理函数。
二、Bison输入的文法文件的格式%{C的声明%}Bison的一些声明%%文法规则%%附加的C代码1.符号:终结符和非终结符终结符:表示具有等价语法的符号。
yylex返回的是表示终结符类型的符号类型码。
终结符有三种,分别是命名符号类型,字面字符类型和字面字符串类型。
非终结符:表示具有等价语法的组合。
2.规则:递归规则中应该使用左递归而非右递归,因为左递归总能够使用有限的栈空间解析出一个字符序列。
3.语义定义Bison中默认将所有的语义值都定义为int类型,可以通过定义宏YYSTYPE来改变值的类型。
如果有多个值类型,则需要通过在Bison声明中使用%union列举出所有的类型,然后为每个符号定义相对的类型,终结符使用%token,非终结符使用%type来定义。
在动作(Action)中,$i表示第i个符号的值,其类型与Bison声明中的类型一致,或者可以通过$type i来指定值类型。
4.Bison声明(1)%token NUM(2)%token NUM 300//指定符号类型的编码数字,不建议使用(3)%union{double*doublepval;int*int_val;}%token int_val NUM(4)将一个字符串与一个符号类型关联起来%token OR"||"(5)操作符优先级定义%left ADD//左结合%right NEG//右结合%nonassoc OP//无结合,如果出现x op y则是语法错误定义在后面的符号比定义在前面的符号具有更好的优先级(6)非终结符%type double_value exp(7)消除警告。
使用FlexBison和LLVM编写自己的编译器(转)编译原理使用Flex Bison 和LLVM编写自己的编译器(转)使用Flex Bison 和LLVM编写自己的编译器译者:赵锟原文:(酷壳)本文由赵锟翻译,酷壳发布,转载请注明译者和出处,请勿用于商业用途原文出处:1、介绍我总是对编译器和语言非常感兴趣,但是兴趣并不会让你走的更远。
大量的编译器的设计概念可以搞的任何一个程序员迷失在这些概念之中。
不用说,我也曾今尝试过,但是并没有取得太大的成功,我以前的尝试都停留在语义分析阶段。
本文的灵感主要来源于我最近一次的尝试,并且在这一次中我取得一点成就。
幸运的是,最近的几年,我参加了一些项目,这些项目给了我在建立编译器上很多有用的经验和观点。
另外一件事是,我非常幸运得到LLVM的帮助。
对于这个工具,我不知道改怎么去形容它,但是他给我的这个编译器的确带来非常大的帮助。
1.1、你为什么要阅读本文你也许想看看我正在做的事情,但是更有可能的是,你也是和我一样对编译器和语言非常感兴趣,并且也可能遇到了一些在探索的过程中遇到了一些难题,你可能正打算解决这些难题,但是却没有发现好的资源。
本文的目标就是提供这些资源,并以一种手把手的方式教你从头到尾的去创建一个具有基本功能的语言编译器。
在本文,我不会去解释一些编译器基本理论,所以你要在开始本文前去了解什么是BNF语法,什么是抽象语法树数据结构AST data structure,什么是基础编译器流水线complier pipline。
就是说,我会把本文描述的尽量简单。
本文的目的就是以一种简单易懂的方式来介绍相关编译器资源的方式来帮助那些从来没有编译器经验的人。
1.2、达到的成果如果你根据文章内容一步步来,你将会得到一个能定义函数,调用函数,定义变量,给变量赋值执行基本数学操作的语言。
这门语言支持两种基本类型,double和integer类型。
还有一些功能还未实现,因此,你可以通过自己去实现这些功能得到你满意的功能并且能为你理解编写一个编译器提供不少的帮助。
编译型PLC的设计与实现贾翔宇;刘淼;金星【摘要】Traditional PLC works inefficiently by using interpreted mode. And the PLC works efficiently by using compiled mode, but it has bad portability. Based on this situation, this paper proposes a new scheme, which converts from instruction list to C language, and then compiles the C code. In addition, the main function and functional function compile separately and download to different address block of the flash. This way can save the time of compiling and downloading efficiently, and can improve the development efficiency.%传统的PLC采用解释执行的方式,效率低.而传统的编译型PLC虽然执行效率高,但是移植性差.基于这种情况,该文提出一种先把指令表语言编译为C语言,再编译C代码的方案.而且,主函数和功能函数分开编译并烧录在flash的不同地址块,能够有效节省编译、烧录时间,提升开发效率.【期刊名称】《电子设计工程》【年(卷),期】2016(024)014【总页数】5页(P40-43,48)【关键词】编译;PLC;指令表;不同地址块【作者】贾翔宇;刘淼;金星【作者单位】中国科学院上海微系统与信息技术研究所,上海 200050;上海科技大学上海 200031;浙江中科领航汽车电子有限公司浙江杭州 311228;中国科学院上海微系统与信息技术研究所,上海 200050;上海科技大学上海 200031;浙江中科领航汽车电子有限公司浙江杭州 311228【正文语种】中文【中图分类】TP31PLC(Programmable Logic Controller),全称为可编程逻辑控制器,是一种专门用于工业控制的微型计算机。
编译原理 flex %option bison-bridge
Flex 是一种词法分析器生成工具,可以把输入的字符流转化为一个个记号流。
在编译原理中,通常与Bison一起使用。
为了使 Flex 与 Bison 兼容,可以使用 %option bison-bridge。
这个选项可以让 Flex 为 Bison 生成符号表和头文件。
使用这个选项的好处是,可以避免手动创建头文件和符号表。
同时,这对于跟踪语法错误也非常有用。
通过使用 %option bison-bridge,Bison 就可以直接使用 Flex 生成的符号表来识别记号。
这样可以避免手动输入符号表,从而减少错误。
同时,如果需要在 Bison 生成的语法中使用 Flex 的记号,也可以非常方便地实现。
总之,使用 %option bison-bridge 可以使 Flex 与 Bison 兼容,使得语法分析更加方便、可靠。
课程设计3 基于Flex/Bison的高级解释器设计及实现3.1 需求分析3.1.1 问题定义1.使用flex和bison开发了一个具有全部功能的桌面计算器,能够支持变量,过程,循环和条件表达式,使它成为一个虽然短小但是具有现实意义的编译器。
2.重点学习抽象语法树的用法,它具有强大而简单的数据结构来表示分析。
3.1.2 功能描述1.计算器具体需要实现的功能:a)变量命名;b)实现赋值功能;c)实现比较表达式(大于、小于、等于等等)d)实现if/then/else和do/while的流程控制;e)用户可以自定义函数;f) 简单的错误恢复机制。
2. 编写 Flex/Bison源文件,实现C 语言的语法分析功能,最后上机调试。
3. 要求编写一个测试程序:首先自定义两个函数sq和avg,sq函数使用Newton方法来迭代计算平方根;avg函数计算两个数值的平均值。
利用定义好的函数进行计算,得到计算结果并显示出来。
4.根据习题1的要求,修改fb3-2相关代码;实现实现以下自定义函数,并保存为fb3-3。
函数示例:let sq(n){e=1; while (|((t=n/e)-e)>.001) do {e=avg(e,t);}}let avg(a,b){(a+b)/2;}let max(a,b) { if(a>b) then a; else b; }let max3(a,b,c) { if(a>b) then { if(a>c) then a; else c; }else { if(b>c) then b; else c; } }3.1.3 开发环境及工具介绍1、Window环境下载Visual Studio之后,利用其命令提示窗口进行操作。
下载并安装Flex。
2、vs2010的编译器cl.exe。
3、flex:词法分析器Flex是用来生成程序的工具,他们所生成的程序能够处理结构化输入,最初的Flex是用来生成编译器的,但是后来他们被证明在其他领域也非常有效。
使用flex和bison生成语法分析器:首先对第一次实验中的词法分析器的程序进行修改:%option noyywrap%{#include<stdio.h>#include<stdlib.h>#include"biso.tab.h"%}identifier_int [A-Za-z]([A-Za-z]|[0-9])*decimalism_int 0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*octonary_int 0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*hexadecimal 0(x|X)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* space [ \n\t]%%{space} { }"if" {return IF;}"then" {return THEN;}"else" {return ELSE;}"while" {return WHILE;}"do" {return DO;}"+" {return add;}"-" {return sub;}"*" {return mul;}"/" {return divi;}";" {return semicolon;}"=" {return equal;}">" {return greater_than;}"<" {return less_than;}"<=" {return LE;}">=" {return GE;}[A-Za-z]([A-Za-z]|[0-9])* {return IDE;}(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*|0 {return INT10;}0(0|1|2|3|4|5|6|7)+ {return INT8;}0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* {return INT16;} "(" {return left_bracket;}")" {return right_bracket;}%%我们可以看到,相较于第一个实验中的头文件,宏定义全部删除,增加了一个头文件,biso.tab.h,这个头文件是bison代码编译后生成的文件,在这个文件中,我们可以看到实验一中所有宏定义。
实验四借助Flex/Bison进行语法分析一.说明:利用附录提供的C语言文法的相关参考资料,利用Yacc/Bison编写一个C语言分析器。
二.具体内容:利用语法分析器生成工具Bison编写一个语法分析程序,与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。
三.实验要求:实验资料如下:3.1 阅读Flex源文件input.lex、Bison源文件cgrammar-new.y。
3.2 实现C 语言的语法分析功能,最后上机调试。
3.3 生成语法分析程序2_2.exe,以给定的测试文件作为输入,输出运行结果到输出文件中。
四.实验过程:(1)执行以下命令,生成lex.yy.c、cgrammar-new.tab.h、cgrammar-new.tab.c。
(2)cgrammar-new.y有移近规约冲突。
执行命令bison -d cgrammar-new.y 后,Bison提示移近规约冲突“cgrammar-new.y: conflicts: 1 shift/reduce”。
以Bison的"-v"选项生成状态机描述文件cgrammar-new.output,即执行bison -d cgrammar-new.y。
cgrammar-new.output文件内容如下:修改以下两处:2.1 在yacc的头部加入%nonassoc LOWER_THAN_ELSE%nonassoc ELSE2.2 在355行加入%prec LOWER_THAN_ELSE(3)编译使用cl.exe或gcc编译器,编译lex.yy.c cgrammar-new.tab.c main.c parser.c。
使用cl.exe编译后,得到以下错误提示:修改lex.yy.c,使其能顺利编译。
3.1 将lex.yy.c中的#ifdef __cplusplusstatic int yyinput()#elsestatic int input()#endif改为static int yyinput()2.2 将lex.yy.c中的#ifdef __cplusplusreturn yyinput();#elsereturn input();#endif改为return yyinput();(3)生成可执行文件2_2.exe,并分析源文件test.c。
课程: 编译原理在Windows平台下使用Flex和Bison
实验报告
系
专业
班级
姓名
学号
指导教师
实验2.4 在Windows平台下使用Flex和Bison 1.实验目的
1. 学习使用词法分析程序自动构造工具Flex和语法分析程序自动构造工具Bison
2.实验平台
Windows + Flex + Bison
范例程序:calc.lex
calc.y
3.实验内容
1. 实现以下步骤, 掌握Flex和Bison的工作过程
a) 在DOS 命令提示符下依次执行以下两行命令
flex -olexyy.c calc.lex
bison -ocalc.c calc.y
b) 编译运行calc.c
c) 分析运行结果
2. 请在范例程序的基础上增加更多的功能
4.具体实验步骤
1) 转到正确路径下
2) 输入命令flex -olexyy.c calc.lex
3) 出现lexyy.c文件
4) 执行命令
5) 出现calc.c文件
6) 用vc++6.0编译calc.c文件,并运行两个算是显示结果正确
7) 错误命令测试
5.请在范例程序的基础上增加更多的功能
利用flex和bison编译出一个exe文件
6.感悟与收获
通过本次试验我们得到很多,不经了解了flex和bison的运行方式而且知道了怎么建立.exe组建。
我们根据范例代码了解了在dos环境下运行方式。
测试方面,我们收获也很多,了解测试时要考虑全面。
试验不足,没能分析错执行错误原因。
词法分析器生成工具flex1.FLEX简介单词的描述称为模式(Lexical Pattern),模式一般用正规表达式进行精确描述。
FLEX通过读取一个有规定格式的文本文件,输出一个如下所示的C语言源程序。
+------------+ +------------+ +----------------+| 输入文件*.l |------>|flex工具 |------>|输出文件lex.yy.c |+------------+ +------------+ +----------------+FLEX的输入文件称为LEX源文件,它内含正规表达式和对相应模式处理的C语言代码。
LEX 源文件的扩展名习惯上用.l表示。
FLEX通过对源文件的扫描自动生成相应的词法分析函数int yylex(),并将之输出到名规定为lex.yy.c的文件中。
实用时,可将其改名为lexyy.c。
该文件即为LEX的输出文件或输出的词法分析器。
也可将int yylex()加入自已的工程文件中使用。
2. LEX源文件的格式LEX对源文件的格式要求非常严格,比如若将要求顶行书写的语句变成非顶行书写就会产生致命错误。
而LEX本身的查错能力很弱,所以书写时一定要注意。
下面以统计单词出现的次数的源程序count.l做说明,count.l的内容如下:%{#include "stdio.h"#include "stdlib.h"int num_num=0,num_id=0;%}INTEGER [-+]?[1-9][0-9]*ID [a-zA-Z][a-zA-Z_0-9]*SPACE [ /n/t]%%{INTEGER} { num_num++;printf("(num=%d)/n",atoi(yytext));/*打印数字值*//*数字数加一*/}{ID} { num_id++;printf("(id=%s)/n",yytext);}{SPACE} |. {/*什么也不做,滤掉白字符和其它字符*/}%%int main(){yylex();printf("num=%d,id=%d/n",num_num,num_id);return 0;}int yywrap()//此函数必须由用户提供{return 1;}定义部份由C语言代码、模式的宏定义、条件模式的开始条件说明三部份组成。
课程设计3 基于Flex/Bison的高级解释器设计及实现3.1 需求分析3.1.1 问题定义1.使用flex和bison开发了一个具有全部功能的桌面计算器,能够支持变量,过程,循环和条件表达式,使它成为一个虽然短小但是具有现实意义的编译器。
2.重点学习抽象语法树的用法,它具有强大而简单的数据结构来表示分析。
3.1.2 功能描述1.计算器具体需要实现的功能:a)变量命名;b)实现赋值功能;c)实现比较表达式(大于、小于、等于等等)d)实现if/then/else和do/while的流程控制;e)用户可以自定义函数;f) 简单的错误恢复机制。
2. 编写 Flex/Bison源文件,实现C 语言的语法分析功能,最后上机调试。
3. 要求编写一个测试程序:首先自定义两个函数sq和avg,sq函数使用Newton方法来迭代计算平方根;avg函数计算两个数值的平均值。
利用定义好的函数进行计算,得到计算结果并显示出来。
4.根据习题1的要求,修改fb3-2相关代码;实现实现以下自定义函数,并保存为fb3-3。
函数示例:let sq(n){e=1; while (|((t=n/e)-e)>.001) do {e=avg(e,t);}}let avg(a,b){(a+b)/2;}let max(a,b) { if(a>b) then a; else b; }let max3(a,b,c) { if(a>b) then { if(a>c) then a; else c; }else { if(b>c) then b; else c; } }3.1.3 开发环境及工具介绍1、Window环境下载Visual Studio之后,利用其命令提示窗口进行操作。
下载并安装Flex。
2、vs2010的编译器cl.exe。
3、flex:词法分析器Flex是用来生成程序的工具,他们所生成的程序能够处理结构化输入,最初的Flex是用来生成编译器的,但是后来他们被证明在其他领域也非常有效。
Flex是一个SourceForge项目。
其依赖于GNU m4宏处理器。
Linux和BSD都应该有m4,对于Windos用户来说,Flex被包含在Cygein Linux模拟环境中。
什么是FLEX?它是一个自动化工具,可以按照定义好的规则自动生成一个C 函数yylex(),也成为扫描器(Scanner)。
这个C函数把文本串作为输入,按照定义好的规则分析文本串中的字符,找到符合规则的一些字符序列后,就执行在规则中定义好的动作(Action)。
例如在规则中可以这样定义:如果遇到一个换行字符\n,那么就把行计数器的值加一。
Flex文件就是一个文本文件,内容包括定义好的一系列词法规则。
4、bison:语法分析器GNU bison 是属于 GNU 项目的一个语法分析器生成器。
Bison 把一个关于“向前查看从左到右最右”(LALR) 上下文无关文法的描述转化成可以分析该文法的 C 或 C++ 程序。
它也可以为二义文法生成“通用的从左到右最右”(GLR)语法分析器。
Bison是一种通用目的的分析器生成器。
它将LALR(1)上下文无关文法的描述转化成分析该文法的C程序。
一旦你精通Bison,你可以用它生成从简单的桌面计算器到复杂的程序设计语言等等许多语言的分析器。
Bison 基本上与 Yacc 兼容,并且在 Yacc 之上进行了改进。
它经常和Flex (一个自动的词法分析器生成器)一起使用。
此软件的源代码是可自由获得的,在 GPL 下发布。
3.2 系统概要设计3.2.1 系统体系结构本实验计算器系统是基于抽象语法树的改进的计算器,在fb3-3.h 的文件中实现声明部分,在fb3-3.l 文件中实现计算器对应的词法分析,在fb3-3.y 文件实现计算器的语法语义分析部分,在fb3-3funcs.c 文件对应的是相应的计算器的C 语言的代码。
之后利用Visual Studio 命令提示实现计算器的功能。
结构图如下:声明部分计算器词法分析语法语义分析C 语言代码fb3-3.funcs.cfb3-3.yfb3-3.lfb3-3.h图3-1 系统体系结构图计算器系统流程图:开始计算式词法分析器读取标识符语法分析器处理判断节点类型建立相应节点求值输出结果释放结束图3-2 系统流程图3.2.2 系统模块划分(1)fb3-3.h文件头声明部分我们要做开始声明部分,在.h 头文件中我们可以用以下语句来定义抽象语法树的struct ast {int nodetype;struct ast *l;struct ast *r;}; 且所有节点都有公共的初始 nodetype。
而删除和释放抽象语法树可以用语句 void treefree(struct ast *)来实现即可。
常量使用 numval,符号引用使用 symref 赋值使用 symasgn,它有一个指向被赋值符号的指针和使用抽象语法树表示的值;(2)fb3-3.l文件词法分析部分词法分析器中设计六个比较操作符都返回一个带有字面值以便于区分的CMP 记号,其中这六个关键字和四个内置函数通过文字模式加以识别,它们放在通用模式之前以便于在通用模式之前进行匹配;利用符号表进行词法分析,其中符号表中记录输入中使用的名称以及常用的符号。
在这部分需要注意与C语言的交叉使用,对于每一类的词法分析须严格按照正则表达式来实现。
(3)fb3-3.y文件语法分析部分语法分析器的设计,其中在语法分析器的最后提供了小部分错误恢复机制,这让我们有可能在错误发生时把语法分析器恢复到可以继续工作的状态;在这一部分我们为每个表达式建立了抽象语法树,以抽象语法树为单位进行计算,并打印出结果,并释放语法树。
在这一部分需考虑移进/规约冲突和操作符的优先级,一定要在此代码中区分语句(stmt)和表达式(exp)。
(4)fb3-3funcs.c文件C语言代码部分在这一部分的文件中语法分析器及.y文件需要调用其中的函数,创建语法树节点、分配节点进行填充、遍历抽象语法树。
最后还要加一个辅助函数,正如《flex 与 bison》中所讲的一样,例程 treefree 的扩展版本会递归的遍历一颗抽象语法树并释放这棵树的所有节点。
本计算器的核心例程是 eval,它用来计算分析器中构造的抽象语法树。
我们采用深度优先遍历算法来计算表达式的值;3.2.3系统的数据流图在系统中,用户在输入要计算的内容后,先进行词法分析和语法分析,之后再判断用户要计算的类型是哪种四则运算,系统运算之后将结果返回给用户,数据流图如下: 用户计算器词法分析语法语义分析进行计算用户输入计算数据进行词法分析进行语法分析计算运算结果返回用户 图3-3 系统数据流图3.3 详细设计与实现3.3.1 fb3-3..h 文件模块的设计与实现在这部分中,主要是对整个系统中的头文件的说明。
首先我们要做开始声明部分,在.h 头文件中我们可以用以下语句来定义抽象语法树的节点,且所有节点都有公共的初始nodetype 。
而删除和释放抽象语法树可以用语句voidtreefree (struct ast *) 来实现即可。
常量使用numval, 符号引用使用symref 赋值使用symasgn, 它有一个指向被赋值符号的指针和使用抽象语法树表示的值;在代码的一开始是说明与词法分析器的接口,其中的变量yylineno 来自词法分析器,接下来的部分用于构造抽象语法树,抽象语法树有多个节点组成,每个节点都有一个节点类型。
不同的节点可以有不同的域,但是在这个文件中有八种不同类型的指针。
之后一部分是对抽象语法树的操作,首先用eval 遍历抽象语法树,返回它所代表的表达式的值,之后删除和释放抽象语法树。
下一部分是对符号表的声明,其中symbol为变量名,func为函数体,syms为虚拟参数列表。
之后建立一个符号列表,并将其作为参数列表。
在这个计算器中,每个符号都有一个变量和一个用户自定义函数。
value域用来保存符号的值,func域指向用抽象语法树表达的该函数的用户代码,而sym域指向任意多个虚拟参数的链表,这些参数也是符号。
函数newsymlist和symlistfree创建和释放符号。
下面抽象语法树的声明:struct ast *newast(int nodetype, struct ast *l, struct ast *r);struct ast *newcmp(int cmptype, struct ast *l, struct ast *r);struct ast *newfunc(int functype, struct ast *l);struct ast *newcall(struct symbol *s, struct ast *l);struct ast *newref(struct symbol *s);struct ast *newasgn(struct symbol *s, struct ast *v);struct ast *newnum(double d);struct ast *newflow(int nodetype, struct ast *cond, struct ast *tl, struct ast *tr);开始建立符号表建立固定大小的符号表声明符号表声明词法分析器接口声明抽象语法树结束图3-4 声明文件流程图开始识别运算符号处理浮点数单一字符操作符比较操作符关键字内置函数名字结束图3-5 词法分析程序流程图这一部分主要是进行语法和语义分析。
语法分析器的设计,其中在语法分析器的最后提供了小部分错误恢复机制,这让我们有可能在错误发生时把语法分析器恢复到可以继续工作的状态;在在代码的一开始%union定义了很多种符号值,符号值可以是符号表中特定用户符号、符号列表、比较子类型和函数记号的指针。
FUNC表示内置函数,它的值确定了具体的某个函数,另外6个保留字,从IF到Let。
记号CMP是6种比较操作符之一,它的值确定了具体的操作符。
优先级声明列表从新的CMP和=操作符开始,%start声明定义了顶层规则。
接下的部分区分了stmt和exp,语句是一个控制流或者是一个表达式。
每当规则匹配到一条语句时,他将调用相应的程序去创建合适的抽象语法树。
且list的定义是右递归的。
新的CMP规则处理6种比较操作符,它使用CMP的值来判断当前的操作符,还有一条赋值规则来创建赋值节点。
这一部分的程序流程图如下图所示:开始定义符号值声明记号规定计算语法表达式的语法顶层规划结束图3-6 语法部分流程图在这一部分,用C 语言进行创建抽象语法树和符号列表的过程,代码中对每一个节点进行分配,然后基于节点类型恰当地填充各个域,利用treefree 递归地遍历一棵抽象语法树,同时释放这棵树的所有节点。