编译原理 算符优先分析法 ppt课件

合集下载

算符优先分析编译原理演示文稿

算符优先分析编译原理演示文稿
算符优先分析编译原理演示文 稿
(优选)算符优先分析编译原 理
6.3 算符优先分析法
算符优先文法的定义 算符优先关系表的构造 算符优先分析算法 算符优先分析法的局限性
6.3.1 算符优先分析
• 自下而上分析算法模型----移进归约 • 算符优先分析不是规范归约
算符优先分析的可归约 串是句型的最左素短语 定义: cfg(上下文无关文法) G 的句型的素短
2)’<‘关系
– 求出每个非终结符B的FIRSTVT(B)
– 若A→…aB…,则b∈FIRSTVT(B),则a<b
3)’>’关系
– 求出每个非终结符B的LASTVT(B)
– 若A→…Bb…,则a∈LASTVT(B),则a>b
计算算符优先关系
例文法G’[E’]: (0) E’→#E# (1) E→E+T (2) E→T (3) T→T*F (4) T→F (5) F→PF|P (6) P→(E) (7) P→i
例 G’[E]:
算符优先关表
E→E+T|T
T→T*F|F F→P↑F|P
P→(E)|i
+ * ( ) i#
+>< << >< >
*> > < < > < >
> > < < > < >
( < < < <=<
)>>>
>
>
i >>>
>
>
#< < < <
<=

第四章_2 算符优先分析法

第四章_2 算符优先分析法

1 自下而上语法分析概述
• 移进-归约过程实例。 例4.11 设有文法G[A]: (1)A → aBcDe (2)B → b (3)B → Bb (4)D → d 对输入串abbcde$的移进-归约分析过程
对输入串abbcde$移进-归约分析过程: 步骤 0 1 2 3 4 5 6 7 8 9 10 符号栈 $ $a $ab $aB $aBb $aB $aBc $aBcd $aBcD $aBcDe $A 输入串 abbcde$ bbcde$ bcde$ bcde$ cde$ cde$ de$ e$ e$ $ $ 动作
动作
移进 归约 移进 移进 归约 归约 接受
4.4.6 算符优先分析法的局限性
• 1 一般语言的文法很难满足算符优先文法的条 件,仅在表达式局部中应用; • 2 由于忽略非终结符在归约过程中的作用,可 能导致对错误的句子得到正确的归约。
例4.13 设有算符优先文法 A → A;D|D D → D(E)|F F → a|(A) E → E+A|A 写出输入串(a+a)$的算符优先分析过程。 $ 该文法的算符优先关系表为:
结论:算符优先文法是无二义的。
4.4.3 算符优先关系表的构造
• 1 FIRSTVT集、 LASTVT集 + FIRSTVT(A)={b|A ⇒ b… 或 + A ⇒ Bb… ,b ∈ VT,B ∈ VN} 即:非终结符A往下推导所有可能出现的首个 算符的集合. LASTVT(A)={a|A ⇒ …a + A ⇒ …aB, a ∈ VT,B ∈ VN} 即:非终结符A往下推导所有可能出现的最后 一个算符的集合.
4.4.4 算符优先分析算法的设计
对4.12中的文法G[E]: E → E+T|T T → T*F|F F →(E)|id 写出输入串id+id$的算符优先分析过程。

算符优先分析方法

算符优先分析方法

目录1.课程设计的目的与原理 (1)1.1设计目的 (1)1.2设计原理 (1)2.课程设计环境 (1)3.课程设计内容 (2)3.1算符优先分析流程图 (2)3.2算符优先总流程图 (3)3.3算符优先文法 (4)3.4 程序调试 (5)4.总结 (6)附录 (6)算符优先分析方法1.课程设计目的与原理1.1设计目的1.了解利用算符优先算法进行移进规约分析的方法。

2. 锻炼和提高自己的编程能力。

3. 熟悉编译原理语法分析的方法,加深对算符优先基本方法的了解。

4. 进一步理解编译原理,更好的的学习它的思路,掌握编译原理的理论基础。

5. 了解算符优先分析和规范规约的不同以及优缺点。

1.2设计原理算符优先分析方法是根据算符之间的优先关系而设计的一种自底向上的语法分析方法。

算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。

由于算符优先分析不考虑非终结符之间的优先关系,在归约过程中只要找到可归约串就归约,并不考虑归约到哪个非终结符,因而算符优先归约不是规范归约。

