语法分析-自上而下分析

语法分析-自上而下分析
语法分析-自上而下分析

第四章语法分析—自上而下分析

知识结构:

带回溯分析法

回溯

自上而下分析面临的问题

左递归

问题的解决

语法分析-求FIRST、FOLLOW集合的算法自上而下分析LL(1)分析法证明LL(1)文法

构造LL(1)分析表

递归子程序的构造思想

递归子程序法递归子程序的特点

递归子程序的设计

第一节语法分析综述

一、语法分析的任务

按照语言即定的语法规则,对字符串形式的源程序进行语法检查,并识别出相应的语法成分。即语法结构是否符合语法规则。

二、语法分析器在编译程序中的地位(一遍扫描)

三、语法分析方法

通常把语法分析方法分为两大类,既自上而下分析与自下而上分析。

1、自上而下分析方法

实际上是一种产生的方法,分析过程是一个推导过程。

⑴自上而下分析过程

从文法G的开始符号S出发,通过反复使用产生式,逐步推导出与输入的符号串完全相匹配的句子。采用最左推导,以文法开始符号为根结点,逐步为输入串自上而下地构造一棵语法树。

面临的输入符号为a,A所有的产生式:

A12n

①若a FISRT(i),则指派去执行匹配任务。

②若a不属于任何一个候选首字符集,则:

a、若属于某个FISRT(i)且a FOLLOW(A),则让A 与自动匹配;

b、否则,a的出现是一种错误。

例:设有文法G和输入符号串W:a*a+a

G:S aA a

A BaA

B +-*/

推导过程:

S aA aBaA a*aA a*aBaA a*a+aA a*a+a=W 构造语法树:

S

a A

B a A

* B a A

+

⑵自上而下分析法

自上而下分析法又可分为确定和不确定的两种。

①不确定的分析法(带回溯)

是一种穷举的试探方法,效率低、代价高,极少使用。

②确定的分析法(不带回溯)

实现方法简单、直观,便于手工构造或自动生成语法分析器,是目前常用的方法之一。但是对文法有一定的限制。

2、自下而上分析法

⑴自下而上分析过程

分析过程是归约过程。从给定的输入串W开始,不断寻找与文法G中某个产生式P的侯选式(右部)进行匹配,并用P代替也称为归约。

⑵自下而上分析法

①算符优先分析法

定义算符(广义讲是文法的终结符号)之间的某种优先和结合关系,借助这种关系来寻找并确定可归约字符串,并进行归约。

②LR分析法

是一类自左向右对输入串进行扫描的自下而上分析方法,分析过程是规范归约的序列。适用于语法分析器的自动构造。

第二节自上而下分析面临的问题

一、不确定的自上而下分析方法

是从文法的开始S出发,试图用一切可能的方法向下推导,产生句子,这种分析过程的本质是一种试探推导过程。

例:文法G

⑴S aAd

⑵A ab a

构造W=aad的最左推导:S aAd aad。

构造语法树:

①产生树的根结点,即文法的开始符号。

②选用文法G的文法规则去延伸树。

③判断当前延伸的子结与输入串扫描到的字符是否匹配。

④若不匹配注销掉当前延伸的子树,选用文法规则的另一个产生式延伸分析树。

⑤直到输入串与语法树末端结点相匹配,分析结束。

S S S

a A d a A d a A d

a b

这种试探识别句子的过程,只会使分析的过程不确定。

二、不确定性的原因

由于分析过程中选择的侯选式不确定,造成输入串匹配的假象,甚至会导致算法实现的失败。

1、左递归问题

由于采用最左推导,左递归将使得输入串的分析过程陷入无限循环之中。

2、回溯问题

⑴采用试探的方法,如匹配不成功回溯到前面分析的某一步。

⑵可能出现假匹配,造成对输入串识别的失败。

⑶不能准确报告输入串的出错位置。

三、确定的自上而下分析方法

1、确定的自上而下分析方法的必要条件

⑴消除文法中的左递归;

⑵消除文法中的回溯问题。

2、消除文法的左递归

文法的左递归可以通过对文法产生式进行改写,使之不含有左递归的非终结符号。左递归一般有两种情况,直接左递归和间接左递归。

⑴直接左递归

如果文法中任意一个非终结符P,若P P(V N U V T),并且在最左推导中有P P形式,称为直接左递归。

⑵间接左递归

在最左推导中有P +

=>P形式,称为间接左递归。

①消除直接左递归

P→Pα |

改写为:P→P

P P

例:表达式文法

E E+T T

改写为:E TE

E+TE

T T*F F

改写为:T FT

T*FT

F(E) i

②消除文法的左递归一般规则

P→P1P2…… P m12……n i≠ε

改写为:

P→1P2P………n P

P→1P2P………m P

③消除间接左递归

A→B…

B→C…间接左递归: A B…C…A…

C→A…

例:文法G

S→Qc|c

Q→Rb|b

R→Sa|a

最左推导:S?Qc?Rbc?Sabc(间接左递归)

⑶清除间接左递归

非终结符排序为R,Q,S。R不存在直接左递归,把R代入Q的规则:

Q→Sab | ab | b

再把Q代入S:

S→Sabc | abc | bc | c

消除S的左递归:

S→abcS| bcS| cS

S→abcS| ε

Q和R的产生式不再被引用,将Q和R删除。

非终结符排序为S,Q,R。S不存在直接左递归,Q的产生式不包含S,再把S代入得到R:

R→Rbca | bca | ca | a

消除S的左递归:

R→bcaR| caR| aR

R→bcaR| ε

改写为:

S→Qc|c 不能删除

Q→Rb|b 不能删除

R→bcaR|caR|aR

