安徽大学编译原理试验三

合集下载

编译原理 实验报告

编译原理 实验报告

编译原理实验报告编译原理实验报告引言编译原理是计算机科学中的重要课程,它研究的是如何将高级语言程序转化为机器语言程序的过程。

在本次实验中,我们学习了编译原理的基本概念和技术,并通过实践来加深对这些概念和技术的理解。

本报告将对我们在实验中遇到的问题、解决方案以及实验结果进行总结和分析。

实验目的本次实验的主要目的是设计并实现一个简单的编译器,能够将类C语言的源代码翻译成目标代码。

通过这个实验,我们可以更好地理解编译器的工作原理,掌握编译器设计的基本方法和技术。

实验过程在实验中,我们首先对给定的类C语言的语法进行了分析,并根据语法规则设计了相应的语法分析器。

然后,我们使用了自顶向下的递归下降分析法来实现语法分析器。

在实现语法分析器的过程中,我们遇到了一些问题,例如如何处理语法规则中的左递归、如何处理语法规则中的优先级和结合性等。

通过仔细研究相关的文献和资料,我们成功地解决了这些问题,并完成了语法分析器的设计和实现。

接下来,我们对语法分析器进行了测试,并对测试结果进行了分析。

通过测试,我们发现语法分析器在处理简单的源代码时能够正确地识别出语法错误,并给出相应的错误提示。

然而,在处理复杂的源代码时,语法分析器可能会出现一些错误,例如无法正确地处理嵌套的语法结构、无法正确地处理运算符的优先级和结合性等。

为了解决这些问题,我们对语法分析器进行了改进,并进行了多次测试,最终得到了令人满意的结果。

实验结果通过本次实验,我们成功地设计并实现了一个简单的编译器,能够将类C语言的源代码翻译成目标代码。

在实验中,我们对编译器的工作原理有了更深入的了解,掌握了编译器设计的基本方法和技术。

同时,我们也发现了一些问题,并通过不断地改进和测试,最终得到了令人满意的结果。

结论编译原理是一门重要的计算机科学课程,它研究的是如何将高级语言程序转化为机器语言程序的过程。

通过本次实验,我们对编译原理的基本概念和技术有了更深入的了解,并通过实践来加深了对这些概念和技术的理解。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。

本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。

二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。

此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。

三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。

在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。

首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。

然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。

在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。

对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。

