编译原理-预测分析程序设计与实现
编译原理笔记10 自上而下分析-预测分析程序与LL(1)文法

预测分析程序与LL(1)文法一、预测分析程序1.带预测分析的PDA:1)在PDA中加入预测分析之后,可以消除自上而下分析中出现回溯的现象,此时PDA可以改造为:2)注:a、改造后,整个分析过程都在预测分析程序控制下工作。
B、预测分析程序用了一个预测分析表,它是预测分析程序分析时的主要依据。
3)预测分析表:预测分析表是一矩阵M[A,a],其中行标A是非终结符,列标a是终结符或串结束符;矩阵元素M[A,a]是存放A的一个候选式,指出当前栈顶符号为A 且面临读入符号为a时应选的候选式;或者存放“出错标志”,指出A不该面临读入符号a。
2.预测分析程序算法描述设栈顶符号为X,读入符号为a,则1)若X=a=‘#’,则表示识别成功,退出分析程序;2)若X=a=‘#’,则表示匹配,弹出栈顶符号X,读头前进一格,让读头指向下一个符号,以读入下一个符号;若X是终结符,但X<>a,则调用error处理;3)若X属于非终结符,则查预测分析表M。
若M[X,a]中存放着关于X的产生式,则弹出X,且将相应产生式右部以自右向左的顺序压入栈,在输出带上记下产生式编号;若M[X,a]中存放着出错标记,则调用相应Error处理。
二、求串α的终结首符集和非终结符A的随符集a) 求串α的终结首符集First(α)i. 定义:假定α是文法G的一个符号串,α属于星闭包,则First(α)={a | α广义推导出a......a,a属于终结符}注:1)若α推导出空串,那么空串就属于First(α)。
2)First(α)集合是α的所有可能推导出的开头终结符或空串所组成的集合。
ii. 算法具体步骤:b) 求非终结符A的随符集Follow(A)i. 定义:假定S是文法G的开始符号,对于G的任何非终结符A,定义:ii. 算法1. 对文法开始符号S,将‘#’加入到Follow(S)中;2. 若B->αAβ是文法G的一个产生式,则将First(β)-空串加入到Folow(A)中;3. 若B->αA是文法G的一个产生式,或B->αAβ是文法G的一个产生式,且β推导出空串,则将Follow(B)加入到Follow(A)中;注:这里的文法必须消除左递归且提取了左因子后的文法。
编译原理预测分析法实验报告

编译原理实验预测分析法姓名**学号**班级**完成日期**1.实验目的加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
2.实验要求1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3. 3.对于遇到的语法错误, 能够做出简单的错误处理, 给出简单的错误提示, 保证顺利完成语法分析过程;4. 4.实验报告要求用文法的形式对语法定义做出详细说明, 说明语法分析程序的工作过程, 说明错误处理的实现。
5.实验原理对文法G进行语法分析, 文法G如下所示:*0. S→a */*1. S→.*2. S→(T)*3. T→SW **4..W→,S.*5. W→ε;6.软件设计与编程#include <stdio.h>#include <stdlib.h>#include <string.h>char str[100]; //存储待分析的句子const char T[ ] = "a^(),#"; //终结符, 分析表的列符const char NT[ ] = "STW"; //非终结符, 分析表的行符/*指向产生式右部符号串*/const char *p[] = {/*0. S→a */ "a",/*1.. S→. *. "^",/*2. S→(T) */ "(T)",/*3. T→SW */ "SW",/*4.. W→,S. */ ",SW",/*5. W→ε; */ ""};//设M[i][j]=x, 通过p[M[i][j]]=p[x]获取右部符号串。
const int M[][6] = {/* a ^ ( ) , # *//*S*/ { 0, 1, 2, -1, -1, -1 },/*T*/ { 3, 3, 3, -1, -1, -1 },/*W*/ { -1, -1,-1, 5, 4, -1 }};void init()//输入待分析的句子{printf("请输入待分析的句子(以$结束): \n");scanf("%s",str);}int lin(char c);//非终结符转换为行号int col(char c);//终结转换为列号bool isNT(char c);//isNT判断是否是非终结符bool isT(char c);//isT判断是否是终结符。
第三四章习题课编译原理