R→bcaR|ε

3、消除回溯,提取左因子

⑴消除回朔

文法G不包含左递归,则G中非终结符号的每个候选式首字符集FIRST()为:

FIRST()={a *

=>a…,a V T,(V N U V T)

*}

若*

=>,则∈ FIRST()。

⑵提取最左公共因子

采用提取最左公共因子的方法改写文法,使得所有侯选式的

首字符集两两不相交。

A→12……n12

……m

提取公因子:

A→(12……n) 12……

m

改写后为:

A→A12……m

A→12……n

4、确定的自上而下分析方法

⑴预测分析法(LL(1)分析法)。

⑵递归子程序法。

第三节预测分析法(LL(1)分析法)

一、LL(1)分析方法

1、是按自左(第一个“L”)向右的顺序扫描输入字符串;

2、在分析过程中产生句子的最左(第二个“L”)推导;

3、“1”表示在分析过程中,每一步推导,最多只能向前查看(向右扫描)一个字符。

二、LL(K)分析方法

如果分析过程的每一步推导,要向前查看K个输入字符,则称为LL(K)分析法。

三、LL(1)文法的定义

该文法是上下文无关的一个子集,是自上而下分析技术的一

类文法。

四、LL(1)分析法的必要条件

1、文法中的非终结符号不包含左递归;

2、对于文法中的每一个非终结符A的各个产生式的侯选首字符集两两不相交。对于产生式A:

⑴若ε,证明侯选式,的首字符集是否相交。

FIRST()∩FIRST()= Ф

⑵若=ε,证明FIRST(A)和FOLLOW(A)是否相交。

FIRST(A)∩FOLLOW(A)=φ

五、构造FIRST集合的算法

对每一文法符号X(V N U V T)*

1、若X V T ,则FIRST(X)={X}。

2、若X V N ,且有产生式X a,a V T,则a FIRST (X)。

3、若X V N ,X,则FIRST(X)

4、若X V N,且Y1,Y2,,Y i V N,

而有产生式X Y1,,Y n。当Y1,Y2,,Y i-1都* =>

ε时,(其中1≤i≤n),则FIRST(Y1,)-{},,FIRST(Y i-1)

-{},

FIRST(Y i)都包含在FIRST(X)中。若FIRST(Y j)包含把加到FIRST(X)中。

例文法G

E →T E`

E`→+TE`|ε

T →F T`

T`→*FT`|ε

F→(E)|i

FIRST(E)=FIRST(T)=FIRST(F)={(,i )}

FIRST(E)={ +,ε}

FIRST(T)={ *,ε}

六、构造FOLLOW集合的算法

FOLLOW (A)={a | S *

=>….Aa…. , a V T }

若S *

=>…A, 则#FOLLOW (A)

FOLLOW (A)为所有句型中紧跟在非终结符A后面的所有终结符集合。

构造算法:

1、对文法开始符号S,将“#”置于FOLLOW(S)中。

即FOLLOW(S) = # 。

2、若A →αBβ是一个产生式,则把FIRST(β)-{ε}加至FOLLOW(B)中。

3、若A →αB是一个产生式,或A→αBβ是一个产生式,而β?ε(即FIRST());则把FOLLOW(A)加至FOLLOW(B)中。

例文法G

E→T E`

E`→+TE`|ε

T →F T`

T`→*FT`|ε

F→(E)|i

求FOLLOW(E):

因为F→(E),所以FIRST())加入FOLLOW(E)中,FOLLOW(E) = );

又因为E→TE`,E是文法的开始符号,则#加至FOLLOW(E)中,所以

FOLLOW(E)= # U FOLLOW(E)=#,) 。

求FOLLOW(E`):

因为E→TE`, 满足算法(3)若A →αB是一个产生式,则

把FOLLOW(A)加至FOLLOW(B)中,所以

FOLLOW(E`)= FOLLOW(E)U FOLLOW(E)

= #,)

求FOLLOW(T):

因为E→T E`, 满足算法⑵若A →αBβ是一个产生式,则把FIRST(β)\{ε}加至FOLLOW(B)中,所以

FOLLOW(T) = FOLLOW(T) U FIRST(E`)\{ε}

= {+}

又因为E`?ε,满足算法(3)若A→αBβ是一个产生式,而β?ε,则把FOLLOW(A)加至FOLLOW(B)中。所以

FOLLOW(T) = FOLLOW(E) U FOLLOW(T)

= #,) U+

= #,),+

求FOLLOW(T`):

因为T→F T`,满足算法(3)若A →αB是一个产生式,则

把FOLLOW(A)加至FOLLOW(B)中,所以

FOLLOW(T) = FOLLOW(T) U FOLLOW(T`)

= #,),+

求FOLLOW(F):

因为T→F T`, 满足算法⑵若A →αBβ是一个产生式,则把FIRST(β)\{ε}加至FOLLOW(B)中,所以

FOLLOW(F) = FOLLOW(F) U FIRST(T`)\{ε}= {*}