(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。

在本次实验中,我们使用了递归下降的语法分析方法。

首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。

在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。

为了处理语法错误,在分析过程中添加了错误检测和处理机制。

当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。

(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。

在本次实验中,我们使用了三地址码作为中间代码的表示形式。

在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。

对于符合语义规则的语法结构,生成相应的三地址码指令。

四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。

安大编译原理期末习题集(有原题)

安大编译原理期末习题集(有原题)
105 (j,_,_,108)
106 (+, C, 1, C)
107 (j,_,_,112)
108 (j≤,A,D,110)
109 (j,_,_,112)
110 (+, A, 2, A)
111 (j,_,_,108)
112 (j,_,_,100)
113
5.已知文法G[S]为S → aSb|Sb|b,试证明文法G[S]为二义文法。
《编译原理》期末试题(一)
一、是非题(请在括号内,正确的划√,错误的划×)(每个2分,共20分)
1.编译程序是对高级语言程序的解释执行。(×)
2.一个有限状态自动机中,有且仅有一个唯一的终态。(×)
3.一个算符优先文法可能不存在算符优先函数与之对应。(√)
4.语法分析时必须先消除文法中的左递归。(×)
17.一张转换图只包含有限个状态,其中有一个被认为是(初)态;而且实际上至少要有一个(终 )态。
19.语法分析是依据语言的(语法 )规则进行。中间代码产生是依据语言的(语义)规则进行的。
21.一个文法G,若它的预测分析表M不含多重定义,则该文法是(LL(1) 文法)文法。
22.对于数据空间的存贮分配, FORTRAN采用( 静态策略, PASCAL采用( 动态)策略。
C.( )编译方法D.( )以上三项都是
6.四元式之间的联系是通过_____实现的。
A.( )指示器B.( )临时变量
C.( )符号表D.( )程序变量
7.表达式(┐A∨B)∧(C∨D)的逆波兰表示为_____。
A. ( ) ┐AB∨∧CD∨B.( ) A┐B∨CD∨∧
C.( ) AB∨┐CD∨∧D.( ) A┐B∨∧CD∨
8.优化可生成_____的目标代码。

安徽大学编译原理试验斯

安徽大学编译原理试验斯

不确定的有穷自动机的化简2015年11月25日星期三班级:软件工程学号: E21314003 姓名:李世1. 目的与要求通过设计、编写和调试,将不确定的有穷自动机转换为与之等价的确定的有穷自动机的程序,使学生了解子集法。

掌握转换过程中的相关概念和方法。

DFA的表现形式可以是表格或图形。

2. 理论基础有穷自动机(也称有限自动机)作为一种识别装置,它能准确地识别正规集,即识别正规式所表示的集合. 应用有穷自动机这个理论,为词法分析程序的自动构造寻找有效的方法和工具。

有穷自动机分为两类,即,确定的有穷自动机(Deterministic Finite Automata)和不确定的有穷自动机(Nondeterministic Finite Automata) 。

(1) 不确定的有穷自动机的定义:一个不确定的有穷自动机(NFA)M 是一个五元组:NFA M={K,Σ,f,S,Z},其中:K为状态的有穷非空集;Σ 为有穷输入字母表;f为K× Σ* 到K的子集(2K)的一种映射, 2K表示K的幂集(f不是一个单值函数);S⊆K是初始状态集;Z ⊆K为终止状态集.例子:NFA M=({S,P,Z},{0,1},f,{S,P},{Z}),其中:f(S,0)={P}//函数的结果为集合f(S,1)={S,Z}f(P,1)={Z}f(Z,0)={P}f(Z,1)={P}状态图表示为:矩阵表示为:(2) 确定的有穷自动机的定义:一个确定的有穷自动机(DFA)M是一个五元组:M=(K,Σ,f,S,Z)其中:K是一个有穷集,它的每个元素称为一个状态;Σ是一个有穷字母表,它的每个元素称为一个输入符号,所以也称Σ为输入符号表;f是转换函数,是在K×Σ→K上的映射,即,如f(ki,a)=kj,(ki ∈K,kj∈K)就意味着,当前状态为ki,输入符为a时,将转换为下一个状态kj,我们把kj称作ki的一个后继状态;S∈K是唯一的一个初态;Z⊂ K是一个终态集,终态也称可接受状态或结束状态。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、引言编译原理是计算机科学中的重要课程,它研究了将高级语言翻译为机器语言的方法和技术。

编译器作为实现这一目标的关键工具,扮演着至关重要的角色。

本实验报告将介绍编译原理实验的相关内容,包括实验目的、实验环境、实验步骤和实验结果等。

二、实验目的编译原理实验的主要目的是通过设计和实现一个简单的编译器,来加深对编译原理相关概念和技术的理解。

具体目标包括: 1. 理解词法分析、语法分析、语义分析等编译器的基本原理和流程; 2. 掌握使用Lex和Yacc工具进行词法分析和语法分析的方法; 3. 学会使用C/C++等编程语言实现编译器的基本功能。

三、实验环境本实验使用的实验环境包括: 1. 操作系统:Windows 10; 2. 开发工具:Visual Studio Code; 3. 编程语言:C/C++; 4. 辅助工具:Lex、Yacc。

四、实验步骤本实验的主要步骤如下:4.1 设计语言文法在开始实验之前,我们首先需要设计我们要实现的编程语言的文法。

文法是描述编程语言语法结构的形式化规则,它指定了合法的语法结构和语句构造方法。

我们可以使用BNF(巴科斯范式)或EBNF(扩展巴科斯范式)来表示文法。

4.2 实现词法分析器词法分析器的主要任务是将输入的字符流转换为一个个的词法单元(token)。

词法单元是编程语言中的最小语法单位,例如关键字、标识符、常量等。

我们可以使用Lex工具来实现词法分析器,它可以根据我们定义的正则表达式规则来生成词法分析器的代码。

4.3 实现语法分析器语法分析器的主要任务是根据语言文法,将词法单元序列转换为语法树。

语法树是描述程序语法结构的一种树状数据结构,它可以帮助我们理解和处理程序的语义。

我们可以使用Yacc工具来实现语法分析器,它可以根据我们定义的文法规则来生成语法分析器的代码。

4.4 实现语义分析器语义分析器的主要任务是对语法树进行遍历和分析,检查程序中的语义错误并生成中间代码。

安徽大学编译原理实验

安徽大学编译原理实验

编译原理实验报告实验名称:实验4 LL(1)文法分析院系:计算机学院专业:科技专业年级:11 级姓名:XXX学号:E01114xxx实验4 LL(1)文法判别实验名称:LL(1)文法的判别实验要求:输入一个文法G[S],判别其是否为LL(1)文法。

输入任意文法消除左递归消除左因子测试任意输入语句是否合法数据结构描述算法说明输出first集合输出follow集合输出LL(1)表实验目的:设计、编制、调试一个具体的LL(1)语法分析程序,加深对语法分析原理的理解。

1.掌握LL(1)分析法的基本原理2.掌握LL(1)分析表的构造方法3.掌握LL(1)驱动程序的构造方法4.加深对预测分析LL(1)分析法的理解。

实验原理:1. LL(1)文法定义一个上下文无关文法G是LL(1)文法, 当且仅当对G中每个非终结符A的任何两个不同的规则A→α|β,满足 SELECT(A→α)∩SELECT(A→β) = Φ其中α、β中至多只有一个能推出ε串。

◆含义:第一个L表示从左到右扫描输入串第二个L表示自上而下进行最左推导1表明只需向前看一个符号便可以决定选哪条产生式进行推导,类似地LL(k)文法需要向前看k个符号才可以确定选用哪个产生式。

2. LL(1)文法的判别◆五步判别法✓求能推出ε的非终结符集✓计算每个产生式右部α的FIRST(α)集✓计算每个非终结符A的FOLLOW(A)集✓计算每个产生式A→α的SELECT(A→α)集✓按LL(1)文法的定义判别☞假定所给文法是经过压缩的(不包含多余规则)3. 算法◆初始化置数组X[ ]中对应每一非终结符的标记为初值“未定”;◆扫描文法中的产生式①删除右部含有终结符的产生式,假使以某一非终结符为左部的所有产生式都被删除,并将数组中对应该非终结符的标记值改为“否”,说明该非终结符不能推出ε;②删除右部仅为ε的产生式,则将数组中对应该非终结符的标志置为“是”,说明该非终结符能推出ε;☞本次扫描后仅剩下产生式左右均为非终结符的产生式◆扫描产生式右部的每一符号①若所扫描到的非终结符号在数组中对应的标志为“是”,则删去该非终结符,若这使产生式右部为空,则对产生式左部的非终结符在数组中对应的标志改“是”,并删除该非终结符为左部的所有产生式②若所扫描到的非终结符号在数组中对应的标志为“否”,则删去该产生式,若这使产生式左部非终结符的有关产生式都被删去,则把在数组中该非终结符对应的标志改成“否”◆重复(3)直到扫描完毕数组中非终结符对应的特征再没有改变为止。

安徽建工编译原理实验及程序

安徽建工编译原理实验及程序

※<实验一词法分析>一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

本实验中,采用的是一类符号一种别码的方式。

2、单词的BNF表示<标识符- <字母<字母数字串<字母数字串-<字母<字母数字串|<数字<字母数字串|<下划线<字母数字串|ε<无符号整数- <数字<数字串<数字串- <数字<数字串 |ε<加法运算符- +<减法运算符- -<大于关系运算符-<大于等于关系运算符-=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。

如当前待分析字符串为“a+”,当前字符为’’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。

于是分析器读入下一个字符’+’,这时可知应将’’解释为大于运算符。

但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。

在分析标识符,无符号整数等时也有类似情况。

4、模块结构三、实验过程和指导:(一)准备:1.阅读课本有关章节,明确语言的语法,写出基本保留字、标识符、常数、运算符、分隔符和程序例。

2.初步编制好程序。

3.准备好多组测试数据。

(二)上课上机:将源代码拷贝到机上调试,发现错误,再修改完善。

编译原理的实验报告

编译原理的实验报告

一、实验目的1. 理解编译原理的基本概念和原理。

2. 掌握编译器的各个阶段及其实现方法。

3. 能够运用编译原理的知识解决实际问题。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 20194. 实验内容:词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成三、实验内容1. 词法分析(1)实验目的:实现一个简单的词法分析器,将源代码中的字符序列转换为词法符号序列。

(2)实验步骤:1)定义词法符号类型,包括标识符、关键字、运算符、常量等。

2)设计词法分析器算法,对源代码进行遍历,将字符序列转换为词法符号序列。

3)实现词法分析器程序,输出词法符号序列。

