C++实现算符优先文法

本文详细介绍算符优先文法的解析方法,包括FIRSTVT集和LASTVT集的定义及求解,算符优先关系表的构建,以及算符优先分析法的实现过程和输出结果。适用于表达式的语法分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Operator-precedence-grammar

C++读取文件,求解firstvt集与lastvt集,构建算符优先关系表,打印文法分析过程,实现算符优先文法

概述

算符优先分析法(Operator Precedence Parse)是仿效四则运算的计算过程而构造的一种语法分析方法。算符优先分析法的关键是比较两个相继出现的终结符的优先级而决定应采取的动作。

​ 优点:简单,有效,适合表达式的分析。

​ 缺点:只适合于算符优先文法,是一个不大的文法类。

FIRSTVT集和LASTVT集

FIRSTVT集

定义:FIRSTVT§={a|P=>a…,或P=>Qa…,a属于VT,Q 属于VN}

求法

若P→a…或P→Qa…, 则a属于FIRSTVT§;

若P→Q…, 则FIRSTVT(Q)含于FIRSTVT§;

直至FIRSTVT§不再增大。

LASTVT集

定义:LASTVT§={a|P=>…a,或P=>…aQ,a含于VT,Q 含于VN}

求法

若P→…a或P→…aQ, 则a属于LASTVT§;

若P→…Q, 则LASTVT(Q)含于LASTVT§;

直至LASTVT§不再增大。

构造算符优先关系表

以以下文法为例:

​ E→E+T|T

​ T→T*F|F

​ F→(E)|i

终结符之间的优先关系

对算符文法G, a,b属于VT 定义

(1)a=b: G中有P→. . .ab. . .或P→. . .aQb. . .

(2)a<b: G中有P→. . .aQ. . .且Q=>b…或Q=>Rb…

(3)a>b: G中有P→. . .Qb. . . 且Q=>. …a或Q=>…aR

算符优先关系表的构造

(1) 在文法中添加E→#E#。

(2) 求出FIRSTVT和LASTVT集

(3) 找出所有终结符,并画出关系表的结构

  • 从文法中找出形为aQb(终结符+非终结符+终结符)和ab(终结符+终结符)的部分,本例中为(E)和#E#,然后在(和)与#和#相应的表格填等于号。
  • 从文法中找出形为aQ(终结符+非终结符)的部分,a与Q的FIRSTVT集合中每一个元素在表格中的交叉点填小于号。
  • 从文法中找出形为Qa(非终结符+终结符)的部分, Q的LASTVT集合中每一个元素与a在表格中的交叉点填大于号。

img

构计算分析过程

初始时,输入指针指向输入串的第一个符号,#入栈;然后比较栈顶终结符a和输入符号b的优先关系:
1.如a=b,且都是#,输入串合法,分析结束。
2.如a<b或a=b, b入栈,输入指针右移。
3.如a>b,寻找位于栈顶的包含a的最小的可规约串(最左素短语) ,
3.1如果找到,将该串规约。
3.2如果未找到,输入串非法,分析结束。
4.如a和b不存在优先关系,输入串非法,分析结束。

实现过程

输出结果

代码链接

C++实现算符优先文法

算符优先分析文法是一种工具,在编译的过程中,隶属于语法分析环节,却又中间代码的生成息息相关,编译可以分为五个阶段:词法分析、语法分析、语义分析(中间代码的生成)、代码优化、目标代码生成。语法分析是指:在词法分析基础上,将单词符号串转化为语法单位(语法范畴)(短语、子句、句子、程序段、程序),并确定整个输入串是否构成语法上正确的程序。也就是说语法分析是检验输入串的语法是否正确,注意这里的语法正确,只是简单地符合自己定义的规范,而不能检测出运行时错误,比如"X/0",空指针错误,对象未初始化等错误。在这一个验中,我将通过算符优先分析文法这一个工具,在语法分析的时候,顺便进行语义分析,也就是识别出语法单位,同时简要的将识别出的中间代码进行计算(目标代码的生成+运行),得到相应的结果,来检验自己设计的正确性。可以说题目虽然叫做算符优先分析文法,其却是一个贯穿了“词法分析+语法分析+语义分析+中间代码优化+目标代码生成+运行”全过程的一个极具概括性的程序。如果能将这个程序得心应手的完成出来,我相信诸位对编译原理的掌握也算是炉火纯青了。时隔将近两年再来整理自己以前写过的验报告,还是挺有感慨的,对一件东西感兴趣,原来影响还会如此深远,还记得自己当时连续六个小时全神贯注写出的验报告,现在看看竟然写了五六十页,核心内容也有三四十页,不觉的感慨当年充满热情的时代慢慢的竟走出许久