基于FlexBison的高级解释器设计及实现
- 格式:docx
- 大小:477.12 KB
- 文档页数:16
flex编译原理教程Flex编译原理教程一、引言Flex(Fast Lexical Analyzer Generator)是一个快速的词法分析器生成工具,它能够将输入的正则表达式规则转化为有效的C代码,用于实现词法分析的过程。
本文将介绍Flex编译原理的基本概念和实现过程。
二、什么是词法分析词法分析是编译过程中的第一个阶段,它负责将源程序中的字符序列划分为有意义的词素(Token)序列。
词素是语言中的基本单位,例如关键字、标识符、常数、运算符等。
词法分析器的任务就是根据预先定义的词法规则,将输入的字符序列转化为词素序列。
三、Flex编译原理概述Flex的工作原理是基于有限状态自动机(Finite State Automaton)的。
它将词法规则表示成一系列正则表达式,并将其转化为NFA (Nondeterministic Finite Automaton)和DFA(Deterministic Finite Automaton)。
Flex会将这些自动机转化为C代码,从而实现词法分析器。
四、Flex编译原理详解1. 定义词法规则在Flex中,词法规则是用正则表达式表示的。
每个规则由两部分组成:模式(pattern)和动作(action)。
模式用于匹配输入字符序列,动作则指定匹配成功后的处理逻辑。
2. 构建NFA根据词法规则,Flex会构建一组NFA片段,每个片段对应一个词法规则。
NFA片段由一组状态和转移函数组成。
状态表示在词法分析过程中的不同状态,转移函数表示状态之间的转换关系。
3. 合并NFA将所有NFA片段合并成一个大的NFA。
合并的过程中,Flex会将各个片段的接受状态通过ε转移链接在一起,形成新的接受状态。
4. 子集构造法通过子集构造法将NFA转化为DFA。
子集构造法的基本思想是根据当前状态和输入字符,确定下一个状态。
通过不断迭代,直到构造出完整的DFA。
5. DFA最小化对生成的DFA进行最小化处理,去除一些不可达状态和等价状态,减少状态的数量。
FLEX 中文手册这是flex手册的部分中文翻译,仅供参考•一些简单的例子•输入文件的格式•模式•如何匹配输入•动作•生成的扫描器•开始条件•文件结尾规则•与yacc一起使用一些简单的例子首先给出一些简单的例子,来了解一下如何使用flex。
下面的flex输入所定义的扫描器,用来将所有的“username”字符串替换为用户的登陆名字:%% username printf("%s", getlogin());默认情况下,flex扫描器无法匹配的所有文本将被复制到输出,所以该扫描器的实际效果是将输入文件复制到输出,并对每一个“username”进行展开。
在这个例子中,只有一个规则。
“username”是模式(pattern),“printf”是动作(action)。
“%%”标志着规则的开始。
这里是另一个简单的例子:int num_lines = 0, num_chars = 0;%% \n ++num_lines; ++num_chars; . ++num_chars;%% int main(void){yylex();printf("# of lines = %d, # of chars = %d\n", num_lines, num_chars);}该扫描器计算输入的字符个数和行数(除了最后的计数报告,并未产生其它输出)。
第一行声明了两个全局变量,“num_lines”和“num_chars”,可以在yylex()函数中和第二个“%%”后面声明的main()函数中使用。
有两个规则,一个是匹配换行符(“\n”)并增加行数和字符数,另一个是匹配所有不是换行符的其它字符(由正规表达式“.”表示)。
一个稍微复杂点的例子:/* scanner for a toy Pascal-like language */%{/* need this for the call to atof() below */#include <math.h>%}DIGIT [0-9] ID [a-z][a-z0-9]*%%{DIGIT}+ {printf( "An integer: %s (%d)\n", yytext,atoi( yytext ) );}{DIGIT}+"."{DIGIT}* {printf( "A float: %s (%g)\n", yytext,atof( yytext ) );}if|then|begin|end|procedure|function {printf( "A keyword: %s\n", yytext );}{ID} printf( "An identifier: %s\n", yytext );"+"|"-"|"*"|"/" printf( "An operator: %s\n", yytext );"{"[^}\n]*"}" /* eat up one-line comments */[ \t\n]+ /* eat up whitespace */. printf( "Unrecognized character: %s\n", yytext );%%int main(int argc, char **argv){++argv, --argc; /* skip over program name */if ( argc > 0 )yyin = fopen( argv[0], "r" );elseyyin = stdin;yylex();}这是一个类似Pascal语言的简单扫描器的初始部分,用来识别不同类型的标志(tokens)并给出报告。
课程设计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。
结构化文本语言编译器的虚拟机指令设计与优化陈宏君;张磊【摘要】In order to independently develop the IEC6 1131 structured text (ST) language compiler,a virtual machine instruction set irrel-evant to the machine is developed,which is classified by functions such as data transmission,arithmetic operation,logic operation,bit op-eration,compare operation,process control and function call,and the quaternary representation of three-address code is adopted.Based on the instruction set,the instruction forming algorithms for IF,FOR,CASE and EXIT statements of structured text are designed,and the compiler can compile the language of the structured text into binary instruction files.Moreover,three translation modes are put forward for the For statement,named "Count Up","Count Down" and "Dynamically Determine Upper and Lower",and the translation mode based on the mixture of short-circuit evaluation and jump table are put forward,which can optimize the instruction structure of FOR and CASE statements.In addition,the binary instructions formed in compilation are further optimized by the constant folding operation,alge-braic simplification,temporary variable elimination,invocation point analysis and other approaches.The test results show that the opti-mized instructions have improved the efficiency of interpretation and execution in the embedded industrial control devices.%针对自主开发 IEC61131结构化文本(ST)语言编译器的需求,设计了一套机器无关的虚拟机指令集,指令集按照数据传送、算术运算、逻辑运算、位操作、比较操作、流程控制、函数调用等类型划分,采用三地址码的四元式表示.基于该指令集,设计了结构化文本语言的 IF语句、FOR 语句、CASE语句、EXIT语句的指令形成算法,编译器将结构化文本语言编译为二进制指令文件.针对FOR语句提出了"向上计数"、"向下计数"、"动态确定上下限"的3种翻译模式,针对CASE语句提出了基于短路求值和跳转表混合的翻译模式,可优化FOR语句、CASE语句的指令结构.对编译形成的二进制指令,采用常量折叠计算、代数简化、临时变量消除、引用点分析等手段,进一步优化指令.实验测试结果表明,优化后的指令在嵌入式工控装置中的解释执行时提升了效率.【期刊名称】《单片机与嵌入式系统应用》【年(卷),期】2018(018)005【总页数】6页(P23-27,48)【关键词】结构化文本;虚拟机指令;三地址码;指令优化【作者】陈宏君;张磊【作者单位】南京南瑞继保电气有限公司,南京 211102;南京南瑞继保电气有限公司,南京 211102【正文语种】中文【中图分类】TP314引言IEC61131是国际电工委员会(IEC)颁布的可编程控制器(PLC)国际标准,用于规范可编程控制器编程工具和应用程序的开发,目的是便于各厂家的应用程序移植,降低用户的使用难度和维护成本[1-5]。
课程: 编译原理在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环境下运行方式。
测试方面,我们收获也很多,了解测试时要考虑全面。
试验不足,没能分析错执行错误原因。
arm 系统中flexnoc 的原理ARM系统中的FlexNoC原理概述:FlexNoC是ARM(Advanced RISC Machines)公司开发的一种高性能、低功耗的片上网络(Network-on-Chip)技术。
它被广泛应用于ARM处理器的设计中,用于实现片上各个模块之间的通信和数据传输。
本文将详细介绍FlexNoC的原理和工作机制。
1. FlexNoC的基本概念FlexNoC是一种基于NoC架构的片上网络,具有高度可配置和可扩展的特点。
NoC(Network-on-Chip)是一种用于替代传统的总线结构的通信架构,通过将片上各个模块连接成网络的形式,实现模块之间的通信。
FlexNoC在NoC的基础上进行了优化和改进,提供了更高的性能和更低的功耗。
2. FlexNoC的核心组成部分FlexNoC主要由以下几个核心组成部分构成:(1)路由器(Router):FlexNoC中的路由器是网络的核心,负责实现数据包的转发和路由选择功能。
路由器采用了自适应的路由算法,根据网络状况智能选择最优的路径进行数据传输。
(2)链路(Link):链路是连接路由器之间的通道,用于传输数据包。
FlexNoC中的链路采用了全双工的通信方式,可以同时进行发送和接收操作,提高了数据传输的效率。
(3)虚拟通道(Virtual Channel):虚拟通道是FlexNoC中的一种重要机制,用于实现不同模块之间的隔离和并行传输。
每个路由器都具有多个虚拟通道,可以同时传输多条数据,提高了网络的带宽和吞吐量。
(4)调度器(Scheduler):调度器用于控制数据包在网络中的传输顺序,避免数据的冲突和竞争。
FlexNoC的调度器采用了优先级调度算法,根据数据包的优先级进行调度,提高了系统的响应速度和性能。
(5)缓存(Cache):缓存用于存储数据包和中间结果,减少对外部存储器的访问次数,提高了数据传输的效率和响应速度。
FlexNoC中的缓存采用了多级缓存结构,可以根据不同的访问模式进行灵活的配置和调整。
江南大学物联网工程学院实验报告课程名称编译原理实验名称FLEX与BISON的计算器实现实验日期 2015-12-11 班级计科1301 姓名曹长兴学号 1030413111 实验报告要求 1.实验名称 2.实验要求 3.实验环境 4.实验步骤 5.实验体会一、实验目的:基于词法分析程序自动构造工具Flex与语法分析程序自动构造工具Bison,编制简单的计算器程序。
二、实验内容:1. 由实验一学习的方法,编译得到示例代码的计算器可执行程序(注意:编译前将libfl.lib文件也添加到项目中)。
通过使用该程序,了解该示例程序的不足。
2. 参考示例程序, 用Flex和Bison实现一个功能更为强大的计算器,尽可能多的包含以下运算(支持浮点数):三、实验环境Windows xp Flex + Bison四、实验步骤(附件见文件末)1.首先添加各类运算的逻辑规则;需要添加math.h分别添加调用函数pow();sqrt();sin();cos();log();log10()一一对应之前的运算求模是%;求阶乘的话需要添加一个递归函数;!添加的时候要注意优先级的问题,^ % sin cos等优先级很高,我们写到最后term里面。
2.使得浮点类型可以运算,原工具代码是int型,我们来将他修改为浮点型(这里用double)(难点)a.修改正则表达式,原代码[0-9]+,改为([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?)。
这个表达式比较全面,其实可以更简单一点(但为了省去各种bug带来不必要的麻烦,这里选用一个全面的)。
b.定义一个全局变量double型的double dval;c.原代码是将字符串型转换为int型,我们需要转换为double,所以将atoi修改为atof方法,并将这个浮点型存入浮点变量中。
{ yylval.dval = atof(yytext); return NUMBER; }d.接着,还要把优先级的几个变量也改为浮点型。
课程设计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 声明文件流程图词法分析器中设计六个比较操作符都返回一个带有字面值以便于区分的CMP 记号,其中这六个关键字和四个内置函数通过文字模式加以识别,它们放在通用模式之前以便于在通用模式之前进行匹配; 该词法分析器能够实现基本的词法分析功能如行数、关键字个数、单词个数以及简单注释等的判别。
这部分流程图开始识别运算符号处理浮点数单一字符操作符比较操作符关键字内置函数名字结束图3-5 词法分析程序流程图这一部分主要是进行语法和语义分析。
语法分析器的设计,其中在语法分析器的最后提供了小部分错误恢复机制,这让我们有可能在错误发生时把语法分析器恢复到可以继续工作的状态;在在代码的一开始%union定义了很多种符号值,符号值可以是符号表中特定用户符号、符号列表、比较子类型和函数记号的指针。
FUNC表示内置函数,它的值确定了具体的某个函数,另外6个保留字,从IF到Let。
记号CMP是6种比较操作符之一,它的值确定了具体的操作符。
优先级声明列表从新的CMP和=操作符开始,%start声明定义了顶层规则。
接下的部分区分了stmt和exp,语句是一个控制流或者是一个表达式。
每当规则匹配到一条语句时,他将调用相应的程序去创建合适的抽象语法树。
且list的定义是右递归的。