语法分析自上而下分析
编译原理张晶版 第四章 自上而下语法分析
1、消除左递归
•1) 什么是左递归 —左递归:文法存在产生式 P + Pa —直接左递归: P —间接左递归:P Pa Aa ,A + Pb
•2)消除左递归
—消除直接左递归 —消除间接左递归
第四章 自上而下语法分析(23)
第二节 自上而下分析法的一般问题 三、不带回溯的自上而下分析算法
2、消除直接左递归
第四章 自上而下语法分析(44)
第三节 预测分析程序与LL(1)文法 二、求串a的终结首符集和非终结符A的随符集
例:对如下文法G(已加上编号)
1. E
4. T 7. F
TE’
FT’ i
2. E’
5. T’ 8. F
+TE’
*FT’ (E)
3.E’
6.T’
e
e
求各非终结符号的终结首符集和随符集
第四章 自上而下语法分析(45)
第四章 自上而下语法分析(47)
第三节 预测分析程序与LL(1)文法 二、求串a的终结首符集和非终结符A的随符集
例:对如下文法G(已加上编号)
1. E
4. T 7. F
TE’
FT’ i
2. E’
5. T’ 8. F
+TBiblioteka ’*FT’ (E)3.E’
6.T’
e
e
求各非终结符号的终结首符集和随符集
第四章 自上而下语法分析(48)
第四章 自上而下语法分析(40)
第三节 预测分析程序与LL(1)文法 三、构造预测分析表
1. 基本思想 1)若A a是一个产生式,a ∈ First(a),那么当A 是栈顶符号且将读入a时,选择a取代A匹配成功的 希望最大,故,M[A,a]元素为A a 2)若A a而a=e,或a + e;当A是栈顶符号且将读 入a时,若a ∈ Follow(A),则栈顶的A应被e匹配; 此时读头不前进,让A的随符与读头下的符号进行 匹配,这样输入串匹配成功的可能最大,故M[A,a] 元素为A a(这里a=e或a + e)
04 语法分析-自上而下分析
待分析的输入串: 待分析的输入串:i+i
只有当a 只有当a是允许出 现在非终结符A 现在非终结符A后 面的终结符时, 面的终结符时, 才可能允许A 才可能允许A自动 匹配。 匹配。
尾随集的定义: VN尾随集的定义:
=*>…Aa Aa…, FOLLOW(A)={a|S =*> Aa , a∈VT}; 特别地,如果S=*> S=*>…A 那么# FOLLOW(A)。 特别地,如果S=*> A,那么# ∈FOLLOW(A)。
例子
文法: S→xAy A→**|* 文法: 输入串:x*y 输入串: S => => => => xAy x**y xAy x*y (S→ xAy) (A→**) 回溯) (回溯) (A→*)
带回溯自上而下分析面临的问题
问题: 问题: 文法的左递归问题 回溯问题 虚假匹配问题 出错位置不确定 低效
实现思想: 实现思想:
分析程序由一组递归过程组成。 分析程序由一组递归过程组成。每一过程 对应于一个非终结符号。 对应于一个非终结符号。 每一个过程的功能是:选择正确的右部。 每一个过程的功能是:选择正确的右部。 在右部中有非终结符号时, 在右部中有非终结符号时,调用该非终结 符号对应的过程。 符号对应的过程。
消除文法的左递归
文法不含回路(形如P=+> P推导 推导) 文法不含回路(形如P=+> P推导) 不含回路 前提: 前提: 不含以ε 也不含以ε 为右部的产生式 结论: 那么可以通过执行消除文法左递 结论: 那么可以通过执行消除文法左递 归的算法消除文法的一切左递归 归的算法消除文法的一切左递归 改写后的文法可能含有以ε (改写后的文法可能含有以ε 为右部的产生式)。 为右部的产生式)。
第04章-语法分析自上而下分析
输入符号串是否为一个句子。 ▪ 语法分析器在编译器中的地位:
源程序
单词符号
词法分析器
取下一个单 词符号
语法分析器
语法分析树
编译器的 后继部分
2021/4/6
符号表
3
4.1 语法分析器的功能
▪ 语法分析方法
➢ 自上而下分析法
从文法的开始符号出发,反复使用文法的产生式, 寻找与输入符号串匹配的推导。
分析输入串x*y(记为)。
xx**yy
SS
IPIPIP xx A y * **
2021/4/6
7
4.2 自上而下分析面临的问题
▪ 当某个非终结符有多个产生式候选时,可 能带来如下问题:
➢ 1.分析过程中,当一个非终结符用某一个候选 匹配成功时,这种匹配可能是暂时的。这时, 不得不“回溯”。
➢ 2.文法左递归问题。一个文法是含有左递归的 ,如果存在非终结符P
➢ 最后所得的无左递归文法是: S→Qc | c Q→Rb | b R→bcaR | caR |a R R→ bca R |
➢ 不同排序所得的文法的等价性是显然的。
2021/4/6
17
4.3.2 消除回溯、提左因子
▪ 为了消除回溯就必须保证:对文法的任何 非终结符,当要它去匹配输入串时,能够 根据它所面临的输入符号准确地指派它的 一个候选去执行任务,并且此候选的工作 结果应是确信无疑的。
2021/4/6
14
4.3.1 左递归的消除
▪ 例4.3 考虑文法G(S)
S→Qc|c Q→Rb|b R→Sa|a
➢ 令它的非终结符的排序为R、Q、S。 ➢ 对于R,不存在直接左递归。 ➢ 把R代入到Q的有关候选后,把Q的规则变为
理学自上而下的语法分析
b∈follow(A),把A→α加至M[A][b]。 ⑤把所有未定义的M[A][c]标上“出错标志”
(c∈VT)。
4.7 预测分析法
㈢预测分析控制程序实现 ①数据结构 M:二维数组,存放预测分析表。 stack:符号栈,初始时为“#S”(S为开
中ε∈afi∈rsVt(XT ,)。则 a∈first(X) ; 若 X→ε , 则 ③观察每个产生式,若有X→Y……,其
中为fYir∈st(VYN),/ε)则加将到fifrisrts(tY(X)中)中的。非ε元素(记
4.5 first集和follow集
考虑更一般情况, Y2、…Yi-1∈VN。
始符号)。 X:表示栈顶符号 t.code:当前处理单词种别
4.7 预测分析法
②算法描述 预测分析控制程序任何时刻的动作,都
按照栈顶符号X和当前输入符号t.code行 事,控制程序每次执行下述三种可能的 动作之一(暂不考虑出错情况)。 l 若X 和 t.code 均为 '#',则分析成功, 输入串为合法句子,终止分析过程。
4.1 带回溯的自上而下分析法概 述
从文法的开始符号出发进行推导,最终 推出确定的输入串(由单词种别构成的 源程序)。
4.1 带回溯的自上而下分析法概 述
从根结点出发,试图用一切可能的办法, 自上而下地为输入串建立一棵语法树。 或者说,为输入串寻找一个最左推导。
4.1 带回溯的自上而下分析法概 述
A→α1|α2|…|αn|ε 设当前输入符号为a,根据下述原则
if (a∈first(αi))
用A→αi推导(1≤i≤n)
else if (a∈follow(A))
自上而下分析
实验二语法分析(自上而下分析)一、实习目的熟悉并设计一个表达式的语法分析器二、实验内容1.设计表达式的语法分析器算法2.编写代码并上机调试运行通过要求:输入表达式输出——表达式语法是否正确三、实验要求运用算术表达式的LL(1)分析算法来设计的表达式的语法分析器。
LL(1)文法是一个自上而下的语法分析方法,它是从文法的识别符号出发,生成句子的最左推导,从左到右扫描源程序,每次向前查看一个字符,便能确定当前应该选择的产生式。
LL(1)分析需要用一个分析表和一个符号栈。
分析表是一个矩阵,它的元素可以存放一个非终结符的产生式,表明当符号栈的栈顶元素非终结符遇到当前输入字符时,所应选择的产生式;分析表的元素还可以是存放一个出错标志,说明符号栈S 的栈顶元素非终结符不应该遇到当前输入符(终结符)。
重复调用LL(1)分析方法对每一个输入字符进行分析,直到输入栈为空为止。
四、运行结果注:此程序只能对由‘i’,’+’,’*’,’<’,’>’构成的以‘#’结速的字符串进行分析。
五、源程序(此程序只能在VC++中运行)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>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;/*结构体变量*/type C[10][10];/*预测分析表*/void print()/*输出分析栈*/{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/ printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/ e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n"); do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受*/getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/ {print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/。
第四章 语法分析——自上而下分析
解二: 规定顺序:S、Q、R
则等价的无左递归的文法: SQc | c QRb| b RbcaR’ | caR’ | aR’ R’bcaR’ |
RSa | a RQca | ca | a
RRbca|bca | ca | a
RbcaR’|caR’ | aR’ R’ bcaR’|
(因为不需要试探某个候选式,而是准确地指派 某个候选式)
17
终结首符集FIRST
令文法G不含左递归,对它的所有非终结符的每 个候选式定义终结首符集 FIRST(): * FIRST()={a | a , a∈VT }
特别地 * 若 ,则规定 ∈ FIRST()
显然, FIRST()是从推导出的所有可能的开头终 结符a或 。
3
§4.2 自上而下分析面临的问题
一、带‚回溯‛的自上而下分析方法:
自上而下分析方法,就是对任何输入串,试 图用一切可能的方法,从文法的开始符号出发, 自上而下地为输入串建立一个语法树(或最左推 导)。 这种分析过程实质上是一种试探过程,即反 复使用不同的产生式以求能匹配输入串。
4
例4.1 设有文法: SxAy
解: S iCtSA | a
A | eS
C b
22
4.3.3 LL(1)分析条件 当一个文法不含左递归,并且满足每个非终结 符的所有候选首符集两两不相交,是不是一定能进 行有效的自上而下的语法分析呢?
若存在 ∈ FIRST() ,则问题较复杂,需要进 一步考虑。 定义:非终结符A的 FOLLOW 集:
* FOLLOW(A)= { a| S …Aa… ,a∈VT } 特别地, * 若S …A,则规定,构造FIRST(X)
a) 若X∈VT,则 FIRST(X)={X}。
第五章自上而下语法分析
第五章⾃上⽽下语法分析第五章⾃上⽽下语法分析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分析⼀、带回溯的⾃顶向下分析⽅法是⾃顶向下分析的⼀般⽅法,即对任⼀输⼊符号串,试图⽤⼀切可能的办法,从树根结点(识别符号)出发,根据⽂法⾃上⽽下地为输⼊串建⽴⼀棵语法树,或者说,从识别符号开始,根据⽂法为输⼊串建⽴⼀个推导序列,这种分析过程本质上是⼀种试探过程,是反复使⽤不同规则谋求匹配输⼊串的过程。
语法分析—自上而下分析
9
§4.2 自上而下面临的问题
例:文法 SxAy A**|*
输入串α :x*y
S x Ay
S x Ay **
S x Ay
*
10
注:
• 回溯法也称试探法,它的基本思想是:从问题的 某一种状态(初始状态)出发,搜索从这种状态 出发所能达到的所有“状态”,当一条路走到“ 尽头”的时候(不能再前进),再后退一步或若 干步,从另一种可能“状态”出发,继续搜索, 直到所有的“路径”(状态)都试探过。这种不 断“前进”、不断“回溯”寻找解的方法,就称 作“回溯法”。
三、分析条件
1.当一个文法不含左递归,并且满足每个非终结符的 所有候选首符集两两不相交的条件,是不是就一定能 进行有效的自上而下分析了呢?
28
§4.3 LL(1)分析法
例:文法
EE+T|T TT*F|F F(E)|i
E T E’
经消去直接左递归后变成 ETE’ E’+TE’|ℇ TFT’ T’*FT’|ℇ F(E) |i
FIRST(A)
2.A→ε
3.A→X1 X2......XK
*
(1) * a..X2....... FIRST(X1)/{ε}
(2) * ε X2.......
FIRST(X2)/{ε}
ε
(3) * εε......ε
36
FIRST集
1.First(X)集合构造,X∈VT∪VN
例:求下题的FIRST集
25
§4.3 LL(1)分析法
3.提取公共左因子 A.事实上,许多文法均存在这样的非终结符,
其所有候选的终结首符集并非两两不相交。
编译原理-自上而下的语法分析
高效性
由于从文法的最顶端开始分析, 一旦发现不匹配,就可以立即终 止当前分支的搜索,避免不必要 的计算,提高了编译器的效率。
易于处理左递归文
法
自上而下的分析方法可以很方便 地处理含有左递归的文法,而左 递归是许多实际编程语言的重要 特征。
局限性
无法处理左边界问题
自上而下的分析方法在处理某些含有左边界的文法时可能 会遇到问题,因为这种方法会优先匹配最左边的符号,而 左边界问题需要从右往左匹配符号。
案例三
在编译器优化中,自上而下的语法分析被用 于识别和修改源代码中的冗余和低效的语法 成分。例如,在C编译器的实现中,自上而 下的语法分析可以用于优化循环结构,减少 不必要的循环次数,提高程序的执行效率。
自上而下的语法分析还可以用于代码生成和 代码生成器的实现。通过识别和解析源代码 中的语法成分,可以生成更高效、更安全的 机器代码或字节码,提高程序的执行效率和
安全性。
THANKS
感谢观看
详细描述:递归下降分析算法易于理解,每个产生式规 则对应一个函数,函数的实现相对简单明了。
详细描述:对于每个产生式规则,需要编写相应的递归 函数,可能会导致代码冗余。
移入-规约分析算法
总结词
基于栈的算法
详细描述
移入-规约分析算法是一种自上而下的语法分 析算法,它将目标语句从左到右依次读入, 并根据文法的产生式规则进行移入或规约操 作,直到找到目标语句的语法结构。
词法分析
词法分析是编译过程的第一步,也称为扫描或词法扫描。它的任务是从左 到右读取源代码,将其分解成一个个的记号或符号。
词法分析器通常使用正则表达式或有限自动机来识别和生成记号,这些记 号可以是关键字、标识符、运算符、标点符号等。
语法分析自下而上分析
LASTVT(P),就能够构造文法G的优先 表。构造优先表的算法是:
.
FOR 每条产生式P→X1X2…Xn DO FOR i:=1 TO n-1 DO
BEGIN
IF Xi和Xi+1均为终结符 THEN 置Xi Xi+1
.
文法G(E) (1) E→E+T | T (2) T→T*F | F (3) F→P F | P (4) P→(E) | i
的优先函数如下表
+ *↑( ) i # F2440660 G1 3 5 5 0 5 0
.
有许多优先关系表不存在优先函数,如:
ab a b
不存在对应的优先函数f和g 假定存在f和g,则有
TN
LA ( P ) S { a |P T a , 或 V P T a ,a Q V T 而 Q V N }
.
有了这两个集合之后,就可以通过检查每
所有终结符对。
➢假定有个产生式的一个候选形为 …aP…
那么,对任何bFIRSTVT(P),有 a b。 ➢假定有个产生式的一个候选形为
…Pb… 那么,对任何aLASTVT(P),有 a b。
栈STACK,把所有初值为真的数组元素F[P, a]的符号对(P,a)全都放在STACK之中。
.
运算:
如果栈STACK不空,就将顶项逐出,记此 项为(Q,a)。对于每个形如 P→Q… 的产生式,若F[P,a]为假,则变其值为真 且将(P,a)推进STACK栈。
上述过程必须一直重复,直至栈STACK拆 空为止。
17
ELSE ERROR /*调用出错诊察程序*/
语法分析最常用的两类方法
LL分析法和LR分析法。
1、自上而下语法分析方法(LL分析法)
给定文法G和源程序串r。
从G的开始符号S出发,通过反复使用产生式对句型中的非终结符进行替换(推导),逐步推导出r 。
是一种产生的方法,面向目标的方法。
分析的主旨为选择产生式的合适的侯选式进行推导,逐步使推导结果与r匹配。
2、自下而上语法分析方法(LR分析法)
从给定的输入串r开始,不断寻找子串与文法G中某个产生式P的候选式进行匹配,并用P的左部代替(归约)之,逐步归约到开始符号S。
是一种辨认的方法,基于目标的方法。
分析的主旨为寻找合适的子串与P的侯选式进行匹配,直到归约到G的S为止。
扩展资料
LALR分析器可以对上下无关文法进行语法分析。
LALR即“Look-AheadLR”。
其中,Look-Ahead为“向前看”,L代表对输入进行从左到右的检查,R代表反向构造出最右推导序列。
LALR分析器可以根据一种程序设计语言的正式语法的产生式而对一段文本程序输入进行语法分析,从而在语法层面上判断输入程序是否合法。
实际应用中的LALR分析器并不是由人手工写成的,而是由类似于yacc和GNU Bison之类的LALR语法分析器生成工具构成。
由机器自动生成的代码相比较于程序员手工的代码,拥有更好的运行效率而且减少了程序员的工作量。
编译原理实验三-自下而上语法分析报告及语义分析报告.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五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string> using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str); string concat(string str); 【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8]; public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++) tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][6]="R3"; tableData[2][7]="R3"; tableData[3][1]="R6"; tableData[3][2]="R6"; tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6";tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4";tableData[13][5]="S4";tableData[14][1]="R2";tableData[14][2]="R2";tableData[14][3]="S7";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码stringcodestring[10]={"main","int","if","then","else","return","void","cout","endlint codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";} else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";} else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";} else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";} else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";} else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";} else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";} else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";} else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";} else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";} else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";} else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";} else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";} else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";} else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";} else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
my第04章-语法分析:自上而下
自上而下分析法的一般问题
3.
带回溯的自上而下分析法的缺陷 1)如果文法存在左递归,语法分析会无限循环下去。 2)若产生式存在多个候选式,选择哪个进行推导完全 是盲目的。 3)回溯会引起时间和空间的打量消耗 4)如果被识别的语句是错的,算法无法指出错误的确 切位置。
第四章 语法分析--自上而下分析
直接左递归,和非直接左递归的消除方法均在必须掌握之列。这里我们 切不可被形式描述消除左递归的算法吓倒,多做几个例题后再来理解是很 有好处的: [例4.3]: 考虑文法:SQc|c Q Rb|b R Sa|a 消除左递归。 解:将终结符排序为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 Sab|ab|b R Sa|a 由于关于Q,R的规则式多余的则可化简
本节要 掌握对给定文法构造出每个非终结符的 FIRST和FOLLOW集合。
第四章 语法分析--自上而下分析
掌握LL(1)预测分析表的构造,请参看4。5。1 预测分析程序的 工作过程(P76)和 4。5。2预测分析表的构造(P78)。 现在举一些例子帮助同学们理解: [例4.7 ]对于文法 ETE’ E’ +TE’| T FT’ T’ *FT’| F (E)| i 我们构造每个非终结符的FIRST和FOLLOW集合 解:FIRST(E) = { (, i } FOLLOW(E) ={ ), # } FIRST(E’) = {+, } FOLLOW(E’) = { ), #} FIRST(T) = {(, i } FOLLOW(T) = {+, ), # } FIRST(T’) = {*, } FOLLOW(T’) ={+ , ), # } FIRST(F) = {(, i } FOLLOW(F) ={*, +, ) , # } 在这里我们要注意FOLLOW(F)的求解过程其中: FOLLOW(F)=FIRST(T’)={*}; 因为T’ ,所以将FOLLOE(T)加 到FOLLOW(F)中 (由于TFT’), 则: FOLLOW(F)=FOLLOW(T)=FIRST(E‘)={+}
自上而下语法分析
从语法树的角度看,从根节点出发,反复使用 所有可能的产生式,谋求输入串的匹配,试图 向下构造一棵语法树,其末端节点正好与输入 符号串相同。
需要反复试探。
复习
句型的推导
最左(最右)推导:在推导的任何一步α β , 其中α 、β 是句型,都是对α 中的最左(右)非 终结符进行替换 最右推导被称为规范推导。 由规范推导所得的句型称为规范句型。
例1:判定输入串(i+i)*i是否是下述文法的句子?
G = ({E}, {i, +, *, (, ) } , P , E) P: E E + E E E*E E (E) Ei
解:使用最左推导:
E E*E (E)*E (E + E)*E (i + E)*E
(i + i)*E (i + i)*i
高级语言的语法结构适合用上下文无关文法 来描述,上下文无关文法是语法分析的基础。
语法分析在编译系统中所处的位置
语法分析的接口设计
源程序 词法分析器 token串
语法分析器 语法分析树
编译程序 后续部分
• 语法分析器的输入
– Token序列:词法分析的输出,是各个单词都正 确的源程序的变换形式,是一个有限序列
• 语法分析器的输出
– 分析树:表示方法? 见教材 P89 – 错误处理信息:定位、继续编译
语法分析器的功能
按照语言的语法构成规则, 识别输入的符号 串能否构成一个句子。这些规则是用文法的 产生式来定义的。
问题
对给定的一个输入串,如何判定它是不是一 个句子?
方法
编译原理第四章语法分析-自上而下分析
• 例 4.4
4.4 递归下降分析程序构造
• 递归下降分析器:
这个分析程序由一组递归过程组成的,每个过程对应 文法的一个非终结符。 E→TE’ E’→+TE’| T→FT’ T’→*FT’| F→(E)|i
PROCEDURE E BEGIN T ; E’ END PROCEDURE E’ IF SYM=‘+’THEN BEGIN ADVANCE ; T ; E’ END
4.2 自上而下分析面临的问题
• 例4.1 假定有文法
(1) SxAy (2)A**|*
对输入串x*y,构造语法树。 • 构造过程:
(1)把S作为根 (2)用S的产生式构造子树 (3)让输入串指示器IP指向输入串的第一个符号。
S x A y x
S
A y x
S
A y
*
*
*
(4)调整输入串指示器IP与叶结点进行匹配。 (5)如果为非终结符,用A的下一个产生式构建子树。 (6)如果匹配成功则结束;否则,回溯到步骤(4)。
• 一个反例:
– 文法:SQc|c;QRb|b;RSa|a虽然不是直接 左递归,但S、Q、R都是左递归。
• 消除左递归算法:
– 算法的思想是:
• • • • 首先构造直接左递归; 再利用一般转换规则,消除直接左递归 化简文法。 下面算法在不含PP,也不含在右部产生式时可以消除 左递归。
• 消除一个文法的左递归算法:
(1) 把文法 G 的所有非终结符按任一种顺利排列成 P1…Pn;按此顺序执行; (2) FOR i:=1 TO n DO
BEGIN FOR j:=1 TO i-1 DO 把形如Pj+1→Pj 的规则改写成 Pj+11|1|…k| 。其中 Pj1|1|…k 是关于 Pj 的 所有规则; 消除关于Pi规则的直接左递归性。 END 化简由(2)所得的文法。即去除那些从开始符号出发永 远无法到达的非终结符的产生规则。
语法分析--自上而下分析的基本问题
语法分析--⾃上⽽下分析的基本问题语法分析基本概念语法分析的前提:对语⾔的语法结构进⾏描述,采⽤正规式和有限⾃动机描述和识别语⾔的单词符号,⽤上下⽂⽆关⽂法来描述语法规则语法分析的任务:分析⼀个⽂法的句⼦的结构语法分析器的功能:按照⽂法的产⽣式(语⾔的语法规则),识别输⼊符号串是否为⼀个句⼦(合式程序)⾃下⽽上(Bottom-up):从输⼊串开始,逐步进⾏归约,直到⽂法的开始符号,归约:根据⽂法的产⽣式规则,把串中出现的产⽣式的右部替换成左部符号,从树叶节点开始,构造语法树,算符优先分析法、LR分析法⾃上⽽下(Top-down):从⽂法的开始符号出发,反复使⽤各种产⽣式,寻找"匹配"的推导,推导:根据⽂法的产⽣式规则,把串中出现的产⽣式的左部符号替换成右部,从树的根开始,构造语法树,递归下降分析法、预测分析程序⾃上⽽下分析⾯临的问题基本思想:从⽂法的开始符号出发,向下推导,推出句⼦,针对输⼊串,试图⽤⼀切可能的办法,从⽂法开始符号(根结点)出发,⾃上⽽下地为输⼊串建⽴⼀棵语法树多个产⽣式候选带来的问题,回溯问题:分析过程中,当⼀个⾮终结符⽤某⼀个候选匹配成功时,这种匹配可能是暂时的,出错时,不得不“回溯”⽂法左递归问题:⼀个⽂法是含有左递归的,如果存在⾮终结符P⾯临的问题⽂法左递归问题回溯问题构造不带回溯的⾃上⽽下分析算法消除⽂法的左递归性消除回溯消除⽂法的左递归直接左递归的消除间接左递归的消除消除左递归的算法由于对⾮终结符排序的不同,最后所得的⽂法在形式上可能不⼀样。
但不难证明,它们都是等价的消除回溯为了消除回溯必须保证:对⽂法的任何⾮终结符,当要它去匹配输⼊串时,能够根据它所⾯临的输⼊符号准确地指派它的⼀个候选去执⾏任务,并且此候选的⼯作结果应是确信⽆疑的FIRST和FOLLOW集合的构造FIRST集合令G是⼀个不含左递归的⽂法,对G的所有⾮终结符的每个候选α定义它的终结⾸符集FIRST(α)为:提取公共左因⼦FOLLOW集合L: 从左到右扫描输⼊串 L: 最左推导 1:每⼀步只需向前查看⼀个符号FIRST和FOLLOW集合的构造构造每个⽂法符号的FIRST集合构造FOLLOW(A)构造每个⾮终结符的FOLLOW集合对最后的FIRST、FOLLOW集合有点迷,真的有点迷,晚上不该看这个的!!o(╥﹏╥)o。
实验三自上而下语法分析--预测分析
实验三预测分析法判断算术表达式的正确性学时数:6一、实验目的1、理解语法分析器的构造方法和工作原理;2、理解自上而下语法分析方法;3、熟练掌握预测分析程序的构造方法。
二、实验内容算术表达式的文法是G[E]:E→E+T| TT→T*F| FF→(E)| id用预测分析法按文法G[E]对算术表达式(包括+、*、()的算术表达式)进行语法分析,判断该表达式是否正确。
三、实验步骤1、准备:阅读课本有关章节,将上述算术表达式的文法改造成LL(1)文法;设计出预测分析表;按算法3.1(P56)编写程序。
2、上机调试,发现错误,分析错误,再修改完善。
四、测试要求1、为降低难度,表达式中不含变量(只含单个无符号整数或i);2、如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3、测试用的表达式建议事先放在文本文件中,一行存放一个表达式,同时以分号结束。
同时将语法分析程序的输出结果写在另一个文本文件中;4、对学有余力的同学,可增加功能:当判断一个表达式正确时,输出计算结果。
5、程序输入/输出示例:如参考C语言的运算符。
输入如下表达式(以分号为结束)和输出结果:(a)1;输出:正确(b)1+2;输出:正确(c)(1+2)/3+4-(5+6/7);输出:正确(d)((1-2)/3+4输出:错误,缺少右括号(e)1+2-3+(*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)实验报告要求同上。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4.2 自上而下分析面临的问题
自上而下就是从文法的开始符号出发,向 下推导,推出句子。
带“回溯”的 不带回溯的递归子程序(递归下降)分析方法。
自上而下分析的主旨:对任何输入串,试 图用一切可能的办法,从文法开始符号(根 结点)出发,自上而下地为输入串建立一棵 语法树。或者说,为输入串寻找一个最左 推导。
(4.3)
虽没有直接左递归,但S、Q、R都是左递归的
SQcRbcSabc
一个文法消除左递归的条件: 不含以为右部的产生式 不含回路。
PP
国防科技大学计算机系602教研室
消除左递归的算法:
1. 把文法G的所有非终结符按任一种顺序排列成P1, P2,…,Pn;按此顺序执行;
2. FOR i:=1 TO n DO
BEGIN FOR j:=1 TO i-1 DO
把形如Pi→Pj的规则改写成 Pi→1|2|…|k ; (其中Pj→1|2|…|k是关于Pj的所有规则) 消除关于Pi规则的直接左递归性
END
3. 化简由2所得的文法。去除那些从开始符号出发永 远无法到达的非终结符的产生规则。
国防科技大学计算机系602教研室
例 文法G(E): E→E+T | T T→T*F | F
F→(E) | i
经消去直接左递归后变成:
E→TE
E→+TE |
T→FT
T→*FT |
(4.2)
F→(E) | i
国防科技大学计算机系602教研室
例如文法G(S): S→Qc|c Q→Rb|b R→Sa|a
国防科技大学计算机系602教研室
定义:称A直接推出,即
A 仅当A 是一个产生式, 且, (VT VN)* 。
如果1 2 n,则我们称这个序 列是从1到n的一个推导。若存在一个从 1到n的推导,则称1可以推导出n 。
例:对文法(1)
E (E) (E+E) (i+E) (i+i)
国防科技大学计算机系602教研室
G(E): E i| E+E | E-E | E*E | E/E | (E)
i*i+i
E*i+i
E*E+i
E+i
E+E
E
E E+ E
E*E i
iHale Waihona Puke i国防科技大学计算机系602教研室
自上而下分析法(Top-down) 基本思想:它从文法的开始符号出发,反复 使用各种产生式,寻找"匹配"的推导。 递归下降分析法:对每一语法变量(非终结 符)构造一个相应的子程序,每个子程序识 别一定的语法单位,通过子程序间的信息反 馈和联合作用实现对输入串的识别。 预测分析程序 优点:直观、简单和宜于手工实现。
国防科技大学计算机系602教研室
通 一常步,或用若干1步,可n 以表推示出:从n。1出发,经过
*
用 1 n 表示:从1出发,经过0步或
若干步,可以推出n。
*
所以 : 即 或
定义:假定G是一个文法,S 是它的开始符号。
如 号果的句S型 是*一个,句则子。称文是法一G个所句产型生。的仅句含子终的结全符体
VT:终结符集合(非空) VN:非终结符集合(非空),且VT VN= S:文法的开始符号,SVN P:产生式集合(有限),每个产生式形式为
P, PVN, (VT VN)* 开始符S至少必须在某个产生式的左部出现一次。
国防科技大学计算机系602教研室
例,定义只含+,*的算术表达式的文法 G=<{i,+,*,(,)},{E},E, P>, 其 中,P由下列产生式组成: Ei E E+E E E*E E (E)
2. 文法左递归问题。一个文法是含有左递归的 ,如果存在非终结符P
P P
含有左递归的文法将使自上而下的分 析陷入无限循环。
国防科技大学计算机系602教研室
4.3 LL(1)分析法
构造不带回溯的自上而下分析算法
要消除文法的左递归性 克服回溯
国防科技大学计算机系602教研室
4.3.1 左递归的消除
第四章 语法分析—自上而下分析
本章主要介绍语法分析的处理 要进行语法分析,必须对语言的语法结构
进行描述。
采用正规式和有限自动机可以描述和识别语言 的单词符号;
用上下文无关文法来描述语法规则。
国防科技大学计算机系602教研室
上下文无关文法的定义: 一个上下文无关文法G是一个四元式
G=(VT,VN,S,P),其中
国防科技大学计算机系602教研室
例3.4.1 假定有文法G(S): (1) S→xAy (2) A→**|*
分析输入串x*y(记为)。
xx**yy
SS
IPIPIP xx A y
* **
国防科技大学计算机系602教研室
当某个非终结符有多个产生式候选时,可 能带来如下问题:
1. 分析过程中,当一个非终结符用某一个候选 匹配成功时,这种匹配可能是暂时的。出错时 ,不得不“回溯”。
是一个语言,将它记为 L(G)。
L(G ) { | S , 国防科技大学计算机系602教研室 VT*}
4.1 语法分析器的功能
语法分析的任务是分析一个文法的句子 结构。
语法分析器的功能:按照文法的产生式 (语言的语法规则),识别输入符号串是 否为一个句子(合式程序)。
国防科技大学计算机系602教研室
单词符号
语法分
源程序 词法分
语法分 析树 编译程序
析器 取下一单词 析器
后续部分
... 符号表
国防科技大学计算机系602教研室
语法分析的方法:
自下而上分析法(Bottom-up) 基本思想:从输入串开始,逐步进行“归约”, 直到文法的开始符号。即从树末端开始,构造语 法树。所谓归约,是指根据文法的产生式规则, 把产生式的右部替换成左部符号。 算符优先分析法:按照算符的优先关系和结合 性质进行语法分析。适合分析表达式。
直接消除见诸于产生式中的左递归:假 定关于非终结符P的规则为
P→P | 其中不以P开头。
我们可以把P的规则等价地改写为如下的 非直接左递归形式:
P→P P→P|
国防科技大学计算机系602教研室
一般而言,假定P关于的全部产生式是 P→P1 | P2 | … | Pm | 1 | 2|…|n
其中,每个都不等于,每个都不以P开头 那么,消除P的直接左递归性就是把这些规 则改写成: P→1P | 2P | … | nP P→1P | 2P |… | mP |