1、MiniPascal的 LR语法分析程序设计文档(仅供参考)Part2-SLR分析表的生成1. 注意 22. 基本流程 23. 文法修改 23.1 SimpleBNF语言的文法开发 33.2 MiniPascal文法的 SimpleBNF语言描述 74. 产生式数据结构 85. LR(0)项目数据结构 95.1 class LR0Item 95.2 各类项目的判定方法 95.3 class LR0ItemSet 95.4 class LR0State 105.5 class VclassifiedLR0ItemTable 106. 符号表 116.1 syntax_vn_code的符号表 11
2、6.2 syntax_vt_class的符号表 126.3 Syntax_vn_code和 Syntax_vt_class与符号表索引的关系 137. SLR内存分析表设计 138. DFA的遍历 158.1 ViewedSet数据结构 178.2 ToAccessQueue数据结构 178.3 DFA子状态(非核心项目)集合生成 188.4 求 FIRST/FOLLOW集合 201. 注意本设计文档反映的是设计过程,与最终代码可能有出入. 2. 基本流程图 1 产生分析表的基本流程3. 文法修改/GProgEx GProg;/ 语法部分/ Statements:Statements; /为达
3、到文法书写时,行终结的一致性/ 0. ProgEx- Prog 手工拓广文法,改为自动拓广文法/ 1. Prog - program id semicolon SubProg /去掉产生式的手工编号,实现自动编号Prog - program id semicolon SubProg ; /1.SubProg - VarDecl begin StatList end fullstop ; /2.VarDecl - var VarDeclList semicolon ; /3.VarDeclList - VarList colon type ; /4.上述修改仅是局部解决方案,为实现 GProg文
4、法的全面处理(词法分析、语法分析),我们必须定义 BNF语言(描述文法的语言)的文法.3.1 SimpleBNF语言的文法开发因为 GProg采用 BNF语言(除 Statements, Tokens,Helper等扩展外)描述,为达到对GProg文法的解析,需要定义 BNF语言的文法(部分参考“Chomsky 4 类文法识别程序 GrammarApp3“文法).除定义 BNF语言的文法这一目标外,考虑到 GProg的文法描述可以控制在本项目内、以及本项目有其它更重要的任务(如 DFA遍历),BNF 语言文法的基本设计原则是“简单性“,即尽可能简化 BNF语言的表述形式.现命名将设计的简化版的
5、 BNF语言文法为 SimpleBNF文法,该文法仅支持 BNF语言的一个子集、支持 Statements, Tokens,Helper的简单扩展、仅支持 posix字符类形式的正则表达式(全面正则表达式的支持,留到本项目的后续版本实现.),以使得仅需开发 LL(1)语法分析器(甚至词法分析器)就可以解析 SimpleBNF的句子.需注意这里有一个递归定义的应用:用 SimpleBNF语言定义 SimpleBNF文法./version 1GSimpleBNF;Statements;SimpleBNF - GrammarTitle ; GrammarParts ;GrammarTitle - i
6、d vn ;GrammarParts - Statements ; StatementListTokens ; TokenListHelpers ; HelperList;StatementList - Statement ; StatementList | epsilon;Statement - vn - StatRight;StatRight - vn StatRight | vt StatRight| epsilon | epsilon;TokenList - vt - RightListSet;RightListSet - RightList MoreRightList;RightLi
7、st - literal RightList | vt RightList | posix RightList | epsilon;MoreRightList - | RightList MoreRightList | epsilon;Tokens;id - A-Za-zA-Za-z_-0-9*;vn - A-Z A-Za-z_-0-9*;vt - a-z A-Za-z_-0-9*;literal id posix - : id :Helpers;上述 GSimpleBNF文法的定义,还存在 FIRST与 FOLLOW的冲突(即非 LL(1)文法),如:FIRST(StatementList)
8、 = FIRST(Statement) = vn (首字母大写的标识符)FOLLOW(StatementList) = Tokens (首字母大写的标识符)因此,我们将“Statements“, “Tokens“, “Helpers“的表述形式,做一要求,以使GSimpleBNF达到 LL(1)文法的要求.Posix表示 Posix Character Classes (Posix 标准的字符类),一些预定义的 posix字符类如下:alnum: Alphanumeric:alpha: Uppercase or lowercase letter:blank: Blank and tab:cnt
9、rl: Control characters (at least 0x000x1f, 0x7f):digit: Digit:graph: Printable character excluding space:lower: Lowercase letter:print: Any printable character (including space):punct: Printable character excluding space and alphanumeric:space: Whitespace (same as s):upper: Uppercase letter:xdigit:
10、Hex digit (09, af, AF)为适应 GProg文法的描述习惯,我们定义如下类 posix字符类:id:A-Za-zA-Za-z_-0-9*;:number: - 1-9 0-9*这样做的目的是使 GProg文法的 Tokens和 Helpers部分,不出现除 posix字符类以外的其它正则表达式,以达到简化语法分析 GProg句子的目的./version 2GSimpleBNF;:Statements;SimpleBNF - GrammarTitle ; GrammarParts ;GrammarTitle - id vn ;GrammarParts - : Statement
11、s ; StatementList: Tokens ; TokenList: Helpers ; HelperList;StatementList - Statement ; StatementList | epsilon;Statement - vn - StatRight;StatRight - vn StatRight | vt StatRight| epsilon | epsilon;TokenList - vt - RightListSet;RightListSet - RightList MoreRightList;RightList - literal RightList | v
12、t RightList | posix RightList | epsilon;MoreRightList - | RightList MoreRightList | epsilon;:Tokens;id - A-Za-zA-Za-z_-0-9*;vn - A-Z A-Za-z_-0-9*;vt - a-z A-Za-z_-0-9*;literal id posix - : id :Helpers;验证上述文法是 LL(1)文法:FIRST(StatementList) = FIRST(Statement) = vn (以大写英文字母开头的串)FOLLOW(StatementList) = :
13、上述无交集.FIRST(vn StatRight) = vn (以大写英文字母开头的串)FIRST(vt StatRight) = vt (以小写英文字母开头的串)FIRST(epsilon) = epsilon (令 epsilon为关键字且规定 vt不允许使用 epsilon)FOLLOW(StatRight) = FOLLOW(Statement) = ;上述无交集FIRST(literal RightList) = literal (以开头的串)FIRST(vt RightList) = vt (以小写英文字母开头的串)FIRST(posix RightList) = posix (以
14、:开头的串)FOLLOW(RightList) = FIRST(MoreRightList) = | ( FOLLOW(MoreRightList) =| ( FOLLOW(RightListSet) = | ( FOLLOW(TokenList) =上述无交集FIRST(| RightList MoreRightList)FOLLOW(MoreRightList) = :上述无交集对于产生式:StatRight - vn StatRight | vt StatRight| epsilon | epsilon;有以下说明:1. 因为无法用英文字符串表示希腊字母(,我们使用 epsilon.2.
15、 StateRight产生式中的epsilon为字符串,表示目标文法(使用 SimpleBNF语言描述)中的(关键字,如:GS;:Statements;S - epsilon; /相当于书本上的:S - (3. 而 StatRight产生式中的 epsilon表示使用 SimpleBNF语言的关键字(.我们发现,Statement 使用 StatRight产生式可以产生如下目标文法中的产生式:GS;:Statements;S - S epsilon;S - t epsilon;严格意义上讲,上述产生式是错误的,但可以被转换为:S - S;S - t;从严格意义上讲,(在产生式中的位置,只可能在
16、某产生式的右侧,且右侧仅有(一个元素(对于 CFG文法),如:S - (;A - (因此,上述转换是不必要的.为简化处理,我们将含有(元素的产生式,做一些修改,以进一步简化 SimpleBNF文法:/version 3GSimpleBNF;:Statements;SimpleBNF - GrammarTitle ; GrammarParts ;GrammarTitle - id vn ;GrammarParts - : Statements ; StatementList: Tokens ; TokenList: Helpers ; HelperList;StatementList - Sta
17、tement ; StatementList | ;Statement - vn - StatRight ;StatRight - vn StatRight | vt StatRight | ; /1.TokenList - vt - RightListSet;RightListSet - RightList MoreRightList;RightList - literal RightList | vt RightList | posix RightList | ;MoreRightList - | RightList MoreRightList | ;:Tokens;id - A-Za-z
18、A-Za-z_-0-9*;vn - A-Z A-Za-z_-0-9*;vt - a-z A-Za-z_-0-9*;literal id posix - : id :Helpers;上述文法使用空来表示(易验证 1所标识(其它同理)的产生式满足 LL(1)文法对产生式的要求:FIRST(vn StatRight) = vn (以大写英文字母开头的串)FIRST(vt StatRight) = vt (以小写英文字母开头的串)/ FIRST(epsilon) = epsilon (令 epsilon为关键字且规定 vt不允许使用 epsilon)FOLLOW(StatRight) = FOLLOW
19、(Statement) = ;上述无交集且这样做,无需规定“令 epsilon为关键字且规定 vt不允许使用 epsilon“.使 version3定义的 SimpleBNF语言,描述目标文法(如 GProg)的 Statement产生具有如下形式:GS;:Statements;S - ;注意:对于空格、t、n、r、/,我们均看成空白字符.使用 version3的 SimpleBNF语言描述 GProg文法如下:3.2 MiniPascal文法的 SimpleBNF语言描述/ MiniPascalGrammar.txt/ version 4: version3的 SimpleBNF描述GPro
20、g;/ 语法部分:Statements;Prog - program id semicolon SubProg; /1.SubProg - VarDecl begin StatList end fullstop; /2.VarDecl - var VarDeclList semicolon;3.VarDeclList - VarList colon type;4.VarDeclList - VarDeclList semicolon VarList colon type; /5.VarList - id;6.VarList - VarList comma id;7.StatList - Sta
21、t;8.StatList - StatList semicolon Stat;9.Stat - AssignStat;10.Stat - ConStat;11.Stat - WhileStat;12.Stat - CompStat;13.AssignStat - id assign ArithExp;14.ConStat - if RatExp then Stat else Stat; /15.WhileStat - while RatExp do Stat;16.CompStat - begin StatList end;17.ArithExp - Item;18.ArithExp - Ar
22、ithExp plus Item;19.ArithExp - ArithExp minus Item;20.Item - Factor;21.Item - Item multiply Factor;22.Item - Item divide Factor;23.Factor - id;24.Factor - cnum;25.Factor - left_paren ArithExp right_paren; /26.RatExp - ArithExp rat_sym ArithExp;27./词法部分:Tokens;program - PROGRAM ;semicolon - ; ;begin
23、- BEGIN ;end - END ;fullstop var - VAR ;colon type - INTEGER | REAL ;comma - , ;assign if - IF ;then - THEN ;else - ELSE ;while - WHILE ;do - DO ;plus - + ;minus - - ;multiply - * ;divide - / ;cnum - inum | fnum ;rat_sym left_paren- ( ;right_paren- ) ;id - :id: ;/词法帮助部分:Helpers;inum - :number: ;fnum
24、 - fullstop :number: | :number: fullstop :number: ;4. 产生式数据结构class Product vector line; /存放 vt和 vn的编码,即 syntax_vn_code,syntax_vt_classint countLeft; /表示产生式左侧的 vn或 vt的数量,因为 SLR文法为 CFG,故 countLeft始终为 1,public:int right(int right_index); /根据产生式右侧位置(=0)返回syntax_vn_code,syntax_vt_class或-1int left(返为产生式左侧
25、的 syntax_vn_code;class ProductMatrix vector matrix;public:int left(int product_no); /返回产生式编号对应产生式的左侧 syntax_vn_code/返回产生式编号对应产生式的右侧 syntax_vn_code,syntax_vt_class或-1int right(int product_no, int right_index); ;在对 GProg句子进行语法解析时,逐步完成产生式矩阵的设置.5. LR(0)项目数据结构5.1 class LR0Item定义 LR(0)项目的数据结构:class LR0Ite
26、m int product_no; /=0: 产生式号int point_index; /=0: ( 在产生式右侧的位置bool operator ( Prog /0. Prog - ( program id semicolon SubProg /1. VarList - VarList ( comma id / 7. product_no = 0;point_index = 0 product_no = 1;point_index = 0 product_no = 7;point_index = 1 5.2 各类项目的判定方法假设产生式矩阵变量为 pm,LR0项目变量为 it,判定其是否为核
27、心项目、移进项目、归约项目、待归约项目、接受项目的方法如下:核心项目 移进项目 接受项目it.product_no = 0 或 it.point_index 0pm.right(it.product_no, it.point_index) = 0 pm.right(it.product_no, it.point_index) = -1 /1.SubProg - VarDecl begin StatList end fullstop; /2.VarDecl - var VarDeclList semicolon;3.VarDeclList - VarList colon type;4.VarDe
28、clList - VarDeclList semicolon VarList colon type; /5.VarList - id;6.VarList - VarList comma id;7.在对文法 GProg进行解析之后,非终止符的符号表,如表 1所示.表 1 syntax_vn_code符号表索引号 lexeme词文 left_location在产生式左侧时,产生式号集合 right_location在产生式右侧时,(产生式号,右侧位置号=0) no_core_closure first_setFIRST集 follow_setFOLLOW集 0“Prog“ 1-1(done/EOF
29、) 1 “SubProg“ 2 (1, 3) 2 “VarDecl“ 3 (2, 0) 3 “VarDeclList“ 4,5 (3,1), (5,0) 4 “VarList“ 6,7 (7, 0), (4,0), (5, 2) 灰色标记的列,在对输入文法(如 GProg)的文本表示进行“语法分析“时,就完成填表.绿色标记的列,在“DFA 遍历“过程中,逐步填表.left_location: 当 Vn在产生式左侧时,为所在的产生式号集合.用于构造其 LR0非核心项目的传递闭包(存放于 no_core_closure 列),也用于求 FIRST集合(存放于 first_set列).no_core
30、_closure:从某 Vn开始的 LR0非核心项目的传递闭包,其类型为VclassifiedLR0ItemTable如:从 VarList开始,LR0 非核心项目集合为: VarList - ( id / 6.VarList - ( VarList comma id / 7.则 VarList的 no_core_closure列为:next_to_point(vn/vt编码,即 syntax_vn_code,syntax_vt_class或-1) LR0ItemSet(产生式号,右侧位置号)集合syntax_vn_code(VarList) (7, 0) Syntax_vt_class(id
31、) (6, 0) 对于形如 A-( / x. 的(产生式(假设 x为产生式号),其在 no_core_closure列具有如下形式:next_to_point(vn/vt编码,即 syntax_vn_code,syntax_vt_class或-1) LR0ItemSet(产生式号,右侧位置号)集合-1 (x,0) -1指(后无 Vn或 vt,取-1 的原因见第 6.3节 Syntax_vn_code和 Syntax_vt_class与符号表索引的关系.no_core_closure列与 first_set,follow_set列一样(在表 1中用绿色标记),是在“DFA 遍历“过程中动态生成的
32、,对于同一 Vn,为防止重复求解 LR0非核心项目集合, FIRST 集合、FOLLOW集合,因此需要在 n符号表中增加 no_core_closure, first_set,follow_set列,相当于 cache,以提高性能.right_location:用于求解某 Vn的 FOLLOW集合.6.2 syntax_vt_class的符号表表 2 syntax_vt_class符号表索引号 lexemesyntax_vt_class的词文 lexeme_define单词的词文定义0 “program“ “PROGRAM“ 1 “id“ :id: 2 “semicolon“ “;“ 3 “t
33、ype“ “INTEGER“, “REAL“ 4 “rat_sym“syntax_vt_class符号表的填表,是在对输入文法(如 GProg)的文本进行“语法分析“时完成的.需注意的是,本项目仅对 GProg的词法分析程序的自动生成提供有限支持,如不支持正则表达式(表 2中黄色标记)词法分析子程序的自动生成,这部分工作将在后续版本中完善.6.3 Syntax_vn_code和 Syntax_vt_class与符号表索引的关系表 3 syntax_vn_code和 syntax_vt_class的整数区间分配syntax_vn_code syntax_vt_class-N -3 -2 -1 0 1 N说明 非终止符 acc / Start Vn done / EOF 终止符位于:ACTION 列头* * 位于:GOTO 列头 * 位于:分析表元素 * * * 位于:输入队列* * 位于:分析栈 * * *