自下而上的语法分析和算符优先分析法

自下而上的语法分析:(规约)

由叶节点到根节点,构造树

规范规约:最左规约(对应于最右推导)


例:

对于文法:

SaABe

AAb|b

Bd

abbde的规约过程:

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子
 

对应的最右推导:

SaABeaAdeaAbdeabbde




存在的问题:遇到Ab的时候,有两种可能AAbAb

解决:

短语的概念:

如果S=> αAw=>αβw,则称β为相对于A的、句型αβ的短语

直接短语

     若A→ β为一产生式,则称β为相对于A的、句型αβ的直接短语

例:

句型aAbde所包含的直接短语:

      Abd

句柄:

最左直接短语是句柄

例:句型aAbde所包含的句柄:Ab

素短语

 ①它首先是一个短语②至少含有一个终结符③除自身外,不再含有其它的素短语

最左素短语LPP ( leftmost Prime Phrase)

算符优先分析过程中归约的是最左素短语

例:关于文法EE+T|T

          T→T*F|F

          F→(E)|id

对于句型F+F*id3



语法树是:

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子
 
 

短语:F1,  F2,  id3,  F2*id3,  

            F1+F2*id3

直接短语: F1,  F2,  id3

句柄: F1

最左素短语: id3



用栈实现移进归约分析

关于文法:

        EE+T|T

        TT*F|F

        F(E)|id

对于串 id1*id2+id3 的分析

方法:对于符号栈中的非终结符,能规约就规约,不能规约就从输入串中移入符号

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子


 

算符优先分析法:

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子 表示ab的优先级相等
自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子 表示a的优先级不如b
自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子 表示a的优先级比b

注:

算术关系“<,=”和“>”与优先关系具有十分不同的性质。例如,a<·b并不一定意味着b·>a