(3)实验结果:输入源代码:int a = 10;输出词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}2. 语法分析(1)实验目的:实现一个简单的语法分析器,将词法符号序列转换为抽象语法树(AST)。

(2)实验步骤:1)定义语法规则,包括产生式、非终结符、终结符等。

2)设计语法分析算法,根据语法规则对词法符号序列进行解析,生成AST。

3)实现语法分析器程序,输出AST。

(3)实验结果:输入词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}输出AST:```AST:- ExpressionStatement- Expression- BinaryExpression- Identifier: a- Operator: =- Constant: 10```3. 语义分析(1)实验目的:实现语义分析器,对AST进行语义检查,确保程序的正确性。

(2)实验步骤:1)定义语义规则,包括类型检查、作用域检查等。

编译原理实验报告

编译原理实验报告

编译原理实验报告
编译原理实验报告
本次实验主要涉及到编译原理中的词法分析和语法分析两个方面。

通过实验,我对编译原理的相关知识有了更深入的了解,并且掌握了一些基本的编译器设计技巧。

一、词法分析
词法分析是编译器的第一个阶段,其主要任务是将源程序中的字符序列转换成有意义的单词序列。

在本次实验中,我使用了Flex工具来生成词法分析器。

通过编写正则表达式和对应的动作,我成功地实现了对源程序中的关键字、标识符、常量、运算符等单词的识别和分类。