0 A 0 C
27
1
1
习题15(1/3)
15、给定右线性文法G: S→0S|1S|1A|0B A→1C|1 B→0C|0 C→0C|1C|1|0 求出一个与G等价的左线性文法。
Y
4
正规式转化为NFA(2/2)
• 若 R 是复合正规式,则按下图的转换规则对 R 进行分裂和加 进新结,直至每个边上只留下一个符号(或 )为止。
A A
r1r2 r1|r2
B B
代换为 代换为
A A
r1
C r1 r2
r2
B B
A
r1*
B
代换为
A
C
r1
B
整个分裂过程中,所有新结点均采用不同的名字,保留 X,Y 为 全图唯一初态结点和终态结点
l
首先 M的状态分成两组:终态组{F},非终 态组{A,B,C,D,E} 考察{A,B,C,D,E},由于{A,B,C,D,E}1 属于 {B,C,F}, 它既不包含在{A,B,C,D,E}中也不包含在{F} 之中,因此,应把{A,B,C,D,E}一分为二。 因为状态 E 经 1 弧到达状态 F,而状态A、 B,C,D经 1 弧都到达 {B,C},因此,应把 E 分 出来,形成{A,B,C,D}、{E}、{F}。 {A,B,C,D}0 属于{D,E},它不含在任何划分 中,因为状态 C 经 0弧到达状态 E,而状态 {A,B,D}经 0 弧都到达 D,因此,应把 C 分 出来,形成{A,B,D}、{C}、{E}、{F}。 由于{A,B,D}1={B,C},它不包含在任何划 分之中,因此,应把{A,B,D}一分为二。因 为状态B、D经 1 弧都到达 {C},经 0弧都到 达 {D}因此,应把 A分出来,形成{A}、 {B,D}、{C}、{E}、{F}。{B,D}无法再分。 至此,整个分划含有四组: {A}、{B,D}、 {C}、{E}、{F} 。每个组都不可再分。
编译原理实验报告

《编译原理》实验报告软件131 陈万全132852一、需求分析通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。
通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。
1、词法分析程序设计与实现假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。
输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。
输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。
对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。
2、语法分析程序设计与实现选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。
G2[<算术表达式>]:<算术表达式> → <项> | <算术表达式>+<项> | <算术表达式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表达式>)若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。
程序设计语言编译程序构造的基本原理和基本实现技术概要

集成化的程序设计环境
五.编译程序生成
以汇编语言和机器语言为工具
优点:
可以针对具体的机器,充分发挥计 算机的系统功能。生成的程序效率高。 缺点: 程序难读、难写、易出错、难维护、 生产的效率低。
五.编译程序生成
高级语言书写
S I S 源程序
T I 实现语言
T 目标程序
优点: 程序易读、易理解、容易维护、 生产的效率高。 缺点: 难以充分发挥计算机的系统功能, 生成的程序效率低。
PROCEDURE INCWAP(M,N:INTEGER); LABEL START; VAR K:INTEGER; BEGIN START: K:=M+1; 表 0.1 符号名表 SNT M:=N+4; NAME INFORMATION N:=K; END. M 形式参数,整 型,值参数 N 形式参数,整 型,值参数 K 整型,变量
NAME INFORMATION (1) INCWAP 二目子程序, 入口四元式:1
PROCEDURE INCWAP(M,N:INTEGER); LABEL START; VAR K:INTEGER; BEGIN START: K:=M+1; M:=N+4; N:=K; 表 0.4 标号表 LT END. NAME INFORMATION (1) START 四元式:(4)
写出最后的译文。
二.
编译过程
编译程序的工作一般分为五个阶段:
词法分析 语法分析 中间代码产生 优化
目标代码产生
1. 词法分析
任务: 输入源程序,对构成源程序的字 符串进行扫描和分解,识别出一个个单 词符号。 依循的原则:构词规则 描述工具:有限自动机 FOR I := 1 TO 100 DO
编译原理预测分析法C语言的实验报告