又因为T`?ε,满足算法(3)若A→αBβ是一个产生式,而β?ε,则把FOLLOW(A)加至FOLLOW(B)中。所以

FOLLOW(F) = FOLLOW(T) U FOLLOW(F)

= #,),+U*

= #,),+,*

连续使用上述三条规则,直到每个FOLLOW不再增大为止。

FOLLOW(E)= FOLLOW(E)= #,)

FOLLOW(T)= FOLLOW(T)= #,),+

FOLLOW(F)= #,),+,*

七、证明上述文法是否为LL(1)文法

对于产生式A:

1、若ε,证明侯选式,的首字符集是否相交。

FIRST()∩FIRST()= Ф

例:F(E)i

FIRST(()∩FIRST(i)= Ф

2、若=ε,证明FIRST(A)和FOLLOW(A)是否相交。

FIRST(A)∩FOLLOW(A)=φ

例:E`+TE`

FIRST(E`)∩FOLLOW(E`)

=+,∩),# =φ

八、构造分析表的算法

1、对文法G的每个产生式A→α执行第二步和第三步;

2、对每个终结符a FIRST(α),把A→α加至M[A,a]中;

3、若εFIRST(α),则对任何b FOLLOW(A)把A→α(或A)加至M[A,b]中;

4、把所有无定义的M[A ,a]标上“出错标志” 例: E →TE` , E`→+TE`′|ε

T →FT` , T`→*FT`′|ε

F →(E )|i

求其FIRST 的集合:

FIRST (E )=FIRST (T )=FIRST (F )={(,i )} FIRST (E

)={ +,ε},FIRST (T

)={ *,ε}

求其FOLLOW 的集合: FOLLOW(E)= FOLLOW(E )= #,

)

FOLLOW(T)= FOLLOW(T

)=

#,),

+

FOLLOW(F)=

#,),+,

*

根据算法构造LL (1)的分析表:

九、LL (1)分析器的逻辑结构与分析程序 1、LL (1)分析器的逻辑结构

LL (1)分析法,由总控程序控制输入字符串,在一张LL (1)分析表和一个分析工作栈上运行,而完成语法分析任务的。 输入字符串 a 1 a 2

a i

a n

终结符 非终结符 i + * ( ) #

E TE` TE` E` +TE`

其中:

①分析表,实现相应的分析动作,即对[A i,a j],设A i表示当前分析工作栈顶为A i,输入字符为a j时,应选用A i进行推导。

②分析工作栈,用于存放分析过程中的文法符号。分析工作栈初始化时,在工作栈顶写入一个“#”,再写入文法开始符号。

③总控程序,依据分析工作栈和分析表联合控制输入串的识别和分析。

2、分析程序的工作原理

⑴把“#”和文法开始符号推入分析工作栈;设置指示器的初始值,用第一个输入符号(终结符号)与分析工作栈顶文法符号进行匹配。

⑵设在某一步的分析工作栈与输入串的当前工作状态:

X1X2X m-1X m为分析工作栈中的当前状态;a i a i+1#为输入串的当前状态。

①若X m V N,则以X m及a i组成符号对(X m,a i)查分

析表M[X m,a i],设X m UVW,将X m从分析工作栈顶退出,并将UVW按反向写入分析工作栈中。若M[X m,a i]=“Error”,则调用出错处理程序。

②若X m V T并且X m=a i,则表明分析工作栈顶的符号与当前输入符号相匹配,将工作栈顶的符号X m退出,输入符号指针向右移一位。

③若X m=#,则表明输入符号串已完全匹配,分析成功结束分析工作。

3、分析程序的算法(P77)

例:对输入串# i*i+i #的预测分析过程

P78

第四节递归下降分析程序的构造

一、递归下降分析程序的构造方法

对文法的每个非终结符号,根据各侯选式的结构,编写一个对应的子程序,完成非终结符相应的语法成分的识别和分析任务。

二、递归下降分析程序的功能

对某个非终结符,用产生式规则的右部符号进行匹配。

三、递归下降分析程序的特点

1、程序结构清晰,易于手工操作。

2、对语义处理灵活。

四、递归下降分析法的必要条件

必须是不包含左递归和回溯的上下文无关文法。

五、递归下降分析程序的设计

P74

第五节预测分析法的错误处理

一、出错情况

1、工作栈顶终结符与输入符号不匹配。

2、对应M[A,a]中为空(Error)。

二、出错处理

1、报告出错(出错位置,出错性质)。

2、处理出错情况,使语法分析继续下去:

⑴若M[A,a]中为空(Error),跳过输入符号a,若该项为同步(synch),则退出工作栈顶的非终结符A。

⑵工作栈顶的终结符无法与输入符号匹配,则弹出该符号。

第六节学习与理解

一、填空题

⑴自上而下语法分析方法的基本思想是:从文法的开始符号出发。不断建立最左直接推导,试图构造一个推导序列,最终由它推导出与输入符号串相同的符号串。

⑵自上而下分析方法会遇到的主要问题有回溯和左递归。

⑶在语法分析中,最常见的两种方法一定是自上而下分析法,

另一种是自下而上分析法。

二、选择题

⑴编译过程中,语法分析器的任务是B,C,D。

A、分析单词是怎样构成的

B、分析单词串是如何构成语句的

C、分析语句是如何构成程序的

D、分析程序结构

⑵高级语言编译程序常用的语法分析方法中,递归下降分析法属于B分析方法。

A、自左至右

B、自上而下

C、自下而上

D、自右至左

三、解答题

⑴已知文法G:

A aAa

①该文法是LL(1)文法吗?为什么?

②若采用LL(1)方法进行分析,如何得到该文法的LL(1)分析表。

③若输入串“aaaa”,请给出语法分析过程。

解:

①因为FOLLOW(A)=FOLLOW(A)FIRST(A)={a,#},造成FOLLOW(A)FIRST(A)={a,#}{a,},所以该文法不是LL(1)文法。

②若采用LL(1)方法进行语法分析,必须修改该文法。因该文法产生偶数(可以为0)个a,所以得到文法G`:A aaA 。

此时FOLLOW(A)={#},因此

FOLLOW(A )FIRST(A)={#}{a ,}=

所以文法G`是LL(1)文法。该文法的LL(1)分析表:

V T a #

V N

A A aaA A

③对符号串“aaaa”的分析过程:

A aaA

A aaA

A

⑵设文法G(A):

A aABc aA

B Bb d

①试给出文法G(A)等价的LL(1)文法G`(A)。

②构造G`(A)的LL(1)分析表,给出输入串aadc#的分析过程。

编译原理实验报告《LL(1)语法分析器构造》

《LL(1)分析器的构造》实验报告 一、实验名称 LL(1)分析器的构造 二、实验目的 设计、编制、调试一个LL(1)语法分析器,利用语法分析器对符号串的识别,加深对语法分析原理的理解。 三、实验内容和要求 设计并实现一个LL(1)语法分析器,实现对算术文法: G[E]:E->E+T|T T->T*F|F F->(E)|i 所定义的符号串进行识别,例如符号串i+i*i为文法所定义的句子,符号串ii+++*i+不是文法所定义的句子。 实验要求: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。 四、主要仪器设备 硬件:微型计算机。 软件: Code blocks(也可以是其它集成开发环境)。 五、实验过程描述 1、程序主要框架 程序中编写了以下函数,各个函数实现的作用如下: void input_grammer(string *G);//输入文法G

//将文法G预处理得到产生式集合P,非终结符、终结符集合U、u, int eliminate_1(string *G,string *P,string U,string *GG);//消除文法G中所有直接左递归得到文法GG int* ifempty(string* P,string U,int k,int n);//判断各非终结符是否能推导为空 string* FIRST_X(string* P,string U,string u,int* empty,int k,int n);求所有非终结符的FIRST集 string FIRST(string U,string u,string* first,string s);//求符号串s=X1X2...Xn的FIRST集 string** create_table(string *P,string U,string u,int n,int t,int k,string* first);//构造分析表 void analyse(string **table,string U,string u,int t,string s);//分析符号串s 2、编写的源程序 #include #include #include using namespace std; void input_grammer(string *G)//输入文法G,n个非终结符 { int i=0;//计数 char ch='y'; while(ch=='y'){ cin>>G[i++]; cout<<"继续输入?(y/n)\n"; cin>>ch; } } void preprocess(string *G,string *P,string &U,string &u,int &n,int &t,int &k)//将文法G预处理产生式集合P,非终结符、终结符集合U、u, { int i,j,r,temp;//计数 char C;//记录规则中()后的符号 int flag;//检测到() n=t=k=0; for( i=0;i<50;i++) P[i]=" ";//字符串如果不初始化,在使用P[i][j]=a时将不能改变,可以用P[i].append(1,a) U=u=" ";//字符串如果不初始化,无法使用U[i]=a赋值,可以用U.append(1,a) for(n=0;!G[n].empty();n++) { U[n]=G[n][0]; }//非终结符集合,n为非终结符个数 for(i=0;i

实验三 自下而上语法分析及语义分析

实验三自下而上语法分析及语义分析 一、实验目的: 通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。 二、实验学时: 4学时。 三、实验内容 根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。 对于正确的表达式,给出表达式的值。 对于错误的表达式,给出出错位置。 四、实验方法 采用LR分析法。 首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。 接下来给出LR分析表。 然后程序的具体实现: ●LR分析表可用二维数组(或其他)实现。 ●添加一个val栈作为语义分析实现的工具。 ●编写总控程序,实现语法分析和语义分析的过程。 注:对于整数的识别可以借助实验1。 五、文法定义 简单的表达式文法如下: E->E+T|E-T|T T->T*F|T/F|F F->(E)|i 上式中,i 为整数。 六、处理程序例 例1: 正确源程序例: 23+(45+4)* 40分析结果应为:正确的表达式。其值为:1983 例2: 错误源程序例: 5+(56+)-24 分析结果应为:错误的表达式:出错位置为)

附录:源程序 #include #include"string.h" #include using namespace std; #define R 30 #define C 20 typedef struct elem { char e[4]; }Elem; //ACTION表与GoTo表中的元素类型 Elem LR[R][C]; //存放ACTION表与GoTo表中的内容 typedef struct out { int order; //序号 int state[10]; //状态栈 char sign[30]; //符号栈 char grasen[20]; //产生式 char input[30]; //输入串 char explen[50]; //解释说明 }OutNode; //输出结果中每一行的类型 OutNode out[20]; //存放输出结果 char Sentence[20]; //存放文法的一个句子 char GramSent[10][20]; //存放文法的一组产生式

语法分析(自上而下分析)实验报告

实习二语法分析-自上而下分析 一、实验目的 使用预测分析方法对输入的表达式进行分析,掌握其具体的使用并且学会去分析一个文法。 二、实验内容 1.设计表达式的语法分析器算法(使用预测分析) 2.编写一段代码并上机调试查看其运行结果 三、实验要求 使用LL(1)分析算法设计表达式的语法分析器 LL(1)文法是一个自上而下的语法分析方法,它是从文法的开始符号出发,生成句子的最左推导,从左到右扫描源程序,每次向前查看一个字符,确定当前应该选择的产生式。 实现LL(1)分析的另一种有效方法是使用一张分析表和一个栈进行联合控制。 预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前a的输入符号行事的。对于任何(X,a),总控程序每次都执行三种可能的动作之一。 1.若X=a=“#”,则宣布分析成功,停止分析过程 2.若X=a≠“#”,则把X从STACK栈顶逐出,让a指向下一 个输入符号。 3.若X是一个非终结符,则查看分析表。 四、运行结果

(本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析) 五、源程序实现 /*LL(1)分析法源程序,只能在VC++中运行*/ #include #include #include #include char A[20]; char B[20]; char v1[20]={'i','+','*','(',')','#'};/*终结符*/ char v2[20]={'E','G','T','S','F'};/*非终结符*/ int j=0,b=0,top=0,l;/*L为输入串长度*/

自顶向下的语法分析(实验报告一)

武汉轻工大学 编译原理实验报告 姓名朱春桃 院(系)数学与计算机学院 班级软件工程1203 学号 1205110605 指导教师李禹生 2014 年11 月10 日

一、实验目的 完成自顶向下语法分析算法的程序设计。 二、实验内容 设计、调试并测试自顶向下语法分析算法程序。 三、设计思路 根据课堂讲授的自顶向下语法分析方法,可以根据递归下降子程序方法设计语法分析程序,也可以根据LL(1)算法设计语法分析程序,针对文法:G[E] E→E+T | T T→T*F | F F→( E ) | i (1)由于文法G[E]不满足LL(1)文法条件,需要进行必要的等价文法变换。变换后的等价文法为: H[E] E→TA A→+TA | ε T→FB B→*FB | ε F→( E ) | i (2)等价文法H[E]不含左递归,可以证明文法H[E]满足LL(1)文法条件(3)根据递归下降子程序方法设计语法分析程序 ①递归程序清单 ②调试过程说明 ③测试语句设计 ④测试结果列表 ⑤测试结论分析 (4)根据LL(1)算法设计语法分析程序 ①预测分析表 ②预测分析程序清单 ③调试过程说明 ④测试语句设计 ⑤测试结果列表

⑥测试结论分析 四、程序清单 /* E->TA, A->+TA|ε, T->FB, B->*FB|ε, F->i|(E). */ #include void E(char str[80],int &i,int &err or); void A(char str[80],int &i,int &error); void T(char str[80],int &i,int &error); void B(char str[80],int &i,int &error); void F(char str[80],int &i,int &error); void main() { int i=0,j=0,error=0; char str[80]; printf("请输入字符串('#'为结束字符):"); while ((str[j]=getchar())!='#') j++; str[j]='#'; E(str,i,error); if(error) printf("error\n"); else printf("right\n"); } void E(char str[80],int &i,int &error) { printf("E->TA\n"); T(str,i,error); A(str,i,error); } void A(char str[80],int &i,int &error) { if(str[i]=='+') { printf("A->+TA|ε\n"); i++; T(str,i,error); A(str,i,error);

TEST语言 -语法分析,词法分析实验报告

编译原理实验报告 实验名称:分析调试语义分析程序 TEST抽象机模拟器完整程序 保证能用!!!!! 一、实验目的 通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法范畴变换为中间代码的语义翻译方法。 二、实验设计 程序流程图

extern int TESTScan(FILE *fin,FILE *fout); FILE *fin,*fout; //用于指定输入输出文件的指针 int main() { char szFinName[300]; char szFoutName[300]; printf("请输入源程序文件名(包括路径):"); scanf("%s",szFinName); printf("请输入词法分析输出文件名(包括路径):"); scanf("%s",szFoutName); if( (fin = fopen(szFinName,"r")) == NULL) { printf("\n打开词法分析输入文件出错!\n"); return 0; } if( (fout = fopen(szFoutName,"w")) == NULL) { printf("\n创建词法分析输出文件出错!\n"); return 0; } int es = TESTScan(fin,fout); fclose(fin); fclose(fout); if(es > 0) printf("词法分析有错,编译停止!共有%d个错误!\n",es); else if(es == 0) { printf("词法分析成功!\n"); int es = 0;

编译原理LL(1)语法分析实验报告

学号20102798 专业软件工程姓名薛建东 实验日期2013.04.08 教师签字成绩实验报告 【实验名称】LL(1)语法分析 【实验目的】 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。 【实验内容】 ◆根据某一文法编制调试LL ( 1)分析程序,以便对任意输入的符号串进行分析。 ◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。 ◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1) 分析表,对输入符号串自上而下的分析过程。 【设计思想】 (1)、LL(1)文法的定义 LL(1)分析法属于确定的自顶向下分析方法。LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。 LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。 需要预测分析器对所给句型进行识别。即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=? (2)、预测分析表构造 LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推

第五章 自上而下语法分析

第五章自上而下语法分析 1、教学目的及要求: 本章介绍编译程序的第二个阶段语法分析的设计方法和实现原理,包括自上而下分析的无回朔的递归下降分析、 LL(1)分析法。要求理解递归下降分析、LL(1)文法的基本概念;掌握无回朔的递归下降分析的设计和实现、LL(1)分析表的构造与分析方法。 ◇能够对一个给定的文法判断是否是LL(1)文法; ◇能构造预测分析表; ◇能用预测分析方法判断给定的输入符号串是否是该文法的句子; ◇能对某些非LL(1)文法做等价变换: ①消除左递归 ②提取左公共因子 可能会变成LL(1)文法。这样可扩大自顶向下分析方法的应用。 2、教学内容: 语法分析器的功能,自上而下语法分析(递归下降分析法,预测分析程序),LL(1)分析法,递归下降分析程序构造,预测分析程序。 3、教学重点: 递归下降子程序,预测分析表构造,LL(1)文法。 4、教学难点: 对一个文法如何判断是否是LL(1)文法,由于在判断 LL(1)文法时用到文法符号串的开始符号集合(FIRST集)和非终结符后跟符号集合(FOLLOW集)的计算,而一般学生往往因概念不清或不够细心对这两个集合的计算常常出错,导致判断和分析结果的错误。 5、课前思考 为了了解自顶向下(自上而下)分析的一般过程和问题,请学生首先回顾本章之前介绍的有关基本概念: ◇句子、句型和语言的定义是什么? ◇什么叫最左推导? ◇什么叫最右推导和规范推导? ◇什么叫确定的自顶向下语法分析?

◇自顶向下语法分析是从文法的开始符号出发,反复使用各种产生式,寻找与输入符号匹配的推导。 ◇确定的自顶向下语法分析中用的是哪种推导? ◇在确定的自顶向下语法分析过程中,当以同一个非终结符为左部的产生式有多个不同右部时,如何选择用哪个产生式的右部替换当前的非终结符? ◇确定的自顶向下语法分析对文法有何限制? 6、章节内容 第一节概述 第二节 LL(1)分析方法 第三节递归下降分析法 5.1 概述 LL分析法 确定的自上而下分析 自上而下分析递归下降分析法 语法分析不确定的自上而下分析——即带回溯的分析方法 算符优先分析 自下而上分析 LR分析 一、带回溯的自顶向下分析方法 是自顶向下分析的一般方法,即对任一输入符号串,试图用一切可能的办法,从树根结点(识别符号)出发,根据文法自上而下地为输入串建立一棵语法树,或者说,从识别符号开始,根据文法为输入串建立一个推导序列,这种分析过程本质上是一种试探过程,是反复使用不同规则谋求匹配输入串的过程。 例有文法G[S]:S→cAd,A→ab|a,输入串w=cad。其分析过程为带回溯的。 二、存在问题及解决办法 1、左递归问题: 自顶向下分析方法只有把规则排列得合适时才能正确工作,该方法不能处理具有左递归性文法,可采取某些算法消除左递归。 2、回溯问题:

编译原理 第四章自顶向下语法分析法

第四章 自顶向下语法分析方法 语法分析是编译过程的核心部分。语法分析的任务是:按照文法,从源程序符号串中识别出各类语法成份,同时进行语法检查,为语义分析和代码生成作准备。执行语法分析任务的程序称为分析程序。也称为语法分析器,它是编译程序的主要子程序之一。 在第二章中我们已经介绍过。通过语法分析可建立起相应的语法树。按语法树的建立方法,我们将语法分析方法分成两大类,即自顶向下分析和自底向上分析。下面,我们先介绍自顶向下分析。 本章重点:自顶向下分析、LL (1)分析 第一节 自顶向下分析方法 一、带回溯的自顶向下分析算法 这是自顶向下分析的一般方法,即对任一输入符号串,试图用一切可能的方法,从识别符号出发,根据文法自上而下地为输入串建立一棵语法树。 下面用一个简单例子来说明这种过程: 假定有文法G[S]: S→c Ad A →ab|a 以及输入串w=cad 为了自上而下地构造w 的语法树,我们首先按文法的识别符号产生根结点S ,并让指示器IP 指 c S 的规则仅有一条)把这棵树发展为 ( a ) (b ) (c ) 图3-1-1 图3-1-1a 。我们希望用S 的子结从左至右匹配整个输入串w 。首先,此树的最左子结是终结符c 为标志的子结,它和输入串的第一个符号相匹配。于是,我们就把IP 调整为指向下一输入符号a ,并让第二个子结A 去进行匹配,非终结符A 有二个选择,我们试着用它的第一个选择去匹配输入串,于是把语法树发展为图3-1-1b 。子树A 的最左子结和IP 所指的符号相符,然后我们再把IP 调为指向下一符号d 并让A 的第二个子结进入工作。但A 的第二个子结为终结符号b ,与IP 当前指的符号d 不一致。因此,A 宣告失败。这意味着A 的第一个选择此刻不适用于构造w 的语法树。这时,我们应该回头(回溯)看A 是否还有别的选择。 为了实现回溯,我们一方面应把A 的第一个选择所生长的子树注销掉;另一方面,应把IP 恢复为进入A 时的原值,也就是让它重新指向第二输入符号a 。现在我们试探用A 的第二个选择,即考虑生成图3-1-1c 的语法树。 由于子树A 只有一个子结a ,而且,它和IP 所指的符号相一致,于是,A 完成了匹配任务。在A 获得匹配后,指示器指向下一个未被触及的符号d 。 在S 的第二子结A 完成匹配后,接着就轮到第三个子结d 进行工作。由于这个子结和最后一个输入符号相符,于是,我们完成了构造语法树的任务,证明了w 是文法G[ s]的一个句子。 上述自顶向下地为输入符号w 建立语法树的过程,实际上也是设法建立一个最左推导序列,以便通过一步步推导将输入串推导出来。很明显,对于输入串w 可以通过如下的推导过程将其推导出来:S ?CAd ?cad 所以用最左推导,是因为我们对输入串是自左向右扫描的,只有使用最左推导,才能保证按扫描顺序去匹配输入串。在上述推出符号串w 的过程中,由于出现在符号串中的非终结符号只有一个,因此,未明显地表现出最左推导的性质。 根据以上分析,不难编出程序来实现这种分析的算法。但是,上述这种自顶向下的分析算法存

语法分析-自上而下分析

第四章语法分析—自上而下分析 知识结构: 带回溯分析法 回溯 自上而下分析面临的问题 左递归 问题的解决 语法分析-求FIRST、FOLLOW集合的算法自上而下分析LL(1)分析法证明LL(1)文法 构造LL(1)分析表 递归子程序的构造思想 递归子程序法递归子程序的特点 递归子程序的设计 第一节语法分析综述 一、语法分析的任务 按照语言即定的语法规则,对字符串形式的源程序进行语法检查,并识别出相应的语法成分。即语法结构是否符合语法规则。 二、语法分析器在编译程序中的地位(一遍扫描)

三、语法分析方法 通常把语法分析方法分为两大类,既自上而下分析与自下而上分析。 1、自上而下分析方法 实际上是一种产生的方法,分析过程是一个推导过程。 ⑴自上而下分析过程 从文法G的开始符号S出发,通过反复使用产生式,逐步推导出与输入的符号串完全相匹配的句子。采用最左推导,以文法开始符号为根结点,逐步为输入串自上而下地构造一棵语法树。 面临的输入符号为a,A所有的产生式: A12n ①若a FISRT(i),则指派去执行匹配任务。 ②若a不属于任何一个候选首字符集,则: a、若属于某个FISRT(i)且a FOLLOW(A),则让A 与自动匹配; b、否则,a的出现是一种错误。 例:设有文法G和输入符号串W:a*a+a G:S aA a A BaA

B +-*/ 推导过程: S aA aBaA a*aA a*aBaA a*a+aA a*a+a=W 构造语法树: S a A B a A * B a A + ⑵自上而下分析法 自上而下分析法又可分为确定和不确定的两种。 ①不确定的分析法(带回溯) 是一种穷举的试探方法,效率低、代价高,极少使用。 ②确定的分析法(不带回溯) 实现方法简单、直观,便于手工构造或自动生成语法分析器,是目前常用的方法之一。但是对文法有一定的限制。 2、自下而上分析法 ⑴自下而上分析过程 分析过程是归约过程。从给定的输入串W开始,不断寻找与文法G中某个产生式P的侯选式(右部)进行匹配,并用P代替也称为归约。 ⑵自下而上分析法

编译原理实验三-自下而上语法分析及语义分析.docx

上海电力学院 编译原理 课程实验报告 实验名称:实验三自下而上语法分析及语义分析 院系:计算机科学和技术学院 专业年级: 学生姓名:学号: 指导老师: 实验日期: 实验三自上而下的语法分析 一、实验目的: 通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。 二、实验学时: 4学时。 三、实验内容

根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。 对于正确的表达式,给出表达式的值。 对于错误的表达式,给出出错位置。 四、实验方法 采用LR分析法。 首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。 接下来给出LR分析表。 然后程序的具体实现: ● LR分析表可用二维数组(或其他)实现。 ●添加一个val栈作为语义分析实现的工具。 ●编写总控程序,实现语法分析和语义分析的过程。 注:对于整数的识别可以借助实验1。 五、文法定义 简单的表达式文法如下: (1)E->E+T (2)E->E-T (3)E->T

(4)T->T*F (5)T->T/F (6)T->F (7)F->(E) (8)F->i 状态ACTION(动作)GOTO(转换) i + - * / ( ) # E T F 0 S5 S4 1 2 3 1 S6 S1 2 acc 2 R 3 R3 S7 S13 R3 R3 3 R6 R6 R6 R6 R6 R6 4 S 5 S4 8 2 3 5 R8 R8 R8 R8 R8 R8 6 S5 S4 9 3 7 S5 S4 10 8 S6 R12 S11 9 R1 R1 S7 S13 R1 R1 10 R4 R4 R4 R4 R4 R4 11 R7 R7 R7 R7 R7 R7 12 S5 S4 14 3 13 S5 S4 15 14 R2 R2 S7 S13 R2 R2 15 R5 R5 R5 R5 R5 R5 五、处理程序例和处理结果例 示例1:20133191*(20133191+3191)+ 3191#

语法分析器实验报告

语法分析器的设计实验报告 一、实验内容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

编译原理-四章自顶向下语法分析法

第四章自顶向下语法分析方法 语法分析是编译过程的核心部分。语法分析的任务是:按照文法,从源 程序符号串中识别出各类语法成份,同时进行语法检查,为语义分析和代码生成作准备。执行语法分析任务的程序称为分析程序。也称为语法分析器,它是编译程序的主要子程序之一。 在第二章中我们已经介绍过。通过语法分析可建立起相应的语法树。按语法树的建立方法,我们将语法分析方法分成两大类,即自顶向下分析和自底向上分析。下面,我们先介绍自顶向下分析。 本章重点:自顶向下分析、LL(1)分析 第一节自顶向下分析方法 一、带回溯的自顶向下分析算法 这是自顶向下分析的一般方法,即对任一输入符号串,试图用一切可能的方法,从识别符号出发,根据文法自上而下地为输入串建立一棵语法树。 下面用一个简单例子来说明这种过程: 假定有文法G[S] : S—c A d A — ab|a 以及输入串w=cad 为了自上而下地构造w的语法树,我们首先按文法的识别符号产生根结点S, 并让指示器IP 指

向输入串的第一符号c。然后,用S的规则(此处左部为S的规则仅有一条)把这棵树发展为| (a) (b)(c) 图3-1-1 图3-1-1a。我们希望用S的子结从左至右匹配整个输入串w。首先,此树的最左子结是终结符c为标志的子结,它和输入串的第一个符号相匹配。于是,我们就把IP调整为指向下一输入符号a,并让第二个子结A去进行匹配,非终结符A有二个选择,我们试着用它的第一个选择去匹配输入串,于是把语法树发展为图3-1-1b。子树A的最左子结和IP所指的符号相符,然后我们再把IP调为指向下一符号d并让A的第二个子结进入工作。但A 的第二个子结为终结符号b,与IP当前指的符号d不一致。因此,A宣告失败。这意味着A的第一个选择此刻不适用于构造w的语法树。这时,我们应该回头(回溯)看A是否还有别的选择。 为了实现回溯,我们一方面应把A的第一个选择所生长的子树注销掉;另一方面,应把IP恢复为进入A时的原值,也就是让它重新指向第二输入符号a。现在我们试探用A的第二个选择,即考虑生成图3-1-1C的语法树。 由于子树A只有一个子结a,而且,它和IP所指的符号相一致,于是,A

LL(1)语法分析实验报告

实验报告 姓名:孙岩 学号:1408080211 班级:惠普开发142 学校:青岛科技大学Mail: 电话:178******** 教师:宮生文

实验报告: 实验名称:LL(1)语法分析 实验目的和要求 编制一个能识别由词法分析给出的单词符号序列是否是给定文法的正确句子(程序),输出对输入符号串的分析过程。 实验内容和步骤: 一、实验内容 对于这个实验,总共用了三个函数,即主函数、输出分析栈函数、输出剩余串函数。在主函数中,还要构造预测分析表。 二、实验步骤 1、基于实验的内容,构造程序所需的模块 2、根据已建构的模块,写出各个模块的相应程序代码 3、在主函数中调用模块来完成所要得到的效果 在本程序中,首先使用了结构体类型定义来定义产生式,用字符串数组存放分析栈、剩余串、终结符和非终结符,用二维数组存放预测分析表,利用指针对栈中数据进行读取。在本程序中,总共用了三个函数,即主函数、输出分析栈函数、输出剩余串函数。在主函数中,还要构造预测分析表,对输入的字符串进行分析,调用另外两个函数。 实验代码如下: #include #include #include #include char A[20];/*分析栈*/ char B[20];/*剩余串*/ char v1[20]={'i','+','*','(',')','#'};/*终结符*/ char v2[20]={'E','G','T','S','F'};/*非终结符*/ int j=0,b=0,top=0,l;/*L为输入串长度*/ typedef struct type/*产生式类型定义*/ { char origin;/*大写字符*/ char array[5];/*产生式右边字符*/ int length;/*字符个数*/ }type; type e,t,g,g1,s,s1,f,f1;/*结构体变量*/

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

习题与答案-5-语法分析-自上而下

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.对文法G[S] G: S →a | ∧| (T) T →T , S | S (1) 给出(a,(a,a))和(((a,a), ∧,(a)),a)的最左推导。 (2) 对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。 (3) 经改写后的文法是否是LL(1)的?给出它的预测分析表。 (4) 给出输入串(a,a)#的分析过程,并说明该串是否为G的句子。 1. [解答] (1)①S ②S (T )( T ) T , S T , S ②S=>(T) =>(T,S) =>(S,S) S ( T ) S a =>((T),S) =>((T,S),S) a T , S ( T ) =>((T,S,S),S) =>((S,S,S),S) S a T , S =>(((T),S,S),S) =>(((T,S),S,S),S) a T , S ( T ) =>(((S,S),S,S),S) =>(((a,S),S,S),S) ①S=>(T) =>(T,S) S ^ S =>(((a,a),S,S),S) =>(S,S) =>(a,S) =>(((a,a),^,S),S) =>(a,(T)) ( T ) a =>(((a,a),^,(T)),S) =>(a,(T,S)) =>(((a,a),^,(S)),S) =>(a,(S,S)) T , S =>(((a,a),^,(a)),S) =>(a,(a,S)) =>(((a,a),^,(a)),a) =>(a,(a,a)) S a a (2) 消除左递归 G': S→a | ∧| (T) T→ST' T'→,ST' |ε 递归子程序: program parser proceduce T; begin begin getsym; if sym in [a,^,() then S begin end; S;

语法分析器实验报告

语法分析器的设计实验报告 一、实验容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

实验二自顶向下语法分析--递归下降法

实验二递归下降法判断算术表达式的正确性 学时数:2-4 一、实验目的和要求 1、用递归下降技术实现语法分析器; 2、理解自顶向下语法分析方法; 3、熟练掌握预测分析程序的构造方法。 二、实验内容 算术表达式的文法是G[E]: E→E+T| T T→T*F| F F→(E)| i 用递归下降分析法按文法G[E]对算术表达式(包括+、*、()的算术表达式)进行语法分析,判断该表达式是否正确。 三、实验步骤 1、准备:阅读课本有关章节,将上述算术表达式的文法改造成LL(1)文法(即消除左递 归和提取左公因子);按P87例4.12编写程序。 2、上机调试,发现错误,分析错误,再修改完善。 四、测试要求 1、为降低难度,表达式中不含变量(只含单个无符号整数或i); 2、如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 3、测试用的表达式建议事先放在文本文件中,一行存放一个表达式,以分号结束。而 语法分析程序的输出结果写在另一个文本文件中; 4、选作:对学有余力的同学,可增加功能:当判断一个表达式正确时,输出计算结果。 5、程序输入/输出示例: 如参考C语言的运算符。输入如下表达式(以分号为结束)和输出结果: (a)1; 或 i; 输出:正确 (b)1+2; 或 i+i; 输出:正确 (c)(1+2)*3+4-(5+6*7); 或 (i+i)*i+i-(i+i*i); 输出:正确 (d)((1+2)*3+4 或 ((i+i)*i+i; 输出:错误,缺少右括号 (e)1+2+3+(*4/5) 或 i+i+i+(*4/5); 输出:错误

五、实验报告要求 1、写出修改后LL(1)文法 2、通过对核心代码做注释或通过程序流程图的方式说明递归下降分析程序的实现思想。 3、写出调试程序出现的问题及解决的方法。 4、给出测试的结果。 六、思考(选作) 文法G[E]所构造算术表达式只包含+和*。请修改文法和程序,使得该语法程序可判断包含减号和除号的算术表达式的正确性。 [实验指导] 将文法G[E]改造为LL(1)文法如下: G’[E]: E → TE’ E’→ +TE’| ε T → FT’ T’→ *FT’|ε F → (E)| i [补充说明] 预测分析法分析程序可以从网上下载,但要求: (1)理解该程序,在实验报告中说明该程序所使用的文法及修改后的文法; (2)实验报告要求同上

相关文档
最新文档