二、语法分析
语法分析是编译器的第二个阶段,其主要任务是将词法分析器生成的单词序列转换成语法树。

在本次实验中,我使用了Bison工具来生成语法分析器。

通过编写文法和对应的动作,我成功地实现了对源程序的语法分析和语法树的生成。

三、实验结果
通过本次实验,我成功地实现了一个简单的编译器,可以对源程序进行词法分析和语法分析,并生成相应的语法树。

在实验过程中,我遇到了一些问题,如正则表达式的编写、文法的设计等,但通过查阅资料和与同学的交流,我最终成功地解决了这些问题。

四、实验总结
本次实验让我深入了解了编译原理的相关知识,掌握了一些基本的编译器设计技巧。

通过实验,我不仅提高了自己的编程能力,还培养了自己的分析和解决问题的能力。

在今后的学习和工作中,我将继续深入学习编译原理的相关知识,不断提高自己的编程水平。

编译原理实验报告 (3)

编译原理实验报告 (3)
附录:源程序
#include <iostream>
#include <string>
using namespace std;
string keywords[8]={"do","end","for","if","printf","scanf","then","while"};
string optr[4]={"+","-","*","/"};
{
st="";
row++;
while(IsLetter(instring[j])||IsDigit(instring[j])||instring[j]=='_')
{
st+=instring[j];
j++;
}
if(IsKey(st)) //判断是否为关键字查询关键字表;
cout<<st<<"\t("<<st<<","<<1<<")"<<'\t'<<'\t'<<"关键字"<<'\t'<<"("<<line<<","<<row<<")"<<endl;
else {cout<<">"<<"\t("<<">"<<","<<4<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;j--;}break;

编译原理中实验报告

编译原理中实验报告

实验名称:编译原理实验实验时间:2023年X月X日实验地点:实验室实验指导老师:XXX一、实验目的1. 理解编译原理的基本概念和流程。

2. 掌握词法分析和语法分析的基本方法。

3. 学习编译器生成中间代码和目标代码的过程。

4. 培养编程能力和问题解决能力。

二、实验内容本次实验主要包括以下内容:1. 词法分析:编写一个简单的词法分析器,将源代码输入转换为抽象语法树(AST)。

2. 语法分析:实现一个简单的递归下降解析器,对词法分析器输出的AST进行语法分析。

3. 中间代码生成:根据AST生成三地址代码(Three-Address Code)。

4. 代码优化:对生成的三地址代码进行优化。

5. 目标代码生成:将优化后的三地址代码转换为机器代码。

三、实验步骤1. 设计词法分析器首先,我们需要设计一个能够识别源代码中各种单词的词法分析器。

在本实验中,我们定义了以下几种单词:- 关键字:如if、else、while、int、float等。

- 标识符:由字母、数字和下划线组成,不能以数字开头。

- 常量:包括整型常量和浮点型常量。

- 运算符:如+、-、、/、==、<=等。

- 分隔符:如(、)、;、,等。

根据以上定义,我们可以编写一个词法分析器,它将输入的源代码字符串逐个字符地读取,并根据定义的规则识别出相应的单词。

2. 语法分析词法分析器生成的AST是一个树形结构,其中每个节点代表源代码中的一个单词或符号。

为了进一步分析AST的结构,我们需要实现一个递归下降解析器,它能够根据语法规则对AST进行解析。

在本实验中,我们以一个简单的算术表达式为例,实现了一个递归下降解析器。

解析器从AST的根节点开始,按照语法规则递归地解析每个子节点,直到整个表达式被解析完毕。

3. 中间代码生成在完成语法分析后,我们需要将AST转换为中间代码。

在本实验中,我们选择了三地址代码作为中间代码的形式。

三地址代码是一种表示赋值、条件判断和循环等操作的方式,它使用三个操作数和两个操作符来表示一个操作。

编译原理实验报告

编译原理实验报告
实验四: 设计一个表示01符号串集合的自动机,其中符号串至少包含1个0且长度必须大于等于2。并通过该自动机判断任意输入的符号串是否合法符号串。
实验五: 设计一个算法,求出任一上下文无关文法中所有导空符号,并输出。
实验六: 检查某段C源程序中,标识符的使用是否正确,即是否先声明后使用,或重复声明。假设数据类型只有int,float,double,char。
break;
}
if(temp[n*13+n2]=='k'&&zt[m]==0) //那些不能推出 空,但是因为要加入 其他非终结符的first集 而可能含有 空
n2++;
else if(n3>=n1) //for循环结束是因为n3而不是break ,即无相同字符
while(temp[n*13+n2]!='\0') //把z[n]对应的first加入temp[m*13+n1]这个first中,每个字符依次加在最后
{
for(n3=0;n3<n1;n3++) //循环判定是否有相同的字符
{
if(temp[m*13+n3]==temp[n*13+n2])
}
n++;
}
break; //break位于if(gs[n]==z2[m]),对于gs[n]已找到z2[m]完成任务跳出for循环
}
}
n2=m; //存放该for循环中m的值
n++;
}
//进一步处理集除去非终结符
m=0;n=0;n1=0;n2=0;
else n2++;

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的一门重要课程,通过实验,旨在加深对编译原理相关理论知识的理解,提高实践动手能力和问题解决能力。

