代码功能:
(1)计算非终结符的FIRST和FOLLOW集
(2)构造SLR分析表
(3)判断该文法是否为SLR文法
(4)输入字符串,按照SLR分析法判断该字符串的语法是否正确,并给出判断过程
代码的思路:
- 将文法中的每一个句子的左部和右部进行分离。其中,右部的每一个终结符和非终结符也是单独保存的。
- 将左部和右部分离后的文法中的终结符和非终结符识别出来。一般左部都是非终结符,那么右部除去非终结符就是终结符了。
- 计算FIRST集。设置一个变量_ALTERED_,在每次有新的终结符添加到FIRST集中的时候,就将_ALTERED_置位true。计算FIRST集的方法如下:如果产生式右部是终结符a,且这个终结符a不在FIRST集中,则添加。如果是非终结符A,则将A的FIRST集中的所有自己没有的终结符添加到自己的FIRST集中。如果A的终结符中包含ε,则继续判断下一个。
- 计算FOLLOW集。设置一个变量_ALTERED_,在每次有新的终结符添加到FOLLOW集中的时候,就将_ALTERED_置位true。计算FOLLOW集的方法如下:1、遍历文法中的所有产生式,所有出现在非终结符右边的终结符加入到相应follow集中,如果非终结符右边没有东西,则把$加入。 2、遍历文法中的所有产生式,若产生式最右边是非终结符,把左部非终结符的follow集的所有元素都添加到对应非终结符中。3、将$加入到第一个非终结符的follow集中。
- 根据每一条产生式,生成项目集规范族。程序设计的是对项目集规范族中的每一个项目集中的每一条项目都进行分析,产生了新的项目集就添加到项目集规范族中。
- 根据项目集规范族和FOLLOW集生成SLR分析表。根据·的位置判断是否将其添加到SLR分析表中,很容易。如果·后面的是终结符,将转移动作s添加到SLR分析表中的ACTION部分;如果·后面的是终结符,将转移添加到SLR分析表的GOTO部分;如果·在项目的末尾,将归约动作r添加到SLR分析表的ACTION部分。
- 设计词法分析器,用于分析输入的程序。
- 根据SLR分析表和词法分析的结果进行词法分析。
程序代码:
CSDN下载了直接用Eclipse打开:https://download.csdn.net/download/oLOVED/12098174
GitHub上的项目:https://github.com/z1178902213/SLRAnalyser-
程序运行:
文法:
E->E+T
E->E-T
E->T
T->T*K
T->T/K
T->K
K->K%F
K->K^F
K->F
F->(E)
F->id
F->num
测试程序:
a+xyz*10+(c/d)+(xyz%a)+(d^5)
运行结果:
终结符:[+, -, *, /, %, ^, (, ), id, num]
非终结符:[E, T, K, F]
文法如下所示:
(1)E->E+T
(2)E->E-T
(3)E->T
(4)T->T*K
(5)T->T/K
(6)T->K
(7)K->K%F
(8)K->K^F
(9)K->F
(10)F->(E)
(11)F->id
(12)F->num文法的First集为:
First(E) = { ( id num }
First(T) = { ( id num }
First(K) = { ( id num }
First(F) = { ( id num }文法的Follow集为:
Follow(E) = { + - ) $ }
Follow(T) = { $ * / + - ) }
Follow(K) = { $ % ^ * / + - ) }
Follow(F) = { $ % ^ * / + - ) }该文法的项目集规范族如下所示:
I0:
START->·E
E->·E+T
E->·E-T
E->·T
T->·T*K
T->·T/K
T->·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI1:
START->E·
E->E·+T
E->E·-TI2:
E->T·
T->T·*K
T->T·/KI3:
T->K·
K->K·%F
K->K·^FI4:
K->F·I5:
F->(·E)
E->·E+T
E->·E-T
E->·T
T->·T*K
T->·T/K
T->·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI6:
F->id·I7:
F->num·I8:
E->E+·T
T->·T*K
T->·T/K
T->·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI9:
E->E-·T
T->·T*K
T->·T/K
T->·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI10:
T->T*·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI11:
T->T/·K
K->·K%F
K->·K^F
K->·F
F->·(E)
F->·id
F->·numI12:
K->K%·F
F->·(E)
F->·id
F->·numI13:
K->K^·F
F->·(E)
F->·id
F->·numI14:
F->(E·)
E->E·+T
E->E·-TI15:
E->E+T·
T->T·*K
T->T·/KI16:
E->E-T·
T->T·*K
T->T·/KI17:
T->T*K·
K->K·%F
K->K·^FI18:
T->T/K·
K->K·%F
K->K·^FI19:
K->K%F·I20:
K->K^F·I21:
F->(E)·SLR分析表:
栈 输入 动作
0 a+xyz*10+(c/d)+(xyz%a)+(d^5)$ 移进
0id6 +xyz*10+(c/d)+(xyz%a)+(d^5)$ 按F->[id]归约
0F4 +xyz*10+(c/d)+(xyz%a)+(d^5)$ 按K->[F]归约
0K3 +xyz*10+(c/d)+(xyz%a)+(d^5)$ 按T->[K]归约
0T2 +xyz*10+(c/d)+(xyz%a)+(d^5)$ 按E->[T]归约
0E1 +xyz*10+(c/d)+(xyz%a)+(d^5)$ 移进
0E1+8 xyz*10+(c/d)+(xyz%a)+(d^5)$ 移进
0E1+8id6 *10+(c/d)+(xyz%a)+(d^5)$ 按F->[id]归约
0E1+8F4 *10+(c/d)+(xyz%a)+(d^5)$ 按K->[F]归约
0E1+8K3 *10+(c/d)+(xyz%a)+(d^5)$ 按T->[K]归约
0E1+8T15 *10+(c/d)+(xyz%a)+(d^5)$ 移进
0E1+8T15*10 10+(c/d)+(xyz%a)+(d^5)$ 移进
0E1+8T15*10num7 +(c/d)+(xyz%a)+(d^5)$ 按F->[num]归约
0E1+8T15*10F4 +(c/d)+(xyz%a)+(d^5)$ 按K->[F]归约
0E1+8T15*10K17 +(c/d)+(xyz%a)+(d^5)$ 按T->[T, *, K]归约
0E1+8T15 +(c/d)+(xyz%a)+(d^5)$ 按E->[E, +, T]归约
0E1 +(c/d)+(xyz%a)+(d^5)$ 移进
0E1+8 (c/d)+(xyz%a)+(d^5)$ 移进
0E1+8(5 c/d)+(xyz%a)+(d^5)$ 移进
0E1+8(5id6 /d)+(xyz%a)+(d^5)$ 按F->[id]归约
0E1+8(5F4 /d)+(xyz%a)+(d^5)$ 按K->[F]归约
0E1+8(5K3 /d)+(xyz%a)+(d^5)$ 按T->[K]归约
0E1+8(5T2 /d)+(xyz%a)+(d^5)$ 移进
0E1+8(5T2/11 d)+(xyz%a)+(d^5)$ 移进
0E1+8(5T2/11id6 )+(xyz%a)+(d^5)$ 按F->[id]归约
0E1+8(5T2/11F4 )+(xyz%a)+(d^5)$ 按K->[F]归约
0E1+8(5T2/11K18 )+(xyz%a)+(d^5)$ 按T->[T, /, K]归约
0E1+8(5T2 )+(xyz%a)+(d^5)$ 按E->[T]归约
0E1+8(5E14 )+(xyz%a)+(d^5)$ 移进
0E1+8(5E14)21 +(xyz%a)+(d^5)$ 按F->[(, E, )]归约
0E1+8F4 +(xyz%a)+(d^5)$ 按K->[F]归约
0E1+8K3 +(xyz%a)+(d^5)$ 按T->[K]归约
0E1+8T15 +(xyz%a)+(d^5)$ 按E->[E, +, T]归约
0E1 +(xyz%a)+(d^5)$ 移进
0E1+8 (xyz%a)+(d^5)$ 移进
0E1+8(5 xyz%a)+(d^5)$ 移进
0E1+8(5id6 %a)+(d^5)$ 按F->[id]归约
0E1+8(5F4 %a)+(d^5)$ 按K->[F]归约
0E1+8(5K3 %a)+(d^5)$ 移进
0E1+8(5K3%12 a)+(d^5)$ 移进
0E1+8(5K3%12id6 )+(d^5)$ 按F->[id]归约
0E1+8(5K3%12F19 )+(d^5)$ 按K->[K, %, F]归约
0E1+8(5K3 )+(d^5)$ 按T->[K]归约
0E1+8(5T2 )+(d^5)$ 按E->[T]归约
0E1+8(5E14 )+(d^5)$ 移进
0E1+8(5E14)21 +(d^5)$ 按F->[(, E, )]归约
0E1+8F4 +(d^5)$ 按K->[F]归约
0E1+8K3 +(d^5)$ 按T->[K]归约
0E1+8T15 +(d^5)$ 按E->[E, +, T]归约
0E1 +(d^5)$ 移进
0E1+8 (d^5)$ 移进
0E1+8(5 d^5)$ 移进
0E1+8(5id6 ^5)$ 按F->[id]归约
0E1+8(5F4 ^5)$ 按K->[F]归约
0E1+8(5K3 ^5)$ 移进
0E1+8(5K3^13 5)$ 移进
0E1+8(5K3^13num7 )$ 按F->[num]归约
0E1+8(5K3^13F20 )$ 按K->[K, ^, F]归约
0E1+8(5K3 )$ 按T->[K]归约
0E1+8(5T2 )$ 按E->[T]归约
0E1+8(5E14 )$ 移进
0E1+8(5E14)21 $ 按F->[(, E, )]归约
0E1+8F4 $ 按K->[F]归约
0E1+8K3 $ 按T->[K]归约
0E1+8T15 $ 按E->[E, +, T]归约
0E1 $ 接受
程序正确