表驱动LL(1)语法分析程序

源码下载链接

(92条消息) 表驱动LL(1)语法分析程序-C++文档类资源-CSDN文库icon-default.png?t=N2N8https://download.csdn.net/download/weixin_51187996/87659928

1 概述

1.1目的与意义

编译程序支撑着计算机核心系统,独立研究、设计并开发一个简单的编译程序或其部分功能,可以加深对编译理论和编译过程的理解。编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,是编译程序的重要组成部分。通过设计、编制和调试一个典型的LL(1)语法分析方法,进一步掌握预测分析法的语法分析方法,有助于加深对编译程序的理解和实践。

1.2主要完成的任务

根据LL(1)分析法编写一个语法分析程序,输入已知文法,由程序自动构造文法的预测分析表。所开发的程序可适用于不同的文法和任意输入串,且能判断该文法是否为LL(1)文法。对输入的任意符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子(句型分析),并可以输出分析过程。

1.3使用的开发工具

使用DEVC++作为本设计的开发工具。

1.4课程设计计划

表1.1 时间规划表

时间

任务

12月初

复习表驱动的LL(1)的基础知识,规划课程设计内容

12月12日

实现文法初始化及LL(1)文法判别模块

12月13日

LL(1)文法判别模块

12月14日

实现预测分析表的构造及输入串分析

12月15日

程序调试及撰写课程设计报告,答辩

12月16日

完成所有材料并提交

