赞
踩
一、实验目的
二、实验原理
分析对象〈算术表达式〉的 BNF 定义如下:
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= =|#|<|<=|>|>=
三、实验内容
1.了解符已给 PL/0 语言文法,构造表达式部分的语法分析器。
分析对象〈算术表达式〉的 BNF 定义如下:
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= =|#|<|<=|>|>=
2.将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,输出“语法正确”;对于语法错误的表达式,输出“语法错误”,指出错误原因。
3.输入:
4.输出:
四、实验算法及流程图
LL(1)分析法属于确定的自顶向下分析方法。LL(1)的含义是:第一个L表明自顶向下分析是从左到右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。
扩充的巴克斯范式
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
普通的巴克斯范式
为表示方便:
表达式E、项X、因子Y、标识符b,无符号整数z,加法运算符A,乘法运算符C
E->AX|X|EAX
X->Y|XCY
Y->b|z|(E)
A->+|-
C->*|/
消除左递归
E->XE’|AXE’
E’->AXE’|ε
X->YX’
X’->CYX’|ε
Y->b|z|(E)
A->+|-
C->*|/
改进后的文法满足LL(1)文法条件,所以该文法是LL(1)的。
手动求了First集和Follow集,方便后面进行程序的验证。
FIRST和FOLLOW集合
FIRST(E)={b,z,(,+,-} FOLLOW(E)={#,)}
FIRST(E’)={ε,+,-} FOLLOW(E’)={#,)}
FIRST(X)={b,z,(} FOLLOW(X)={+,-,#,)}
FIRST(X’)={ε,,/} FOLLOW(X’)={+,-,#,)}
FIRST(Y)={b,z,(} FOLLOW(Y)={,/,+,-,#}
FIRST(A)={+,-} FOLLOW(A)={b,z,(}
FIRST©={,/} FOLLOW©={b,z,(}
构建预测分析表。要构建预测分析表就要根据产生式来生成三个集合First set, Follow Set, Select Set
功能:对一个给定的非终结符,通过一系列语法推导后,能出现在推导表达式最左端的所有终结符的集合,统称为该非终结符的FIRST SET。
S -> a B
S是非终结符,a是终结符,B是零个或多个终结符或非终结符的组合,那么 a属于 FIRST(S).
s -> b a
s 和 b 是非终结符,而且b 不是nullable的,那么first(s) = first(b)
s -> a1 a2 … an b
如果a1, a2 … an 是nullable 的非终结符,b是非终结符但不是nullable的,或者b是终结符,那么
first(s) 是 first(a1)… first(an) 以及first(b)的集合。
对于某个非终结符通过一系列推导变换后,某个终结符出现在该非终结符的后面,那么我们称该终结符属于对应非终结符的FOLLOW SET。
对于标号为N的推导表达式s->a,以及当前输入T,那么Selest(N)要包括T的话,当栈顶元素是s,且输入为T时,要使用推导表达式N来进行下一步推导。
lhs = 推导表达式箭头左边的非终结符
for (对应每一个在SELECT(N)中的token) {
parse_table[lhs][token] = N
}
}
LL(1)大概的工作流程:
1)将开始符号压入栈中;
2)根据输入符号和分析表来选择产生式;
3)把产生式都压入栈中;
4)如果当前栈顶是终结符,就进行匹配;
5)匹配失败退出,成功则读入,再回到第二个步骤
用例1
用例2
itc验证
递归下降分析也成功。
根据程序运行得到的结果可以看出:编写的代码正确。
第二次编译原理的实验课,最大的收获是复习了LL(1)文法的相关知识,从代码的层面深入的学习了符号表的建立与使用,同样提高了动手写代码的熟练程度。
这次实验难度不大,主要是理解和掌握建立FIRST集、FOLLOW集、SELECT集等操作,以及对预测分析表的理解对编写代码尤为重要。
这次编译原理实验课,总结上一次实验课的经验与教训:理解好项目给出的数据结构,以及演示模式程序执行的步骤和输出结果,熟练掌握数据结构的相关知识是完成代码的关键。
总的来说,通过这次实验课,既加深了我对编译原理课程重点内容的理解,又复习了数据结构、c/c++的相关知识,提高了编写代码的能力,收获良多。
最后,特别感谢刘老师一直以来的耐心指导和同学的热心帮助!
代码如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。