具体目标包括:1、熟悉编译程序的基本结构和工作流程。

2、掌握词法分析、语法分析、语义分析及中间代码生成等主要阶段的实现方法。

3、培养运用编程语言实现编译算法的能力。

二、实验环境本次实验使用的编程语言为_____,开发工具为_____,操作系统为_____。

三、实验内容(一)词法分析词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个单词符号。

使用正则表达式和有限自动机的理论,设计并实现了词法分析器。

首先,定义了单词的类别,如标识符、关键字、运算符、常量等。

然后,根据不同单词类别的特征,编写了相应的正则表达式模式。

在实现过程中,通过对输入的源程序进行逐字符扫描,利用正则表达式匹配来识别单词,并将其分类存储。

(二)语法分析语法分析是编译过程的核心部分,其目的是确定输入的单词序列是否符合给定的语法规则。

采用了自顶向下的递归下降分析法和自底向上的算符优先分析法。

对于递归下降分析法,根据语法规则编写了相应的递归函数。

每个函数处理一种语法结构,通过递归调用实现对整个语法的分析。

算符优先分析法则通过定义算符的优先级和结合性,构建算符优先关系表,然后依据表进行语法分析。

(三)语义分析语义分析阶段主要检查语法正确的句子是否具有实际的意义,并进行类型检查、语义计算等操作。

在实现中,通过构建符号表来记录变量的信息,包括名称、类型、作用域等。

同时,在语法分析的过程中,根据语义规则进行相应的检查和计算。

(四)中间代码生成中间代码生成是将源程序转换为一种便于优化和目标代码生成的中间表示形式。

选择了三地址码作为中间代码。

在生成中间代码时,根据语法分析和语义分析的结果,按照一定的规则将源程序转换为三地址码的形式。

四、实验步骤1、需求分析仔细研究实验要求,明确各个阶段的任务和目标,确定所需的数据结构和算法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

词法分析器及其算法的设计与实现2015年11月11日星期三班级:13级软件工程学号: E21314003 姓名:李世(一).词法分析器的设计 1.1 目的与要求通过设计、编写和调试词法分析程序(又称扫描器),了解扫描器的组成结构,不同种类单词的识别方法,掌握由单词的词法规则出发,画出识别单词的状态转换图,然后再用程序实现的扫描器的设计方法。

1.2 词法分析器实现中的约定设计的扫描器可以是一个子程序,也可以是一个完整的程序,其输入是源程序字符串,输出是单词符号本身。

为简化编译程序的编写过程,对Simple 语言源程序的书写,可以做如下假定:(1) 假定Simple 语言采用自由格式书写;(2) 可以使用注释,用/*……*/或者//标识,但注释不能插在单词内部,注释要在一行内结束。

若在某一行的结束,没有遇到注释后面的结束标记,自动认为注释结束; (3) 一行可以有多个语句,一个语句也可以分布在多个行中,单词之间、语句之间可以插入任意空格,但单词中间不能有空格符号,单词中间也不能有回车换行符,即单词不能跨行书写;(4) 为了避免超前搜索、提高运行效率,假定关键字都是保留字。

(5) 1.3 词法分析器的总体设计(6) 词法分析器的功能时从源程序中读入一个个字符,依据一定的构词规则,识别出各类有用的单词。

