实验项目
完成以下描述赋值语句的LL(1)文法的递归下降分析程序1
2
3
4
5
6
7
8
9S→V=E
E→TE′
E′→ATE′|ε
T→FT′
T′→MFT′|ε
F→ (E)|i
A→+|-
M→*|/
V→i
设计说明
终结符号i为用户定义的简单变量,即标识符的定义
设计要求
(1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;
(2)递归下降分析程序应能发现简单的语法错误;
(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果
设计思路
接收输入
词法分析器输出文件
由设计要求中的(1)可知,语法分析器所能接受的输入为词法分析器所输出的二元组
首先我们来回顾一下词法分析器所输出的二元组的格式:
可以看到,语句i=i+i)
对应的词法分析输出二元组格式为:<number,token>
的格式
number:编码数字
token:符号/字符串
显然,我们可以通过一个结构体来接受词法分析器所输入的二元组!
数据存储结构
我构造的结构体如下:1
2
3
4
5//记录词法分析器生成的二元组
typedef struct {
int num;
string token;
}two;
考虑到语句长度总是变化的,所以为了提高程序的鲁棒性,总的数据结构应定义为可变数组:1
2//记录全部的二元组
vector<two> text;
到此,数据储存结构的准备工作1已全部完成。
构造执行函数
根据递归下降分析的思想,我们首先需要对所有非终结符对应的产生式构造执行函数。
再者,根据设计要求,我们在进行字符匹配时仅使用编码two->num
进行匹配即可
编码映射
在本题中所使用到的主要编码如下:
字符 | 编码 |
---|---|
# | -1 |
id | 10 |
= | 18 |
+ | 19 |
- | 21 |
* | 23 |
/ | 24 |
( | 27 |
) | 28 |
S()
对产生式:S→V=E
,可以得到如下的递归调用流程。
由词法分析器的编码可知,match(18)中的18代表字符
=
E()
对产生式:E→TE′
,可以得到如下的递归调用流程。
E’()
对产生式:`E′→ATE′|ε,可以得到如下的递归调用流程。
由于产生式包含空动作
E′→ε
,所以在程序执行时需要判断是否读到E’的follow集元素,
其中编码28代表字符)
,编码-1代表字符#
。
T()
对产生式:T→FT′
,可以得到如下的递归调用流程。
T’()
对产生式:T′→MFT′|ε
,可以得到如下的递归调用流程。
由于产生式包含空动作
T′→ε
,所以在程序执行时需要判断是否读到E’的follow集元素,
其中编码19代表字符+
,编码21代表字符-
,编码28代表字符)
,编码-1代表字符#
。
F()
对产生式:F→ (E)|i
,可以得到如下的递归调用流程:
10代表用户定义标识符,27代表字符
(
,28代表字符)
A()
对产生式:A→+|-
,可以得到如下的递归调用流程:
19代表字符
+
,21代表字符-
M()
对产生式:M→*|/
,可以得到如下的递归调用流程:
23代表字符
*
,24代表字符/
V()
对产生式:V→i
,可以得到如下的递归调用流程:
10代表用户定义标识符
测试
正确用例
对于语句:1
i = i + i
编译结果为:
对于语句:1
i = i * (i/i)
编译结果为:
错误用例
对于语句:1
i = i + i )
编译结果为:
对于语句:1
i = i + -
编译结果为:
至此,该递归下降语法分析器已全部符合题目要求