编译原理 实验三 LR(1)分析法 Java版
一、 实验目的
构造 LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解 LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、 描述 LR(1)语法分析程序的设计思想
**1.**提取所有有效识别活前缀的式子:
形式上我们说一个LR(1)项目[A→a·b, a]对于活前缀g是有效的,如果存在规范推导 其中,
-
g=da;
-
a是w的 第一个符号,或者a为#而w为e。
[A→a·Bb, a]对活前缀g=da是有效的,则对于每个形如B®x的产生式, 对任何bÎFIRST(ba),[B→·x, b]对g也是有效的。
**2.**项目集I 的闭包CLOSURE(I)构造:
-
I的任何项目都属于CLOSURE(I)。
-
若项目[A→a·Bb, a]属于CLOSURE(I),B→x 是一个产生式,那么,对于FIRST(ba) 中的每个终结符b,如果[B→·x, b]原来不在CLOSURE(I)中,则把它加进去。
-
重复执行步骤2,直至CLOSURE(I)不再增大为止。
3.GO****构造:
令I是一个项目集,X是一个文法符号,函数GO(I,X)定义为:GO(I,X)=CLOSURE(J)其中J={任何形如[A→aX·b, a]的项目| [A→a·Xb, a]ÎI}
**4.**分析表构造:
令每个Ik的下标k为分析表的状态,令含有[S¢→·S, #]的Ik的k为分析器的初态。
-
若项目[A→a·ab, b]属于Ik且GO(Ik, a)=Ij, a为终结符,则置ACTION[k, a]为 “sj”。
-
若项目[A→a·,a]属于Ik,则置ACTION[k, a]为 “rj”;其中假定A→a为文法G¢的第j个产生式。
-
若项目[S¢→S·, #]属于Ik,则置ACTION[k, #]为 “acc”。
-
若GO(Ik,A)=Ij,则置GOTO[k, A]=j。
-
分析表中凡不能用规则1至4填入信息的空白栏均填上“出错标志”。
三、 程序结构描述:
函数名称及调用格式返回类型 | 参数含义 | 返回值描述 | 函数功能 |
---|---|---|---|
void init() | 无 | 无 | 得到相应的终结符集和非终结符集 |
String getAction(int topState, char in) | 返回action表中相应的字符串 | Topstate是状态栈中的栈顶符号,in是当前输入符号 | 通过栈顶状态和输入符号来查找相应的action表,得到表中对应操作 |
String getStateStack() | 状态栈里全部符号 | 无 | 得到当前状态栈中的全部符号 |
String getCharStack() | 符号栈的全部符号 | 无 | 得到符号栈的全部符号 |
int getGoto(int state, char c) | Goto表中对应状态 | 无 | 得到goto表中对应的状态 |
void analyze() | 无 | 无 | 根据action表和goto表的内容进行LR(1)分析 |
MyFrame(String title) | 无 | 标题字符 | 这是构造器,为了将输出界面化 |
void actionPerformed(ActionEvent actionEvent) | 无 | 响应事件 | 主要为按钮绑定事件,进行语法分析 |
void main(String[] args) | 无 | Main参数 | Main方法,执行入口 |
注:分析表构造的逐步分析过程由OnBnClickedButton1()完成在表格控件输出。
四、 详细的算法描述
(1)移进:
table[i,a]= Sj:状态 j 移入到状态栈,把a移入到文法符号栈,其中 i,j 表示状态号。
(2)归约:
table[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符 A,即文法中有 A- B 的产生式,若 B 的长度为 R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉 R 个符号,即栈指针 SP 减去 R,并把 A 移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中 i 为修改指针后的栈顶状态。
(3)接受 acc:
当归约到文法符号栈中只剩文法的开始符号 S 时,并且输入符号串已结束即当前输入符是’#',则为分析成功,当table中该项为acc时分析成功接受。
(4)报错:
当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输
入端不是该文法能接受的符号串。
五、 结果和代码
有用的话,请不要吝啬,动动小手点个赞把~