编译器设计 第三章 语法分析器

第三章 语法分析器

判断单词流表示的输入程序在设计语言中是否为一个有效的句子

概述

  • 概念路线图

主要任务,确定输入程序在源语言中是否是一个语法上有效的语句。通过将源语言的形式限制到一个称为上下文无关语言(context-free language)的语言集,可以确保语法分析器能够高效地回答成员资格问题。

  • 自顶向下语法分析(top-down parsing ) 递归下降语法分析器(recursive-descent parser)和LL(1)语法分析器;

  • 自底向上语法分析(bottom-up parsing ) LR(1)语法分析器

  • 语法分析

给出单词流s和语法G,找到G中生成s的一个推导

语法的表示

RE无法匹配括号左右平衡的表达式

  • 上下文无关语法 (CFG)
    对于语言L,其CFG定义了表示L中有效语句的符号串的集合。
    设G为上下文无关语法,描述了语句的形成;则L(G)为可以从G导出的语句集,G定义的语言

  • 语句
    可以从语法规则推导出的一个符号串

  • 产生式
    CFG中的每个规则都称为一个产生式

  • 非终结符
    语法产生式中使用的语法变量

  • 终结符
    出现在语句中的单词,包含一个词素及其语法范畴;在语法中,单词通过其语法范畴表示

  • 推导
    推导是一系列的重写步骤,从语法的起始符号开始,,结束于语言中的一个语句

  • 句型
    有效推到中的某个步骤出现的符号串

  • 上下文无关语法的构成
    上下文无关语法G是一个四元组( T , NT , S , P):
    T 终结符或语言L(G)中单词的集合
    NT G产生的非终结符的集合
    S 一个非终结符,L(G)中语句的集合
    P G中产生式或重写规则的集合
    T和NT可以在P中推导出来

语法分析树

语法分析树

  • 表示推导的图 语法分析树

  • 最右推导 每次都重写最右侧的非终结符(仅看非终结符的最右侧)

  • 最左推导 每次都重写最左侧的非终结符

  • 二义性 如果L(G)中的某个语言有一个以上最右(最左)推导,那么语法G就是二义性的 // 不良性质,无法确定分析树,转化成确定的代码

  • 为强制保证优先级正确 在 a+b* c 之类的语句,会按照 a+(b*c)来进行推导, 其他具有优先级先后的均如此

上下文无关语法及对应语法分析器的类

各种语法分析器

从特定输入语句构造推导的过程称为语法分析
语法分析器看到的“程序”来自于词法分析器的输出:一个单词并注明了其语法范畴
ex. a+b*c ==> <name,a> + <name,b> * <name,c>
将语法分析器的功能形象化定义为 “为输入程序构建语法树” 也是有用的。
树的根已知,即语法的起始符号;叶子节点已知,必须按照从左至右的顺序逐一匹配词法分析器返回的单词流

自顶向下语法分析

  • 从根开始构建语法树,并使树向叶子的方向增长,直至:
    1. 语法分析树的下边缘只包含终结符 且输入流已经耗尽
    2. 部分完成的语法分析树的下边缘各节点,与输入流存在着明确的不匹配

上下文无关语法的很大一个子集不进行回溯即可完成语法分析

为进行自顶向下语法分析而转换语法

  • 左递归 会导致无限循环
    对于CFG中的一个规则,如果其右侧第一个符号与左侧符号相同或者能够推导出左侧符号,那么称该规则是左递归的,前者为直接左递归,后者为间接左递归

    引入e使得左递归变成右递归:即规则中的递归只涉及最右侧的符号

  • 无回溯语法
    一种CFG,最左自顶向下语法分析器可以在至多前瞻一个单词的情况下,总是能够预测正确的产生式规则(前瞻符号 look ahead symbol)

  • 提取左因子以消除回溯
    在一组产生式中,提取并隔离共同前缀的过程

自顶向下的递归下降语法分析器

递归下降的语法分析器,在结构上呈现为一组相互递归的过程,语法中的每个非终结符号都对应与一个过程,因而,语法自身充当了实现语法分析器的指南

LL(1)语法分析器: 由左(Left)到右扫描其输入,构建一个最左推导(Leftmost),其中仅使用一个前瞻符号(1),其是无回溯的
语法分析器生成器:可以根据规格来构建语法分析器,编译器的编译器。

自底向上语法分析 ×

从叶子节点开始构建语法树,并使树向根的方向增长,直到出现以下两种情况:
1. 将分析书的上边缘缩减到只有一个节点,即语法的目标符号 (分析成功)
2. 无法找到句柄 (失败)

  • 句柄 <A -> β , k > ,其中β出现在语法分析树的上边缘,而其右侧末端位于位置k,且将β替换为A是语法分析中的下一步
  • 归约 在自底向上语法分析器中,利用A -> β将树上边缘中的β替换为A,从而缩减语法树上边缘的做法

LR(1)从左(Left)到右扫描,反向(Reverse)最右推导,一个前瞻符号(1)

实际问题

出错恢复

通过找到下一个同步单词 synchronizing word 例如 ; ,再调用分析器

一元运算符

增加一个反引用的形式

处理上下文相关的二义性

  1. 重写语法 暂时搁置二义性
  2. 根据声明类型来归类标识符

左递归和右递归的选择

  1. 栈深度
    右递归语法栈深度更大,受限于列表长度;左递归栈深度取决于语法本身,而非输入流
  2. 结合性

高级主题 ×

这个里面的都是测试数据,总共得分5分。从控制台输入,不能从文件中读取。实现了基本功能,加分项目都没有去实现,没有函数数组这些的实现。这是用C++语言写的,新建parser类别要选C++,其他对于VS的配置和C语言一样。for语句用的是枚举所有情况,你可以自行修改。 对预备工作中自然语言描述的简化C编译器的语言特性的语法,设计上下文无关文法进行描述 借助Yacc工具实现语法分析器 考虑语法树的构造: 1.语法树数据结构的设计:节点类型的设定,不同类型节点应保存哪些信息,多叉树的实现方式 2.实现辅助函数,完成节点创建、树创建等功能 3.利用辅助函数,修改上下文无关文法,设计翻译模式 4.修改Yacc程序,实现能构造语法树的分析器 考虑符号表处理的扩充 1.完成语法分析后,符号表项应增加哪些标识符的属性,保存语法分析的结果 2.如何扩充符号表数据结构,Yacc程序如何与Lex程序交互,正确填写符号表项 以一个简单的C源程序验证你的语法分析器,可以文本方式输出语法树结构,以节点编号输出父子关系,来验证分析器的正确性,如下例: main() { int a, b; if (a == 0) a = b + 1; } 可能的输出为: 0 : Type Specifier, integer, Children: 1 : ID Declaration, symbol: a Children: 2 : ID Declaration, symbol: b Children: 3 : Var Declaration, Children: 0 1 2 4 : ID Declaration, symbol: a Children: 5 : Const Declaration, value:0, Children: 6 : Expr, op: ==, Children: 4 5 7 : ID Declaration, symbol: a Children: 8 : ID Declaration, symbol: b Children: 9 : Const Declaration, value:1, Children: 10: Expr, op: +, Children: 8 9 11: Expr, op: =, Children: 7 10 12: if statement, Children: 6 11 13: compound statement, Children: 3 12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值