图1为词法分析器的输入输出接口:对图1细化,可得词法分析程序的顶层数据流图,如图2所示:图1. 词法分析器的输入输出接口细化图2可得词法分析程序的详细数据流图:在词法分析程序的详细数据流图中,各个加工处理模块完成的功能如下:1.1读一行并显示:收到读下一行的命令后,从源程序读入一行,装入缓冲区buffer ,行计数器加1,并打印。

需要注意的是,回车换行在源程序(文本文件)中用两个字符0D 0A H 来表示,而用高级语言(C 语言)读入内存后,就用一个字符0AH 来表示,这是在用高级语言编写词法分析器时常被忽略而导致错误的原因。

1.2 读一非空字符:收到读入一个字符的命令后,从缓冲区读入一非空字符(空格的ASCII码为20H ),列计数器加1.若buffer 已空,则在读入一行,类计数器置0. 1.3 分类:根据单词的首字符决定对不同单词的处理。

1.4 识别标识符/关键字:当读入一个字母时,开始识别标识符和关键字,边拼写边从buffer 中读入下一个符号。

当读入一非字母、数字符号时,标识符识别已经完成。

但已经多读入一个符号,所以列图3. 词法分析程序的详细数据流图图2. 词法分析程序的顶层数据流图计数回退,减1。

然后查关键字表,判断拼出的符号串是否为关键字。

若是关键字,输出其种别码(token);否则识别的单词就是标识符,同时输出标识符及其种别码。

1.5 识别数值常数:当读入数字时,开始识别整数或实数。

边拼写边读入下一个符号,当遇到“.”时,还要继续拼写该常数(实数情况)。

如果遇到E或e,要识别带指数的常数。

如果遇到其他非数字符号时,数字常数识别完毕。

输出常数及其种别码。

1.6 处理注释/除号:当读入“/”时,开始识别注释或除号。