例如:+ <·(,但(· >+不一定存在。 具体如:2+(3+5)



算符优先关系矩阵:

关于文法

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子
的优先关系矩阵:

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子

 

FIRSTVTLASTVT集:

FIRSTVT(P)={a|P=>a…或P=>Qa,

LASTVT(P)={a|P=> … aP=>aQ



上面文法的FIRSTVTLASTVT集:

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子
 

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子

 

关于上面文法对于串id+id*id$的分析:

方法:如果<· (表示当前优先级不够)就移进,如果·或者=就规约

自下而上的语法分析和算符优先分析法 - 小镜子~ - 菜园子


算符优先分析法 C++ 编译原理 运行环境:Visual Studio 2005 #include "SStack.h" #include <iostream> #include <string> using namespace std; class Functor { private : char ** table; string ** production; string prog;//待分析字符 int p;//字符指针 int num;//终结符个数 int num1;//产生式个数 SStack <char> stack; public: Functor(int m,int n,char ** T,string **prod,string pr) { num=m; num1=n; table=T; production=prod; prog=pr; p=0; stack.push('$'); } void traversal() { while(p<(prog.length())) { stack.display(); cout<<prog.substr(p)<<" "; char ch; if(Getnum(stack.gettop())) { ch=stack.gettop(); } else { ch=stack.getsecond(); } switch(compare(ch,prog[p])) { case 1: case 2:stack.push(prog[p]);p++;cout<<"移入"<<endl;break; case 3:reduct();cout<<"归约"<<endl;break; } } cout<<"分析成功!"<<endl; } int Getnum(char ch) { for(int i=1;i<num;i++) { if(ch==table[i][0]) { return i; } } return 0; } int compare(char col,char row) { int c=Getnum(col); int r=Getnum(row); switch( table[c][r]) { case '>': return 3;break; case '<': return 2;break; case '=': return 1;break; default:cout<<endl<<"输入有误,程序将终止!"<<endl;system("pause");exit(0);break; } } void reduct() { //待定 string token=""; int temp; string str=""; if(!Getnum(stack.gettop())) { token+=stack.gettop(); stack.pop(); } char ch=stack.gettop(); str+=ch; temp=Haven(str); if(temp!=-1) { token+=production[temp][0]; } else { token+=ch; } stack.pop(); bool Nover=true; while(Nover) { if(Getnum(stack.gettop())) { if(compare(stack.gettop(),ch)==2) { Nover=false; } else { ch=stack.gettop(); str=""; str+=ch; temp=Haven(str); if(temp!=-1) { token+=production[temp][0]; } else { token+=ch; } stack.pop(); } } else { token+=stack.gettop(); stack.pop(); } } string token2=""; //cout<<token<<" "; for(int i=token.length()-1;i>=0;i--) { token2+=token[i]; } //cout<<token2<<endl; if(Haven(token2)!= -1) { stack.push(production[Haven(token2)][0][0]); } else { cout<<"输入有误!分析终止!"<<endl; system("pause"); exit(0); } } int Haven(string temp) { for(int i=0;i<num1;i++) { int j=1; while(production[i][j]!="") { if(temp==production[i][j]) { return i; } j++; } } return -1; } public: ~Functor(void) { } };
### 算符优先分析法的设计与实现 #### 1. 基本概念 算符优先分析是一种基于自底向上语法分析的方法,主要用于解析表达式结构并验证其合法性。该方法的核心在于定义终结符之间的优先级关系,并利用这些关系逐步识别句柄并完成规约[^2]。 #### 2. 设计算符优先关系表 为了实施算符优先分析,需构建一张 **优先关系表**,用于描述各终结符间的相对优先级。具体而言: - 若某两个符号之间存在 `>` 关系,则表示左侧符号具有更高的优先权; - 若为 `<` 关系,则右侧符号更优; - 若两者相等则记作 `=`。 此表格依据文法规则推导得出,通常涉及对 FIRSTVT LASTVT 集合的计算以辅助判定[^1]。 #### 3. 构建栈操作流程 在实际执行过程中采用堆栈存储当前处理状态。初始状态下将特殊标记 `$` 放入栈底作为边界指示器;随后逐字符读取输入并与栈顶元素对比优先级别决定下一步动作——可能包括移进 (shift) 或者归约(reduce)[^2]: 当遇到更高或相同级别的新项时应将其压入栈中(即实行 shift 动作),反之如果发现更低等级项目则尝寻找匹配模式从而触发 reduce 行动直至满足条件为止或者整个字符被成功解析完毕。 以下是伪代码展示如何控制上述逻辑循环直到结束: ```python def operator_precedence_analysis(input_string, precedence_table): stack = ['$'] # 初始化栈含底部标志$ i = 0 # 输入指针起始位置 while True: top_stack_symbol = stack[-1] current_input_symbol = input_string[i] relation = get_relation(top_stack_symbol, current_input_symbol, precedence_table) if relation == '>': # 如果栈顶大于等于待处理符号,则进行reduce操作 handle_reduce(stack) elif relation == '<' or relation == '=': # 当前符号优于或等于栈顶元素,执行shift动作 stack.append(current_input_symbol) i += 1 if is_final_state(stack): break # 判断最终接受态退出循环 return 'Accepted' ``` 其中函数 `get_relation()` 负责查询给定两符号间的关系值来自先前准备好的优先关系矩阵; 函数 `handle_reduce()` 执行具体的产生式替换工作按照既定语法规范展开还原步骤 ; 条件检测 `is_final_state()` 检查是否达到合法终态形式["$S$"] 结束程序运行. #### 4. 示例说明 假设我们有如下简单加减乘除四则运算文法 G[S]: ``` E -> E + T | E - T | T T -> T * F | T / F | F F -> ( E ) | id ``` 经过一系列转换得到相应FIRSTVT/LASTVT集合以及完整优先级对照图表之后可以开始测实例比如 "(id+id)*id-id" 是否符合预期规则集的要求。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值