2 使用的基本概念和原理(一些书上的概念,公式编辑器编辑的公式识别成图片了,CSDN复制粘贴图片不好使,一个个下载再放进来太麻烦了,自己看书补全吧

2.1 LL(1)分析法

LL(1)分析法又称预测分析法,是一种不带回溯的非递归自顶向下分析法。LL(1)的含义是:第一个L表明自顶向下分析是从左至右扫描输入串的;第二个L表明分析过程中将用最左推导;“1”表明只需向右查看一个符号就可以决定如何推导(即可知用哪一个产生式进行推导)。

2.2 自顶向下语法分析

从文法的开始符号出发,反复使用文法的产生式,寻找与输入符号串匹配的推导。

2.3 FIRST集合

是上下文无关文法,则对于,有对应的

,若,则规定。

2.4 FOLLOW集合

是上下文无关文法,。

,若有,则规定。

2.5 SELECT集合

是上下文无关文法,则对于,有对应的

SELECT集,若,则。

否则,。

2.6 LL(1)文法的判定

一个上下文无关文法为LL(1)文法的充分必要条件是,对每个非终结符A的两个不同产生式与 ,满足

3 总体设计

采用C++设计实现LL(1)语法分析器,数据结构上主要使用标准模板库,功能上主要分为4个模块,获取到文法产生式,判别文法是否是LL(1)文法,构造预测分析表,对输入串进行分析。

图3.1总体流程图

3.1 获取文法

在此模块中,从文本文档中获取到文法产生式,并对文法产生式进行分析,初始化得到文法的开始符号,非终结符,终结符等特征。

3.2 判别文法

要判别一个上下文无关文法是否是LL(1)文法,分为五步:

(1)求能推出的非终结符集

(2)计算FIRST集

(3)计算每个非终结符A的FOLLOW(A)集

(4)计算每个产生式A→β的SELECT(A→β)集

(5)按LL(1)文法的定义判别

3.3 构造预测分析表

根据判别文法过程中得到的SELECT集,把产生式填入分析表。分析表的列为终结符与‘#",分析表的行为非终结符。行列交点M[A,a]的填写法则如下:

(1)若,放入M[A,a]

(2)若无产生式对应M[A,a],表示出错

3.4 分析输入串

LL(1)分析法的原理

(1)初始化分析栈,将#和开始符号分别入栈,输入指针指向输入串的第一个字符。

(2)比较当前分析栈栈顶符号与当前输入符号:

  • 如果栈顶符号为非终结符号,则到LL(1)分析表中查找(X.a),若存在可用产生式,则使用该产生式替换栈顶符号,转到②;若为错误信息,则输出错误信息,结束分析。
  • 如果栈顶符号为终结符号,且与输入符号相同,则分析栈弹出栈顶符号,输入指针读入下一个输入符号,转到②;

(3)如果栈顶号为#且当前输入符号也为#,则分析成功,结束分析。

3.5 程序数据结构

enum

{

    FU, SH, WD//012

};//规定大写字母为非终结符,E为空字符

char start;//开始符号

vector<char>Vn;//非终结符

vector<char>Vt;//终结符

vector<char>V;//文法字符

vector<string>G;//文法

vector<string>G1;//文法副本

map<char, int>isEVn;//非终结符标记数组

map<char, string>First;//每个文法符号的first集

map<string, string>First1;//每个字符串的first集

map<char, string>Follow;//每个非终结符的follow集

map<string, string>Select;//select集

map<char,map<char,string> >Anlysis;// 分析表

4 详细设计

4.1 获取文法

以只读方式,读取文本文档,默认文本中产生式的第一个符号为文法的开始符号,读取后的产生式处理后,存入文法副本,对形如的产生式做处理,变成,的形式,再存储到文法中。并更新文法副本,用于推导的非终结符集使用。扫描文法产生式,初始化终结符集和非终结符集。

4.2 求能推出的非终结符集

首先建立一个以文法的非终结符个数为上界的一维数组,其数组元素为非终结符,对应每一非终结符有一个标志位,用以记录能否推到出。其值有三种情况:“未定”、“是”、“否”。

计算能推出的非终结符步骤如下:

  1. 将数组X[]中对应每一非终结符的标记置初值为“未定”(WD)。
  2. 扫描文法中的产生式。
  • 删除所有右部含有终结符的产生式,若这使得以某一非终结符为左部的所有产生式都被删除,则将数组中对应该非终结符的标记值改为“否”,说明该非终结符不能推出。

若某一非终结符的某一产生式右部为,则将数组中对应该非终结符的标志置为“是”,并从文法中删除该非终结符的所有产生式。

图4.1 scanA_s()函数流程图

  1. 扫描产生式右部的每一符号。
  • 若所扫描到的非终结符在数组中对应的标志是“是”,则删去该非终结符;若这使产生式右部为空,则将产生式左部的非终结符在数组中对应的标志改为“是”,并删除以该非终结符为左部的所有产生式。
  • 若所扫描到的非终结符号在数组中对应的标志是“否”,则删去该产生式;若这使产生式左部非终结符的有关产生式都被删去,则把在数组中该非终结符对应的标志改成“否”。
  1. 重复(3),直到扫描完一遍文法的产生式,数组中非终结符对应的特征再没有改变为止。

必须严格按照步骤进行,顺序不可颠倒。

图4.2 scan_s()函数流程图

4.3 计算FIRST集

  1. 根据FIRST集定义对每一文法符号计算FIRST(X)。
  • 对,则。
  • 扫描产生式,对,且识别到有产生式,则。
  • 扫描产生式,对,识别到,则。
  • 若,而识别的有产生式。当时(其中),则count标记记录下标,将

都包含在中。

  • 当步骤四中所有,则。

图4.3get_First()函数流程图

反复使用上述2~5步,最后对每个符号的FIRST集合去除重复元素。

(2)求符号串的FIRST集合

求出每个文法符号的FIRST集合后,也就不难求出一个符号串的FIRST集合。

若符号串,当不能,则置。对产生式右部串,判断是否都含有空元素,记录最后一个FIRST集含有空元素的元素下标k,若该下标不等于右部串长度,即串元素的FIRST集合部分含有空,,则使得

当k等于右部串长度时,也即对任何都含有,则

图4.4 get_Firsts()函数流程图

4.4 计算FOLLOW集

对文法中每一个,计算FOLLOW(A)。

(1)设S为文法的开始符号,把{#}加人FOLLOW(S)中(这里#为句子括号),并初始化FOLLOW集均为空。

(2)循环查找,若识别到形如的产生式,则获取串,判断该串是否可推导出空,把 FIRST()的非空元素加入FOLLOW(B)中,FIRST()串可能尚未计算过,这里需要另计算FIRST(),将串中的每个符号的FIRST集中的非空元素加入其中,直到某符号推导不出空。

如果,则把FOLLOW(A)也加人FOLLOW(B)中,

图4.5 get_Follow()函数流程图

(3)重复使用(2),最后对FOLLOW集进行去重操作。

4.5 计算SELECT集

扫面文法的全部产生式,获取产生式右部串,存储在s中,同时进行分析,若不能推导出空,则修改标记。按照SELECT集定义对于产生式,若,则

否则,

4.6 判断LL(1)文法

按照定义判断是否是LL(1)文法,对比同一非终结符的产生式对应的SELECT集合是否相交。需要注意的是,在实际实现过程中需要对SELECT集的元素进行循环比较,不能简单的判断两集合是否相等,若相交则修改标记。

对标记进行判断,若不是LL(1)文法,则暂停程序。

4.7 构造预测分析表

SELECT集本身存储了产生式,在构造预测分析表时,直接遍历SELECT即可,将产生式左部的非终结符,对应的SELECT集内的元素,以及相应的产生式,按照定义存储在分析表中。

4.8 分析输入串

首先处理输入串,压入一个’#’号,分析栈压入’#’和文法开始符号。t存取当前栈顶元素。如果栈顶符号与输入串当前元素不匹配,则到LL(1)分析表中查找Anlysis(t,s[i]),若存在可用产生式,则获取到该产生式右部,替换栈顶符号(注意入栈顺序);若不存在产生式,则输出错误信息,结束分析。

如果栈顶符号与输入串当前元素相匹配,则分析栈弹出栈顶符号,输入串指针下标向下移动,读入下一个输入符号;若两者的匹配符号为’#’,则表示该串是此LL(1)文法的句子。

图4.6  anlysis()函数流程图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值