1、(4)(5)该程序可分为如下几步:读入文法判断正误若无误,判断是否为LL(1)文法 若是,构造分析表; 由句型判别算法判断输入符号串是为该文法的句型。三、核心思想该分析程序有15部分组成:(1)首先定义各种需要用到的常量和变量;(2)判断一个字符是否在指定字符串中;读入一个文法; 将单个符号或符号串并入另一符号串; 求所有能直接推出 & 的符号; 求某一符号能否推出 & ; 判断读入的文法是否正确; 求单个符号的 FIRST; 求各产生式右部的 FIRST; 求各产生式左部的 FOLLOW ; 判断读入文法是否为一个 LL(1) 文法; 构造分析表 M ; 句型判别算法; 一个用户调用函数;
2、主函数;(6)(7)(8)(9)(10)(11)(12)(13)(14)(15) 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集I、实例中求直接推出空的 empty集的算法描述如下: void emp(char c) 参数 c 为空符号 char temp10; 定义临时数组 int i;1, temp 中& 符号的数组 empty 中。for(i=0;iB,B可推出空)1 但第一个字符为终结符 ,then 返回 0(A-a,a 为终结符 )找一个左部为 c 的产生式 j=strlen(righti);if 右部长度为 if 右部长度为elsefor(k=0;kAB)if 找到
3、的字符与当前字符相同 (A-AB) 结束本次循环else(mark 等于 0)查找右部符号是否可推出空字 ,把返回值赋给 resultif把当前符号加入到临时数组 empt 里.当前字符不能推出空字且还没搜索完全部的产生式 then 跳出本次循环继续搜索下一条产生式 else if / 当前字符可推出空字 ,返回2、计算每个符号的 first 集: 实例中求单个符号的 FIRST 集的算法描述如下: void first2 (int i) 参数 i 为符号在所有输入符号中的序号 c 等于指示器 i 所指向的符号 在保存终结符元素的 termin 数组查找 cif c 为终结符(c Vt ),
4、then FIRST(c)=c 在保存终结符元素的 non_ter 数组查找 c if c是非终结符(c Vn )(即 C7 a (a Vt)或 &) thenthen在所有产生式中查找 c 所在的产生式 if 产生式右部第一个字符为终结符或空 把 a 或 & 加进 FIRST(c) if 产生式右部第一个字符为非终结符if 产生式右部的第一个符号等于当前字符 then 跳到下一条产生式进行查找 求当前非终结符在所有字符集中的位置 if 当前非终结符还没求其 FIRST 集 then 查找它的 FIRST 集并标识此符号已求其 FIRST 集 求得结果并入到 c 的 FIRST 集 .if 当
5、前产生式右部符号可推出空字且当前字符不是右部的最后一个字符 获取右部符号下一个字符在所有字符集中的位置 if 此字符的 FIRST 集还未查找 then 找其 FIRST 集 ,并标其查找状态为 1 把求得的 FIRST 集并入到 c 的 FIRST 集 .if当前右部符号串可推出空且是右部符号串的最后一个字符 (即产生式为 c7丫1丫2Yk,若对一切 1=i )的产生式if X在产生式右部的最后(形如产生式A7 X) then 查找非终结符A是否已经求过其FOLLOW集.避免循环递归if 非终结符 A已求过其 FOLLOW集 thenFOLLOW(A) FOLLOW(X)继续查下一条产生式是
6、否含有 X求A之FOLLOW 集,并标识为 A已求其FOLLOW 集else if X不在产生式右部的最后(形如A 7 B ) thenif右部X后面的符号串 能推出空字then查找是否已经求过其FOLLOW集.避免循环递归if 已求过 的FOLLOW 集thenFOLLOW(A) FOLLOW(B)结束本次循环else if 不能推出空字 then求 FIRST()把FIRST()中所有非空元素加入到 FOLLOW(B)中标识当前要求的非终结符 X的FOLLOW 集已求过4.计算 SELECT!SELECT集的构造算法如下:对所有的规则产生式 A 7 X:(1)若 X 不能推出空字 ,贝y
7、SELECT(A 7X) = FIRST(x);(2)若 X 可推出空字 ,贝U SELECT(A 7x)=FIRST(x) - FOLLOW(A)。算法描述如下:=产生式总数-1;先把当前产生式右部的 FIRST集(一切非空元素,不包括 放入到当前产生式的SELECT(i);if 产生式右部符号串可推出空字 then把 i 指向的当前产生式左部的非终结符号的 FOLLOW 集并入到 SELECT(i) 中5.判断是否 LL(1) 文法要判断是否为 LL(1) 文法,需要输入的文法 G 有如下要求: 具有相同左部的规则的 SELECT 集两两不相交,即:SELECT(A T ) nSELECT
8、(A )= 如果输入的文法都符合以上的要求,则该文法可以用 算法描述如下:把第一条产生式的 SELECT(0) 集放到一个临时数组 temp 中 for(i=1;= 产生式总数 -1;求 temp 的长度 lengthif i 指向的当前产生式的左部等于上一条产生式的左部 temp 数组中 length 加上 SELECT (i) 的长度LL(1) 方法分析。把 SELECT(i) 并入到If temp 的长度小于 返回 0把 temp 清空把 SELECT (i) 存放到结果返回 1 ;四、算法temp 中#includestdio.hstring.h /*/ int count=0; in
9、t number; char start; char termin50; char non_ter50; char v50; char left50; char right5050;/产生式的个数/所有终结符和非终结符的总数/开始符号/终结符号/非终结符号/所有符号/左部/右部char first5050,follow5050; char first15050; char select5050; char firstflag50,followflag50; char empty20; char nonempty20; char empt20; char TEMP50;int int/各产生式右
10、部的 FIRST 和左部的 FOLLOW 集合 / 所有单个符号的 FIRST 集合 /各个产生式的 SELECT 集合/记录各符号的 FIRST 和 FOLLOW 是否已求过 /记录可推出 & 的符号/记录不可推出 &II求_em p()时使用/求 FOLLOW 时存放某一符号串的 FIRST 集合intvalidity=1; ll=1;M2020;II表示输入文法是否有效II表示输入文法是否为 LL(1)文法II分析表char choose; /用户输入时使用char foll20; / 求 FOLLOW 集合时使用/*判断一个字符 c 是否在指定字符串 p 中 */int in(char c,char *p)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1