题目:编写识别由下列文法所定义的表达式的预测分析程序。
E→E+T | E-T | TT→T*F | T/F |FF→(E) | i输入:每行含一个表达式的文本文件。
输出:分析成功或不成功信息。
(题目来源:编译原理实验(三)--预测(LL(1))分析法的实现)解答:(1)分析a) ∵E=>E+T=>E+T*F=>E+T*(E)即有E=>E+T*(E)存在左递归。
用直接改写法消除左递归,得到如下:E →TE’ E’ →+TE’ | −TE’|εT →FT’ T’ →*FT’ | /FT’|εF → (E) | i对于以上改进的方法。
可得:对于E’:FIRST( E’ )=FIRST(+TE’)∪FIRST(-TE’)∪{ε}={+,−,ε}对于T’:FIRST( T’ )=FIRST(*FT’)∪FIRST(/FT’)∪{ε}={*,∕,ε} 而且:FIRST( E ) = FIRST( T ) = FIRST( F )=FIRST((E))∪FIRST(i)={(,i }由此我们容易得出各非终结符的FOLLOW集合如下:FOLLOW( E )= { ),#}FOLLOW(E’)= FOLLOW(E)={ ),#}FOLLOW( T )= FIRST(E’)\ε∪FOLLOW(E’)={+,−,),#}FOLLOW( T’ ) = FOLLOW( T ) ={+,−,),#}FOLLOW( F )=FIRST(T’)\ε∪FOLLOW(T’)={*,∕,+,−,),#}由以上FOLLOW集可以我们可以得出SELECT集如下:对E SELECT(E→TE’)=FIRST(TE’)=FIRST(T)={ (,i }对E’ SELECT(E’ →+TE’)={ + }SELECT(E’ →−TE’)={ − }SELECT(E’ →ε)={ε,),#}对T SELECT(T→FT’)={(,i}对T’ SELECT(T’ →*FT’)={ * }SELECT(T’ →∕FT’)={ ∕ }SELECT(T’ →ε)={ε,+,−,),#}对F SELECT(F→(E) )={ ( }SELECT(F→i)={ i }∴SELECT(E’ →+TE’)∩SELECT(E’ →−TE’)∩SELECT(E’ →ε)=ΦSELECT(T’ →*FT’)∩SELECT(T’ →∕FT’)∩SELECT(T’ →ε)=ΦSELECT(F→(E) )∩SELECT(F→i)= Φ由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。
编译原理实验LL1分析

实验三语法分析---LL(1)分析器
一
(
1.用程序的方法实现语法分析的LL(1)方法。
}
void put_setence()
{
char ch;
int i=0;
while((ch=cin.get()) != '#') {
analyz_sentence[i] = ch;
i++;
}
analyz_sentence[i] = '#';
}
void init_stack()
{
stack[0] = '#';
return i;
}
return -1;
}
void reve()
{
strcpy(s, tp);
int i,j;
char t;
i=0;
while (s[i] != '\0')
++i;
--i;
if (s[i] == '\n')
--i;
j=0;
while (j<i)
{
t = s[j];
s[j] = s[i];
cout << "=>";
if (top == 'u')
pop();
}
void pop()
{
编译原理c语言编译器的设计与实现

经编译程序运行后得到的输出结果如下:
1〕词法分析得出的相应的名字的号码和他的值2〕列举程序中所有的变量
3〕状态栈的移进-归约过程1.
4〕最后产生的四元式中间代码
一、实验总结:
通过此次实验,让我知道了词法分析的功能是输出把它组织成单个程序,让我理解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;对语法规那么有明确的定义;编写的分析程序可以进展正确的语法分析;对于遇到的语法错误,可以做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;实验报告要求用文法的形式对语法定义做出详细说明,说明语法分析程序的工作过程,说明错误处理的实现。
通过该实验的操作,我理解编译原理课程兼有很强的理论性和理论性,是计算机专业的一门非常重要的专业根底课程,它在系统软件中占有非常重要的地位,是计算机专业学生的一门主修课。
为了让学生可以更好地掌握编译原理的根本理论和编译程序构造的根本方法和技巧,融会贯穿本课程所学专业理论知识,进步他们的软件设计才能,。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告《编译原理》课程预测分析程序设计与实现一、实验目的及要求1.根据文法采用手工方式或程序方式构造预测分析表的构造;2.若采用程序方式构造预测分析表,还需要考察文法、First(α)、Follow(A)的计算机实现,有一定难度,可以给予较高加分;3.必须针对相应预测分析表,设计并实现预测分析总控程序,从而完成一个具有自上而下分析能力的语法分析器(Parser)二、实验内容◆构造该文法的预测分析表◆实现预测分析的总控程序三、实验原理LL(1)文法的判定First集与Follow集的构造预测分析表的设计预测分析总控程序的设计与实现四、文法的定义E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→(E)|i五、实验步骤1.设计上下文无关文法;2.构造该文法的预测分析表;3.设计并实现相应的预测分析总控程序;六、描述核心数据结构和算法。
/*函数的定义*/int yuCeFenXi(){char X; /*X变量存储每次弹出的栈顶元素*/char a; /*a变量存储用户输入串的第一个元素*/int i;int counter=1; /*该变量记录语法分析的步骤数*/init(); /*初始化数组*/printf("wen fa : \n\n"); /*输出文法做为提示*/printf("E->Te \n");printf("e->+Te | $ \n");printf("T->Ft \n");printf("t->*Ft|$\n");printf("F ->(E)|i \n");printf("input string ,'#' is a end sign !!( i1+i2 ) \n "); /*提示用户输入将要测试的字符串*/scanf("%s",inputString);push('#');push('E');printf(" Counter-----Stack---------------Input string "); /*输出结果提示语句*/while(1) /*while循环为语法分析主功能语句块*/{printf(" ");printf("\n");printf(" %d",counter); /*输出分析步骤数*/printf(" "); /*输出格式控制语句*/printStack(); /*输出当前栈内所有元素*/X=pop(); /*弹出栈顶元素赋给变量X*/printinputString(); /*输出当前用户输入的字符串*/if( search(X)==0 ) /*在终结符集合VT中查找变量X的值,存在返回 1,否则返回 0*/{if(X == '#') /*栈已经弹空,语法分析结果正确,返回 1*/{printf("success ... "); /*语法分析结束,输入字符串符合文法定义*/return 1;}else{a = inputString[firstCharIntex];if( M(X,a)==1 ) /*查看预测分析表M[A,a]是否存在产生式,存在返回1,不存在返回0*/{for(i=0;i<13;i++) /* '$'为产生式的结束符,for循环找出该产生式的最后一个元素的下标*/{if( chanShengShi[i]=='$' ) break;}i-- ; /*因为 '$' 不是产生式,只是一个产生式的结束标志,所以i自减1*/while(i>=0){push( chanShengShi[i] ); /*将当前产生式逆序压入栈内*/i-- ;}}else{printf(" error(1) !!"); /*若预测分析表M[A,a]不存在产生式,说明语法错误*/return 0;}}}else /*说明X为终结符*/{if( X==inputString[firstCharIntex] ) /*如果X等于a,说明a匹配*/{firstCharIntex++; /*输入串的第一个元素被约去,下一个元素成为新的头元素*/}else{printf(" error(2) !! ");return 0;}}counter++;}}void init(){int i;for(i=0;i<13;i++){inputString[i]=NULL; /*初始化数组inputString[10] */stack[i]=NULL; /*初始化栈stack[10] */chanShengShi[i]=NULL; /*初始化数组chanShengShi[10]*/}}七、源程序#include <iostream.h>#include <string.h>#include <stdio.h>char inputString[13]; /*用来存储用户输入的字符串,最长为20个字符*/char stack[13]; /*用来进行语法分析的栈结构*/int base=0; /*栈底指针*/int top=1; /*栈顶指针*/char VT[5]={'i','+','*','(',')'}; /*用来存放5个终结符*/char chanShengShi[13]; /*用来存放预测分析表M[A,a]中的一条产生式*/int firstCharIntex=0; /*如果a匹配产生式,则每次firstCharIntex 自增 1 */ /*firstCharIntex用来存放用户输入串的第一个元素的下标*/char pop() ; /*弹出栈顶元素*/int push(char ch) ; /*向栈内添加一个元素,成功返回1,若栈已满则返回0*/int search(char temp) ; /*查找非终结符集合VT中是否存在变量temp,存在返回1,不存在返回0*/int M(char A, char a) ; /* 若预测分析表M[A,a]中存在产生式,则将该产生式赋给字符数组chanShengShi[10],并返回 1,若M[A,a]中无定义产生式则返回 0*/void init() ; /*初始化数组inputString[10] 、栈 stack[10] 和chanShengShi[10]*/int yuCeFenXi() ; /* 进行输入串的预测分析的主功能函数,若输入串满足文法则返回 1,不满足则返回0*/void printStack(); /*打印栈内元素 */void printinputString(); /*打印用户输入串 *//*进入主函数*/void main(){// clrscr();yuCeFenXi(); /*调用语法预测分析函数*///getch();}/*函数的定义*/int yuCeFenXi(){char X; /*X变量存储每次弹出的栈顶元素*/char a; /*a变量存储用户输入串的第一个元素*/int i;int counter=1; /*该变量记录语法分析的步骤数*/init(); /*初始化数组*/printf("wen fa : \n\n"); /*输出文法做为提示*/printf("E->Te \n");printf("e->+Te | $ \n");printf("T->Ft \n");printf("t->*Ft|$\n");printf("F ->(E)|i \n");printf("input string ,'#' is a end sign !!( i1+i2 ) \n "); /*提示用户输入将要测试的字符串*/scanf("%s",inputString);push('#');push('E');printf(" Counter-----Stack---------------Input string "); /*输出结果提示语句*/while(1) /*while循环为语法分析主功能语句块*/{printf(" ");printf("\n");printf(" %d",counter); /*输出分析步骤数*/printf(" "); /*输出格式控制语句*/printStack(); /*输出当前栈内所有元素*/X=pop(); /*弹出栈顶元素赋给变量X*/printinputString(); /*输出当前用户输入的字符串*/if( search(X)==0 ) /*在终结符集合VT中查找变量X的值,存在返回 1,否则返回 0*/{if(X == '#') /*栈已经弹空,语法分析结果正确,返回 1*/{printf("success ... "); /*语法分析结束,输入字符串符合文法定义*/return 1;}else{a = inputString[firstCharIntex];if( M(X,a)==1 ) /*查看预测分析表M[A,a]是否存在产生式,存在返回1,不存在返回0*/{for(i=0;i<13;i++) /* '$'为产生式的结束符,for循环找出该产生式的最后一个元素的下标*/{if( chanShengShi[i]=='$' ) break;}i-- ; /*因为 '$' 不是产生式,只是一个产生式的结束标志,所以i自减1*/while(i>=0){push( chanShengShi[i] ); /*将当前产生式逆序压入栈内*/i-- ;}}else{printf(" error(1) !!"); /*若预测分析表M[A,a]不存在产生式,说明语法错误*/return 0;}}}else /*说明X为终结符*/{if( X==inputString[firstCharIntex] ) /*如果X等于a,说明a匹配*/{firstCharIntex++; /*输入串的第一个元素被约去,下一个元素成为新的头元素*/}else{printf(" error(2) !! ");return 0;}}counter++;}}void init(){int i;for(i=0;i<13;i++){inputString[i]=NULL; /*初始化数组inputString[10] */stack[i]=NULL; /*初始化栈stack[10] */chanShengShi[i]=NULL; /*初始化数组chanShengShi[10]*/}}int M(char A, char a) /*文法定义因实际情况而定,该文法为课本例题的文法*/ { /*该函数模拟预测分析表中的二维数组 */ if( A=='E'&& a=='i' ) { strcpy(&chanShengShi[0],"Te$"); return 1; }if( A=='E'&& a=='(' ) { strcpy(&chanShengShi[0],"Te$"); return 1; }if( A=='e'&& a=='+' ) { strcpy(&chanShengShi[0],"+Te$"); return 1; }if( A=='e'&& a==')' ) { strcpy(&chanShengShi[0],"$"); return 1; }if( A=='e'&& a=='#' ) { strcpy(&chanShengShi[0],"$"); return 1; }if( A=='T'&& a=='i' ) { strcpy(&chanShengShi[0],"Ft$"); return 1; }if( A=='T'&& a=='(' ) { strcpy(&chanShengShi[0],"Ft$"); return 1; }if( A=='t'&& a=='+' ) { strcpy(&chanShengShi[0],"$"); return 1; }if( A=='t'&& a=='*' ) { strcpy(&chanShengShi[0],"*Ft$"); return 1; }if( A=='t'&& a==')' ) { strcpy(&chanShengShi[0],"$"); return 1; }if( A=='t'&& a=='#' ) { strcpy(&chanShengShi[0],"$"); return 1; }if( A=='F'&& a=='i' ) { strcpy(&chanShengShi[0],"i$"); return 1; }if( A=='F'&& a=='(' ) { strcpy(&chanShengShi[0],"(E)$"); return 1; }else return 0; /*没有定义产生式则返回0*/}char pop() /*弹出栈顶元素,用topChar返回*/{char topChar;topChar=stack[--top];return topChar;}int push(char ch){if( top>12 ){printf(" error : stack overflow "); /*栈空间溢出*/return 0;}else{stack[top]=ch; /*给栈顶空间赋值*/top++;return 1;}}int search(char temp){int i,flag=0; /*flag变量做为标志,若找到temp则赋1,否则赋0*/ for(i=0;i<5;i++){if( temp==VT[i] ) /*终结符集合中存在temp*/{flag=1;break;}}if(flag==1) return 1; /*flag==1说明已找到等于temp的元素*/else return 0;}void printStack() /*输出栈内内容*/{int temp;for(temp=1;temp<top;temp++){printf("%c",stack[temp]);}}void printinputString() /*输出用户输入的字符串*/{int temp=firstCharIntex ;printf(" "); /*该句控制输出格式*/do{printf("%c",inputString[temp]);temp++;}while(inputString[temp-1]!='#');printf(" ");}八、测试结果及实验总结1.实验截图2.实验总结这次的预测分析程序实验同样要求文法必须是LL(1)文法。