若是注释(“/*”)时,最后两个连续读入的符号应是“*/”,不再读入下一符号,列计数器不变。

当判定是除号“/”时,已多读入一个字符,列计算器减1,输出除号“/”的种别码。

同样可识别注释符号//。

1.7 识别界符和运算符识别其他界符,对于<、>、:等符号,还需要再读入下一个符号,判断是否为双界符。

若不是,列计数器减1,输出单词的种别码。

1.8 识别文字常数:当读入单引号时,忽略它,开始拼写字符常数,不断读入下一个符号,搜索下一个单引号,当读入下一个单引号时,字符常数拼写结束。

最后列计数器不减1,然后输出该常数。

注:以上加工1.4~1.8都需要从buffer中每次读入一个字符,进行列计数。

由于假定每个单词不跨行,所以不用考虑从源程序中读出下一行到缓冲区的功能。

1.9 输出token:对于各种界符与关键字输出其在编译器的内部表示形式(token),对常数与标识符则让它流入下一个加工。

2 查填符号表:如果是标识符或常数,首先查看名字栏和类型栏(字符常数的类型栏中填有“字符常数”,标识符的类型栏空白),判断有无同名和同类型的入口。

如果有同名入口P1,则把P1作为token的自身值填入它的二元式;如果不同名,则将字符串存入符号表中,把它的长度和在字符串表中的开始位置及其类型(标识符为空白)填入符号表的新入口P中,并把P作为token的自身值填入二元式中。

对数值常数的处理是:先查符号表的val栏,若发现相同的常数则直接输出其二元式。

若表内无相同的常数,则将数值常数填入表内,在type栏内填入整型或实型,然后输出其二元式。

二元式包含该常数在符号表中的入口。

1.4 词法分析程序的详细设计将图3的词法分析程序的详细数据流图,可以得到词法分析程序的总体框架。

词法分析器的输出:(1)源文件的token表(系统单词出现几次就输出几次)(2) 源文件的符号表(二)Simple语言的定义Simple语言是一种类PASCAL语言,它以赋值语句为基础,包括顺序、条件和循环三种结构。

有变量说明和常量说明,有多种数据类型:整型、实型、字符型等。

它包括以下语法成份:(1)数据类型:整型、布尔型、实型、和字符型。

(2)表达式:可以进行算术、布尔表达式的运算。

(3)说明语句:常量说明(用const定义)、变量说明(用var定义)。

(4)赋值语句。

(5)控制语句:if语句、while语句、repeat语句、和for循环语句。

(6)begin……end复合语句。

(7)程序(program)语句与结束(end)语句。

Simple语言的语法定义如下:1. Simple语言字符集的定义:(1)<字符集> ::= <字母>︱<数字>︱<单界符>(2)<字母> ::= a︱b︱c︱……︱z︱A︱B︱C︱……︱Z(3)<数字> ::= 0︱1︱2︱……︱9(4)<单界符> ::= +︱-︱*︱/︱=︱<︱>︱(︱)︱{︱}︱:︱;︱,︱‟︱_︱.note: 不在该字符集范围内的其他字符视为非法字符。

2. Sample 语言词法定义(1)<单词>::= <保留字>︱<双界符>︱<标识符>︱<常数>︱<单界符>(2)<保留字>::= and︱begin︱bool︱case︱char︱const︱do︱else︱and︱false︱for︱if︱input︱integer︱not︱of︱or︱output︱program︱read︱real︱repeat︱then︱to︱true︱until︱var︱while︱write(3)<双界符>::= /*︱*/︱<=︱>=︱<>︱:=︱//(4)<标识符>::= <字母>︱<标识符><数字>︱<标识符><字母>(5)<常数>::= <整数>︱<布尔常数>︱<字符常数>︱<常数标识符>︱<实数>(6)<整数>::= <无符号整数>︱+<无符号整数>︱-<无符号整数>(7)<无符号整数>::= <数字>︱<无符号整数><数字>(8)<布尔常数>::= true︱false(9)<字符常数>::= 除…‟以外的任意字符串(10)<常数标识符>::= <标识符>(11)<实数>::= <小数>︱<指数>(12)<小数>::= <整数>.<无符号整数>︱<整数>(13)<指数>::= <小数>E<整数>︱<小数>e<整数>3. Sample语言数据类型的定义<简单类型>::= integer︱bool︱char︱real4.Sample语言表达式的定义(1)<表达式>::= <算术表达式>︱<布尔表达式>(2)<算术表达式>::= <项>+<算术表达式>︱+<项>︱<项>(3)<项>::= <项>*<因子>︱<项>/<因子>︱<因子>(4)<因子>::= <算术量>(5)<算术量>::= <标识符>︱<整数>︱<实数>(6)<布尔表达式>::= <布尔项>or<布尔表达式>︱<布尔项>(7)<布尔项>::= <布尔因子>and<布尔项>︱<布尔因子>(8)<布尔因子>::= <布尔量>︱not<布尔因子>(9)<布尔量>::= <布尔表达式>︱<布尔常数>︱<标识符>︱<算术表达式><关系符><算术表达式>(10)<关系符>::= <︱>︱<>︱<=︱>=︱=5. Sample语言语句的定义(1)<语句>::= <说明语句>︱<执行语句>(2)<说明语句>::= <常量说明><变量说明>(3)<常量说明>::= const<常数定义>︱ε(4)<常数定义>::= <标识符>=<常数><常数定义>︱<标识符>=<常数>;(5)<变量说明>::= var<变量定义>︱ε(6)<变量定义>::= <标识符表>:<简单类型>;︱<标识符表>:<简单类型><变量定义>;(7)<标识符表>::= <标识符>,<标识符表>︱<标识符>(8)<执行语句>::= <简单句>︱<结构句>(9)<简单句>::= <赋值句>(10)<赋值句>::= <变量>:=<表达式>(11)<变量>::= <标识符>(12)<结构句>::= <复合句>︱<if语句>︱<while语句>︱<for语句>︱<repeat语句>(13)<复合句>::= begin<语句表>end(14)<语句表>::= <执行语句>;<语句表>︱<执行语句>(15)<if语句>::= if<布尔表达式>then<执行语句>(16)<if语句>::= if<布尔表达式>then<执行语句1>︱else<执行语句2>(17)<while语句>::= while<布尔表达式>do<执行语句>(18)<for语句>::= for<标识符>:=<算术表达式1>to<算术表达式2>do<执行语句>(19)<repeat语句>::= repeat<执行语句>until<布尔表达式>6.Sample语言程序的定义(1)<程序>::=program<标识符>;<分程序>(2)<分程序>::= <常量说明><变量说明><符合句>.(三).调试运行结果(四).实验源代码:#include<iostream>#include<string>#include<iomanip>#include"fstream"#include"sstream"using namespace std;int n;int k=0;string s[200];string h[49]={"and","begin","bool","case","char","const","do","else","end","false","for","if","input","integer","not","of","or","output","program","read","real","repeat","then","to","true","until","var","while","write","+","-","*","/","<",">","<=",">=","<>","=",":=",";",",","'",":","/*","*/","//","(",")"};struct ji1{int hang;int token;string name;string type;}p[200];struct ji2{int hang1[10];int token1;string name1;string type1;int m;}q[200];void text()//导入程序,并存储在字符串数组中{cout<<"请输入程序行数";cin>>n;ifstream a("D:\\123.txt");inti = 0;for(i;i<n;i++){getline(a,s[i]);cout<<s[i]<<endl;}}void panbie1(string a)//对字符串进行判断{int flag=0;for(inti=0;i<29;i++){if(a==h[i]){p[k].token=i+1;p[k].type="关键字";k++;flag=1;}}if(a.length()==1){p[k].token=56;p[k].type="标识符";k++;}if((a.length()>1)&&(flag==0)){p[k].token=55;p[k].type="id";k++;}}void panbie2(string a)//对符号进行判断{for(inti=29;i<39;i++){if(a==h[i]){p[k].token=i+1;p[k].type="运算符";k++;}}for(i=39;i<49;i++){if(a==h[i]){p[k].token=i+1;p[k].type="界符";k++;}}}void huafen()//对一行程序进行划分,并进行简单判断{inti=0,flag=0;string a;for(i;i<n;i++){for(int j=0;j<s[i].length();j++){if(s[i][j]==32||s[i][j]==0)continue;if((s[i][j]<='z')&&(s[i][j]>='a')){a=a+s[i][j];if(s[i][j+1]<'a'||s[i][j+1]>'z'){p[k].name=a;p[k].hang=i+1;panbie1(a);a="";}}if((s[i][j]<='9')&&(s[i][j]>='0')){a=a+s[i][j];if(s[i][j+1]<'0'||s[i][j+1]>'9'||(s[i][j+1]==32)){p[k].type="整常数";p[k].token=51;p[k].name=a;p[k].hang=i+1;k++;a="";}}if(((s[i][j]>'z')||(s[i][j]<'a'))&&((s[i][j]>'9')||(s[i][j]<'0'))){a=a+s[i][j];if(((s[i][j+1]<='z')&&(s[i][j+1]>='a'))||((s[i][j+1]<='9')&&(s[i][j+1]>='0'))||(s[i][j+1]==32)||(s[i][j+1]==0)) {p[k].name=a;p[k].hang=i+1;panbie2(a);a="";flag=1;}if((a.length()==1)&&(flag==0)){if((s[i][j]=='<')&&(s[i][j+1]=='='))continue;else if((s[i][j]=='<')&&(s[i][j+1]=='>'))continue;else if((s[i][j]=='>')&&(s[i][j+1]=='='))continue;else if((s[i][j]=='*')&&(s[i][j+1]=='/'))continue;else if((s[i][j]=='/')&&(s[i][j+1]=='*'))continue;else if((s[i][j]=='/')&&(s[i][j+1]=='/'))continue;else if((s[i][j]==':')&&(s[i][j+1]=='='))continue;else{p[k].name=a;p[k].hang=i+1;panbie2(a);a="";}}if(a.length()==2){p[k].hang=i+1;panbie2(a);a="";}}flag=0;}}}void display()//显示token表{cout<<"-------------------------------token表-------------------------------"<<endl;cout<<"所在行数"<<" 单词本身"<<" token码"<<" 类型"<<endl;for(inti=0;i<k;i++){cout<<" "<<p[i].hang<<" ";cout<<p[i].name<<" ";cout<<p[i].token<<" ";cout<<p[i].type<<" ";cout<<endl;}cout<<"-------------------------------------------------------------------"<<endl<<endl;}int change()//将token表转换为符号表{inti=0,j=0,l,flag=0;for(i;i<200;i++)q[i].m=1;for(i=0;i<k;i++){for(l=0;l<j+1;l++){if(p[i].name!=q[l].name1)flag++;else{q[l].hang1[q[l].m]=p[i].hang;q[l].m++;break;}if(flag==j+1){q[j].token1=p[i].token;q[j].type1=p[i].type;q[j].hang1[0]=p[i].hang;j++;break;}}flag=0;}return j;}void display1()//显示符号表{cout<<"-------------------------------符号表-------------------------------"<<endl;int j=change(),g;cout<<"行号"<<"单词本身"<<" token码"<<" 类型"<<" 引用信息"<<endl;for(inti=0;i<j;i++){cout<<q[i].hang1[0]<<" ";cout<<q[i].name1<<" ";cout<<q[i].token1<<" ";cout<<q[i].type1<<" ";for(g=1;g<q[i].m;g++){cout<<q[i].hang1[g]<<" ";}cout<<endl;}cout<<"--------------------------------------------------------------------"<<endl;}void main(){cout<<"*****************************欢迎使用!******************************"<<endl; cout<<"* 词法分析器及其算法的设计与实现*"<<endl;cout<<"* 作者:李世13级软件工程E21314003 *"<<endl;cout<<"********************************************************************"<<endl;text();huafen();display();display1();cout<<"***************************欢迎再次使用!****************************"<<endl; }。

相关文档
最新文档