2.课程设计环境1.硬件运行环境:Windows XP2.软件运行环境:VC++ 6.0版本3.课程设计内容3.1算符优先分析流程图流程图说明:k:表示的是符号栈S的使用深度S:用来存放终结符和非终结符的符号栈Vt:存放该文法中的所有终结符3.2算符优先总流程图3.3算符优先文法例已知表达式文法为:E->E+TE->TT->T*FT->FF->(E)F->i⑴计算FIRSTVE和LASTVT集合FirstVT(E)={+,*,(,i} LastVT(E)={+,*,),i} FirstVT(T)={*,(,i} LastVT(T)={*,),i} FirstVT(F)={(,i} LastVT(F)={),i} FirstVT(Q)={#} LastVT(Q)={#}见附录3.4程序调试例:1、输入产生式的个数:2、输入文法:3、判断文法4、生成非终结符的FIRSTVT集和LASTVT集:5、生成算符优先分析表:5、输入字符串进行分析:输出结果与自己做的结果一模一样,说明设计成功。

编译原理之算符优先分析

编译原理之算符优先分析

编译原理之算符优先分析1.算符优先分析:1.1定义是⼀种简单直观、⼴泛使⽤、便于⼿⼯实现的⾃下⽽上的语法分析⽅法。

1.2原理定义算符之间的某种优先关系,寻找“归约串”,并进⾏归约1.3相关知识拓展1.3.1 算符⽂法:产⽣式的右部不包含两个相继的⾮终结符,即不包含形如:.....QR.....1.3.2 算符优先⽂法:任何终结符对(a,b)⾄多⼀种优先级关系。

1.3.3 构造优先关系表步骤:(1)写出FIRSTVT、LASTVTFIRSTVT(P)={a|P->a.....或P->Qa......}LASTVT(P)={a|P->.....a或P->......aQ} (2)列表,根据优先级填表 1.确定同⼀产⽣式的末尾终结符之间⽆优先关系 2.确定=,再使⽤FIRSTVT、LASTVT1.4 算符优先分析算法 素短语:⾄少包含⼀个终结符且不包含更⼩的终结符,如p*p或 i 最左素短语:最左侧的素短语 缺点:跳过了所有单⾮产⽣式所对应的归约步骤。

(单⾮产⽣式:形如:P->Q ,右部只有⼀个⾮终结符的产⽣式)1.5 构造优先函数使⽤构造优先函数代替优先表f:表⼊栈优先函数、g:表⽐较优先函数1.6 举例S→a|Λ|(T) T->T,S|S(1)基本了解:FIRSTVT(P)={a|P->a.... or Qa....}; LASTVT(P)={a|P->...a or P->....aQ}所以对于:S→a|Λ|(T) 则FIRSTVT(S)={a,Λ,(}对于:S→a|Λ|(T) 则LASTVT(S)={a,Λ,)}对于:T->T,S|S 则FIRSTVT(T)={, ,a,Λ,(}对于:T->T,S|S 则LASTVT(T)={, ,a,Λ,)}(2)优先关系aΛ(),a>>Λ>>(<<<=<)>>,<<<>>,<<<>>由于G[S]中任何终结符对(a,b)之多只有⼀种关系成⽴,所以,G[S]为算符优先⽂法。

编译原理实验4 算符优先语法分析

编译原理实验4  算符优先语法分析

归约时找最左素短语
栈底
串头
可归约串
串尾
#…aj-1 aj aj+1 … ai-1 ai ai+1…
优先关系: ⋖


串头与串尾之间为可归约串(素短语), 包括其间的及左右两边的非终结符。
核心问题
• 分析栈的数据结构、出栈操作、入栈操作 • 分析表的存储结构、读取操作
步骤1
• 判断给定的文法是否是OPG文法
步骤3:构造算符优先分析表
优先关系:
设G是一个不含 产生式的算符文法,令 a、b是任意两个VT , P、Q、R ∈ VN ,则:
(1) ab 当且仅当文法G中含有形如P …ab…或P …aQb…的产生式 (2) a<b 当且仅当G中含有形如P …aR…的产生式,R而Rb… 或R Qb… (3) a>b 当且仅当G中含有形如P …Rb…的产生式,R而R…a 或R …aQ
步骤6
• 完成主分析程序
符号栈的初始化
for( 从左到右扫描输入符号串 ) {
i = 获取当前的输入符号 j = 获取栈顶的终结符号 switch(table[i][j]) //比较优先关系 { case 9: // 语法错误 case 0: // 移进 case -1: // 移进 case 1: // 归约 } }
{ k = k+1 ; S[ k ] = a ;
} else error( ); } while ( a != ‘#’ ) ; // end of do
// 判断符号栈是否出现成功标志 or 出错
在正确的情况下,算法工作完毕时符号栈将呈现 #N,输入 符号为# 。
步骤7
• 测试语法分析的结果
分析过程

算符优先分析法

算符优先分析法



a b 表示a的优先级低于b a b 表示a的优先级等于b a b 表示a的优先级大于b 若a,b在任何情况下不可能相继出现,则a,b无关系
表6.2
+ * / id ( ) #
优先关系表
* / id ( ) #
initial
a+b*c#
T1 a + # T2
#<· + +<· *
a #
控制程序
B a #
控制程序
6.2 简单优先分析法

定义

一个文法G,如果它不含ε产生式,也不含任何右部 相同的不同产生式,并且它的任何符号对(X,Y), X,Y∈V或者没有关系,或者存在优先级相同或低于、 高于等关系之一,则这是一个简单优先文法。 X Y 当且仅当G中含有形如P→„XY„ X <·Y 当且仅当G中含有形如P→„XQ„,且Q X · > Y 当且仅当G中含有形如P→„QR„,且 Q „X,R Y„(Y∈FIRST(R)),Y∈VT。
语法分析

推导——自顶向下的语法分析过程

预测分析程序,递归下降分析法(最左推导) 要求文法是LL(1)文法

归约——自底向上的语法分析过程


简单优先分析法,算符优先分析法 LR分析法
自底向上的语法分析过程思想

自底向上语法分析过程是一个最左归约的过程 (规范推导的逆过程,亦称规范归约),从输入 串开始,朝着文法的开始符号进行归约,直到 到达文法的开始符号为止的过程。
例6.1 文法G[S] 产生式如下: ①S→aAcBe ②A→b ③A→Ab ④B→d 输入串 abbcde是不是文法的句子? SaABe aAde aAbcde abbcde

编译原理 实验3 算符优先分析

编译原理 实验3 算符优先分析

编译原理实验3 算符优先分析一、实验目的通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。

二、实验内容1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。

2. 构造算符优先表。

3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。

三、程序思路在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。

文法结束再输入一行G->#E#1. 先做文法判断,即可判断文法情况。

2. 若是算符优先文法,则在优先表栏显示优先表。

3. 写入要分析的句子,按回车即可。

4. 在分析过程栏,可以看到整个归约过程情况四、实验结果FunctorFirst.h#include<afx.h>#include<iostream>#include<fstream>#include<string>using namespace std;#define rightlength 20#define product_num 20 // 产生式最多个数#define num_noterminal 26 // 非终结符最多个数#define num_terminal 26 // 终结符最多个数struct Production{char Left;char Right[rightlength];int num;};struct VT{bool vt[num_noterminal][num_terminal];};struct Stack{char P;char a;};class CMyDlg{public:CMyDlg();void InputRule();CString showLastVT();CString showFirstVT();CString shownoTerminal(char G[]);CString showTerminal(char g[]);CString showLeftS(char S[], int j, int k);void InitAll();CString showSentence(CString sen, int start);CString showStack(char S[], int n);void Initarry(char arry[], int n);CString ProdtoCStr(Production prod);int selectProd(int i, int j, char S[]);void preFunctor(CString sen);void insertFirstVT(Stack S[], int &sp, char P, char a);void insertLastVT(Stack S[], int &sp, char P, char a);void ShowPreTable();void createPreTable();char pretable[num_terminal][num_terminal];bool like_Q(Production prod, char Q);void createLastVT();bool likeQ_(Production prod, char Q);bool likeQa_(Production prod);bool like_aQ(Production prod);bool like_a(Production prod);bool likea_(Production prod);bool Dignose(char c);int findg(char c);int findG(char c);void createFirstVT();void createTerminal();void createnoTerminal();void buildProduction(CString s);bool test(CString s);void parse(); // 语法分析CString gram; // 存放文法;Production production[product_num];VT FirstVT;VT LastVT;int locProduct; // 已有产生式个数char G[num_noterminal];char g[num_terminal];int i_G;int i_g;CString m_sen;};FunctorFirst.cpp#include"FunctorFirst.h"CMyDlg::CMyDlg(){}bool CMyDlg::test(CString s) // 测试是否是算符优先文法{bool t = 1;for (int i = 0;i < s.GetLength() - 1;i++)if (s[i] > 64 && s[i] < 91 && s[i + 1]>64 && s[i + 1] < 91){t = 0;break;}return t;}void CMyDlg::InputRule(){string infile;string line;cout <<" 请输入语法文件的路径:";cin >> infile;cout << endl;ifstream input(infile.c_str());if (!input){cout << endl <<"###打不开文件,请确认输入的路径有效###"<< endl;cout <<"请再次运行本程序"<< endl << endl;exit(0);}while (getline(input, line)){if (test(line.c_str()) == 0){cout << endl <<"这不是算符优先文法!"<< endl;exit(0);}buildProduction(line.c_str());}cout << endl <<"这是算符优先文法!"<< endl;input.close();}void CMyDlg::buildProduction(CString s){int i = 0;int j = 0;int k = 0;for (k = 0;k < s.GetLength();k++) // 得到左部{if (s[k] != ' '){production[locProduct].Left = s[k];break;}}for (i = k + 1;i < s.GetLength();i++){if (s[i - 1] == '-'&&s[i] == '>')break;}int temp = i;for (i = temp + 1;i < s.GetLength();i++){if (s[i] != '|'){if (s[i] != ' '){production[locProduct].Right[j] = s[i];j++;production[locProduct].num = j;}}else{locProduct++;production[locProduct].Left = production[locProduct - 1].Left;j = 0;}}locProduct++;}void CMyDlg::createnoTerminal() // 建立非终结符索引{i_G = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (j = 0;j < i_G;){if (production[i].Left != G[j])j++;elsebreak;}if (j > i_G - 1){G[i_G] = production[i].Left;i_G++;}}}void CMyDlg::createTerminal() // 建立终结符索引{i_g = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (int k = 0;k < production[i].num;k++){char temp = production[i].Right[k];if (Dignose(temp)){for (j = 0;j < i_g;){if (temp != g[j])j++;elsebreak;}if (j > i_g - 1){g[i_g] = temp;i_g++;}}}}}void CMyDlg::createFirstVT() // production已完成,创建FirstVT{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVTfor (j = 0;j < i_g;j++)FirstVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (likea_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[0]);if (likeQa_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[1]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (likeQ_(production[i], Q))insertFirstVT(S, sp, production[i].Left, a);}}}void CMyDlg::createLastVT() // 创建Last集{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVT for (j = 0;j < i_g;j++)LastVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (like_a(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 1]);if (like_aQ(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 2]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (like_Q(production[i], Q))insertLastVT(S, sp, production[i].Left, a);}}}int CMyDlg::findG(char c) // 定位c在G中的下标{int i = 0;for (i = 0;i < i_G;i++)if (c == G[i])break;return i;}int CMyDlg::findg(char c) // 定位c在g中的下标{int i = 0;for (i = 0;i < i_g;i++)if (c == g[i])break;return i;}bool CMyDlg::Dignose(char c) // 判断c 是终结符还是非终结符,终结符true,非终结符 false{if (c > 64 && c < 91)return false;elsereturn true;}bool CMyDlg::likea_(Production prod){if (Dignose(prod.Right[0]))return true;elsereturn false;}bool CMyDlg::like_a(Production prod) // 形如P->…a型产生式{if (Dignose(prod.Right[prod.num - 1]))return true;else}bool CMyDlg::like_aQ(Production prod) // 形如P->…aQ型产生式{if (prod.num < 1)return false;else{if (Dignose(prod.Right[prod.num - 2]) && (!Dignose(prod.Right[prod.num - 1])))return true;elsereturn false;}}bool CMyDlg::likeQa_(Production prod){if (prod.num < 1)return false;else{if (Dignose(prod.Right[1]) && (!Dignose(prod.Right[0])))return true;elsereturn false;}}bool CMyDlg::likeQ_(Production prod, char Q){if (prod.Right[0] == Q)return true;elsereturn false;}bool CMyDlg::like_Q(Production prod, char Q){if (prod.Right[prod.num - 1] == Q)return true;else}void CMyDlg::createPreTable() // 创建优先表{// 初始化优先表pretableint i, j;for (i = 0;i < i_g;i++)for (j = 0;j < i_g;j++)pretable[i][j] = ' '; // 表错误for (j = 0;j < locProduct;j++){for (i = 0;i < production[j].num - 1;i++){char xi, xi1, xi2;xi = production[j].Right[i];xi1 = production[j].Right[i + 1];xi2 = production[j].Right[i + 2];if (Dignose(xi) && Dignose(xi1))pretable[findg(xi)][findg(xi1)] = '=';if (i < production[j].num - 2 && Dignose(xi) && Dignose(xi2) && (!Dignose(xi1)))pretable[findg(xi)][findg(xi2)] = '=';if (Dignose(xi) && (!Dignose(xi1))){int N = findG(xi1);for (int k = 0;k < i_g;k++)if (FirstVT.vt[N][k] == true)pretable[findg(xi)][k] = '<';}if ((!Dignose(xi)) && Dignose(xi1)){int N = findG(xi);for (int k = 0;k < i_g;k++)if (LastVT.vt[N][k] == true)pretable[k][findg(xi1)] = '>';}}}}void CMyDlg::ShowPreTable() // 显示相关集合和优先表{CString str = "";str = str +"终结符"+ showTerminal(g) +"\r\n";str = str +"非终结符"+ shownoTerminal(G) +"\r\n";str = str +"First集合:\r\n"+ showFirstVT();str = str +"Lasst集合:\r\n"+ showLastVT();str = str +" | ";int i, j;for (i = 0;i < i_g;i++)str = str + g[i] +" | ";str = str +"\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";for (i = 0;i < i_g;i++){str = str + g[i] +" | ";for (j = 0;j < i_g;j++)str = str + pretable[i][j] +" | ";str +="\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";}cout << str.GetBuffer(1000);}void CMyDlg::insertFirstVT(Stack S[], int &sp, char P, char a) {if (FirstVT.vt[findG(P)][findg(a)] == false){FirstVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::insertLastVT(Stack S[], int &sp, char P, char a){if (LastVT.vt[findG(P)][findg(a)] == false){LastVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::preFunctor(CString sen) // 算符优先分析过程实现{bool tagbreak = true;char S[100];int k = 0;S[k] = '#';int i = 0; // 表下次读入位置int j = 0;//char a;CString show = "";CString temp = "";temp.Format("%-15s %s %15s %-15s%-10s%-15s\r\n\r\n", "符号栈", "关系", "输入串", "最左素短语", "使用产生式", "下步动作");show = show + temp;temp ="";CString s_stack, s_sentence, s_lefts, s_prod, s_action;char s_presymbol;do{a = sen[i];if (Dignose(S[k]))j = k;elsej = k - 1;while (pretable[findg(S[j])][findg(a)] == '>'){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);char Q;do{Q = S[j];if (Dignose(S[j - 1]))j = j - 1;elsej = j - 2;} while (pretable[findg(S[j])][findg(Q)] == '>' ||pretable[findg(S[j])][findg(Q)] == '=');int n = selectProd(j + 1, k, S);if (n > -1 && n < locProduct){s_lefts = showLeftS(S, j + 1, k);k = j + 1;S[k] = production[n].Left;s_prod = ProdtoCStr(production[n]);s_action ="归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="无法归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n",s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';tagbreak = false;break;}}if (!tagbreak)break;if (pretable[findg(S[j])][findg(a)] == '<' ||pretable[findg(S[j])][findg(a)] == '='){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);s_action ="入栈";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;k = k + 1;S[k] = a;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="出错";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';break;}i++;} while (a != '#');show = show +"完成";cout << show.GetBuffer(1000) << endl << endl;}void CMyDlg::parse(){string sen;cout << endl << endl <<" 请输入分析的句子:";cin >> sen;cout << endl << endl;m_sen = sen.c_str();}int CMyDlg::selectProd(int i, int j, char S[]) // 查找产生式{int n = -1;int k = 0;for (k = 0;k < locProduct;k++){if (j - i == production[k].num - 1){int si = i;for (int m = 0;m < production[k].num;m++){if (S[si] == production[k].Right[m] || ((!Dignose(S[si])) &&(!Dignose(production[k].Right[m]))))si++;elsebreak;}if (si == j + 1){n = k;break;}}}return n;}CString CMyDlg::ProdtoCStr(Production prod){CString str = "";str = str +prod.Left +"->";for (int i = 0;i < prod.num;i++)str = str +prod.Right[i];return str;}void CMyDlg::Initarry(char arry[], int n)//初始化数组{for (int i = 0;i < n;i++)arry[i] = ' ';}CString CMyDlg::showStack(char S[], int n)//显示符号栈,n表栈大小{CString str = "";for (int i = 0;i <= n;i++)str = str +S[i];return str;}CString CMyDlg::showSentence(CString sen, int start){CString str = "";for (int i = start;i < sen.GetLength();i++)str = str +sen[i];return str;}void CMyDlg::InitAll(){gram ="";i_G = 0;i_g = 0;locProduct = 0;}// 以下是为了便于显示,将数组型转换成CString型CString CMyDlg::showLeftS(char S[], int j, int k) {CString str = "";for (int i = j;i <= k;i++)str = str +S[i];return str;}CString CMyDlg::showTerminal(char g[]){CString str = "{";for (int i = 0;i < i_g;i++)str = str +g[i] +" ";return str +"}";}CString CMyDlg::shownoTerminal(char G[]){CString str = "{";for (int i = 0;i < i_G;i++)str = str +G[i] +" ";return str +"}";}CString CMyDlg::showFirstVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"FirstVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (FirstVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}CString CMyDlg::showLastVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"LastVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (LastVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}FFmain.cpp#include"FunctorFirst.h"void main(){CMyDlg ff;ff.gram ="";ff.locProduct = 0; // 已有产生式个数ff.InputRule();ff.createnoTerminal(); // 建立非终结符索引ff.createTerminal(); // 建立终结符索引ff.createFirstVT(); // 建立FirstVTff.createLastVT(); // 建立LastVTff.createPreTable(); // 建立优先表ff.ShowPreTable();ff.parse();if (ff.m_sen[ff.m_sen.GetLength() - 1] != '#') ff.m_sen = ff.m_sen +'#';ff.preFunctor(ff.m_sen);}。

编译原理实验4算符优先算法

编译原理实验4算符优先算法

一、实验目的与任务算术表达式和赋值语句的文法可以是(你可以根据需要适当改变):S→i=EE→E+E|E-E|E*E|E/E|(E)|i根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。

二、实验涉及的相关知识点算符的优先顺序。

三、实验内容与过程如参考C语言的运算符。

输入如下表达式(以分号为结束):(1)a = 10;(2)b = a + 20;注:此例可以进行优化后输出(不作要求):(+,b,a,20)(3)c=(1+2)/3+4-(5+6/7);四、实验结果及分析(1)输出:(=, a,10,-)(2)输出:(=,r1,20,-)(+,r2,a,r1)(=,b,r2,-)(3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-)五、实验有关附件(如程序、附图、参考资料,等)//程序功能://根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。

//文法:E→E+E|E-E|E*E|E/E|(E)|i// 其中i为无符号整数////例://输入:10;//输出:正确//输入:1+2;//输出:正确//输入:(1+2)/3+4-(5+6/7);//输出:正确//输入:((1-2)/3+4;//输出:错误////输入测试数据保存在同目录的文本文件testin.txt中,保存格式:// 表达式行;// 表达式行;// .....//预期的输出保存在同目录的文本文件testout.txt中,保存格式:// 表达式行;// 正确/错误// 表达式行;// 正确/错误// ...../////////////////////////////////////////////////////////////////#include "stdio.h"#include "stdlib.h"#define TRUE 1#define FALSE 0//文件信息:#define TESTIN_FILENAME "testin.txt"#define TESTOUT_FILENAME "testout.txt"FILE * fTestIn;FILE * fTestOut; //打开文件后的柄//运算符定义:#define O_NUMBER 8 //运算符个数,+-*/()i# #define O_PLUS 0 // 加+#define O_MINUS 1 // 减-#define O_TIMES 2 // 乘*#define O_SLASH 3 // 除/#define O_L_PAREN 4 //左括号(parenthesis)#define O_R_PAREN 5 //右括号#define O_IDENT 6 //标识符#define O_NUL 7 //语法界符#//表达式缓冲区:由专门函数操作(ReadFormula(),GetChar())#define BUFFER_SIZE 1000 //表达式缓冲区大小char Buffer[BUFFER_SIZE]; //表达式缓冲区,以'\0'表示结束int ipBuffer = 0; //表达式缓冲区当前位置序号//算符优先关系表:char O_Table[O_NUMBER][O_NUMBER] = {{'>','>','<','<','<','>','<','>'},{'>','>','<','<','<','>','<','>'},{'>','>','>','>','<','>','<','>'},{'>','>','>','>','<','>','<','>'},{'<','<','<','<','<','=','<','-'},{'>','>','>','>','-','>','-','>'},{'>','>','>','>','-','>','-','>'},{'<','<','<','<','<','-','<','='}}; //优先关系表:八个字符分别是+-*/()i#,其中'-'表示出错//文法:#define OG_NUMBER 6 //文法个数char OG[OG_NUMBER][4] = {"E+E","E-E","E*E","E/E","(E)","i"}; //文法右部//单词序列存放格式定义:#define TOKEN_MAX_LENTH 100 //最大的单词长度+1typedef struct{char ch; //存放字符:+-*/()i#Eint No; //存放算符优先关系表中的序号//double Value; //当ch==i时,且为数值时,存放值的大小} SToken;#define MAX_TOKEN_NUMBER 1000 //在一个表达式中允许最大的单词个数SToken Token[MAX_TOKEN_NUMBER]; //单词序列,最后一个以“#”结束int TokenNumber = 0; //单词序列中包含的单词个数int ipToken = 0; //进行“移进-规约”时的位置指示//堆栈:由专门的函数操作(PopUp(),Push(),…)#define STACK_MAX_SIZE 1000 //堆栈最大存储量SToken Stack[STACK_MAX_SIZE]; //堆栈int ipStack = 0; //堆栈指针,指向栈顶(下一个空位置)//词法分析专用全局变量:char ch; //存放取得的一个字符//char AToken[TOKEN_MAX_LENTH]; //存放组成的单词,存放时以\0为结束//int ipAToken; //用于读字符时,指向下一个AToken[]的位置,便于组成单词//错误信息:char * ErrMsg; //出错信息//函数声明:bool Judge(); //利用算符优先关系表判断单词序列是否正确int GuiYue(); //规约,并判断是否完成bool IsOK(); //判断规约是否全部完成bool GuiYueN(int n); //将堆栈中0~n单词规约int FindPriorOp(int Begin); //在堆栈中,从Begin开始,查找前一个终结符位置int MoveIn(); //移进,并判断是否需要规约void JudgeInit(); //(利用算符优先关系表判断单词序列是否正确)判断前的初始化SToken Peek(int n); //窥视堆栈bool PopUp(int n); //弹出堆栈void PushToken(char ch, int O_No); //压栈(以字符形式)void Push(SToken Token); //压栈bool Init(); //全局初始化void End(); //程序退出前作善后处理void OutPut(char * Formula, char * Result); //将结果输出到文件bool ReadFormula(); //从文件中读出一个表达式存于表达式缓冲区Buffer[]中,以'\0'结束,并置ipBuffer=0;bool ChangeToTokens(); //将表达式分割成单词序列char GetFirstChar(); //从表达式缓冲区中取到下面第一个非空字符char GetChar(); //从表达式缓冲区取一个字符,返回该字符的同时将它存于全局变量ch中bool MakeErr(char * ErrMassage); //生成错误信息,错误信息存于全局变量ErrMsg 中///////////////////////////////////////void main(){if(! Init()) //初始化{printf("初始化失败!程序不能继续。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

13
4.4.2 算符优先文法的定义 • 3 算符优先文法的定义
设有一个不含 规则的OG文法G,
如果任意两个终结符间至多有一种算符 关系存在, 则称G是算符优先文法,也称OPG文法。
结论:算符优先文法是无二义的。
编译原理 算符优先分析法
14
4.4.3 算符优先关系表的构造
• 1 FIRSTVT集、 LASTVT集
规范归约:
自上而下最右推导的逆过程。
编译原理 算符优先分析法
18
例4.12文法G[E]:
E E+T|T
E
T T*F|F
E +T
F (E)|id
句子id*id+id的
T
F
自下向上的语法分析过程。
T * F id
规范归约是最右推导的 逆过程。
*优先于+:
+优先于*:
(1)id+id*id
(1)id+id*id
(2)E+id*id
(2)E+id*id
(3)E+E*id
(3)E+E*id
(4)E+E*E
(4)E*id
(5)E+E
(5)E*E
(6)E
(6)E
编译原理 算符优先分析法
7
4.4.1 方法概述
• 3 优先关系种类
任何两个相邻的终结符a和b可能的优先关系有3 种: a b: a的优先级低于b
FIRSTVT
LASTVT
E
{+,*,(,id}
{+,*,),id}
T
{*,(,id}
{*,),id}
F
{(,id}
{),id}
编译原理 算符优先分析法
17
4.4.4 算符优先分析算法的设计
• 0 算符优先分析法与规范归约的区别
算符优先分析法:
只考虑终结符之间的优先关系来确定可归 约串,而与非终结符无关。
4.3 自下而上分析法的一般原理
• 1 自下而上语法分析概述
基本思想:用一个寄存文法符号的栈,将一个 输入串反向至文法的开始符号。
特点:效率高、文法限制少。
编译原理 算符优先分析法
1
1 自下而上语法分析概述
• 移进-归约过程实例。 例4.11 设有文法G[A]: (1)A aBcDe (2)B b (3)B Bb (4)D d
d进栈
7
$aBcd
e$
用D d归约
8
$aBcD
e$
e进栈
9
$aBcDe
$
用AaBcDe归约
10
$A $ 编译原理 算符优先分析法
分析成功
3
2 移进-归约的基本思想
(1)用一个栈寄存文法符号,移进将一个终结符 推进栈; (2)归约是将0个或多个符号从栈中弹出,用相应 产生式的左部一个非终结符压入栈;
a b: a的优先级等于b
a b: a的优先级高于b
注:优先关系与出现的左右次序有关,不同于数
学符号<,=,>。
编译原理 算符优先分析法
8
4.4.1 方法概述 • 4 优先关系矩阵(表)
矩阵的行和列都是文法的终结符; 矩阵元素是两终结符间的优先关系。
算符优先分析法借助优先关系表寻找句型的可 归约串。
把栈顶被归约的一串符号称为可归约串;
(3)重复这一过程直至整个输入串分析完毕;
(4)最终栈中只剩下左界符$和开始符号S,则所 分析的输入串是文法的正确句子;否则,出错。
编译原理 算符优先分析法
4
3 分类 ◆算符优先分析法
用 最左素短语 刻画可归约串
◆规范归约分析法 简单优先分析法
LR分析法
用 句柄 刻画可归约串
编译原理 算符优先分析法
9
算符优先关系表实例
+ * id
+ * id ( ) $
当前输入串首字符
()$
栈顶第一个终结符
编译原理 算符优先分析法
10
4.4.2 算符优先文法的定义
• 1 算符文法的定义
设有文法G,若G中没有形如U …VW…的规则 ,其中V和W为非终结符,则G称为算符文法, 也称OG文法。
编译原理 算符优先分析法
5
4.4 算符优先分析法
• 4.4.1 方法概述 • 1 特点
适合分析各类表达式; 宜于手工实现; 规定运算符之间的优先顺序(优先关系,结合性 质)。
通过比较算符之间的优先关系确定可归约串。
编译原理 算符优先分析法
6
4.4.1 方法概述
• 2 优先关系
例 文法G[E]: E E+E|E*E|(E)|id 对输入串id+id*id的规范归约过程。
规则。

(2)a b :含有P …aR…的规则,且Rb…或
R

Qb…

(3)a b:含有P …Rb…的规则,且R…a或 R+ …aQ。
编译原理 算符优先分析法
12
4.4.2 算符优先文法的定义 • 2 算符优先关系的定义
规定:
若S

a…或S

Ca…,则$
a


若S …a或S …aC,则a $
编译原理 算符优先分析法
对输入串abbcde$的移进-归约分析过程
编译原理 算符优先分析法
2
对输入串abbcde$移进-归约分析过程:
步骤
符号栈
输入串
动作
0
$
abbcde$
a进栈
1
$a
bbcde$
b进栈2$ab Nhomakorabeabcde$
用B b归约
3
$aB
bcde$
b进栈
4
$aBb
cde$
用B Bb归约
5
$aB
cde$
c进栈
6
$aBc
de$

FIRSTVT(A)={b|A b… 或

A Bb… ,b VT,B VN} 即:非终结符A往下推导所有可能出现的首个 算符的集合.
LASTVT(A)={a|A

…a
A

…aB,
a
VT,B VN}
即:非终结符A往下推导所有可能出现的最后
一个算符的集合.
编译原理 算符优先分析法
15
4.4.3 算符优先关系表的构造
(3) 最后,在表中填入界符的优先关系:
对FIRSTVT(S)中所有b,置$ b;
对 LASTVT(S)中所有a,置a $.
置 $ $。
编译原理 算符优先分析法
16
例4.12 文法G[E]: E E+T|T T T*F|F F (E)|id
构造该文法的算符优先关系表。
Homework: (P105)- 4.5 (2)
性质:
1.在算符文法中任何句型都不包含两个相邻的 非终结符。 2.如Ab或bA出现在算符文法的句型中,则中 任何含b的短语必含有A。
编译原理 算符优先分析法
11
4.4.2 算符优先文法的定义
• 2 算符优先关系的定义
在OG中定义算符优先关系: (1)a b :含有P …ab…,或 P …aQb…的
• 2 算符优先关系表的构造方法 (1)为每个非终结符A计算FIRSTVT(A),LASTVT(A)
(2)计算算符之间的优先关系,并填表。计算方法:
★ 关系:若A …ab… 或A…aBb,则a b
★ 关系:若A…aB…,则bFIRSTVT(B),a b ★ 关系:若A…Bb…,则aLASTVT(B),a b
相关文档
最新文档