【龙书笔记】语法分析涉及的基础概念简介

本篇笔记是我对龙书第2.3-2.5节内容的理解,主要介绍编译器前端关于语法分析的众多基础概念。下篇笔记将根据本篇笔记的主要内容,实现一个针对简单表达式的后缀式语法翻译器Demo(原书中是java实例,我给出的将是逻辑一致的Python版本的实现)。

1. 语法分析(Syntax Analysis)

简单来说,语法分析的任务是分析输入的符号字符串(string of symbols, 通常是词法分析产生的tokens)是否遵循某种语言在其上下文无关文法(context-free grammar)中给出的规则,其中,规则由一系列产生式(production)给出。

如果分析成功,则它会构造出程序的抽象语法树(Abstract syntax tree http://en.wikipedia.org/wiki/Abstract_syntax_tree);否则它会抛出类似于"syntax error"的错误提示。

完成语法分析的程序在术语上被称为Parser,其任务是判决输入的token streams是否可以由该语言的文法的开始符号推导出来以及如何推导。

原则上parser必须具备为输入串构造出语法分析树的能力(虽然事实上,编译器在实现语法分析时是不会真正去构造完整的语法分析树的,它会构造更简洁的抽象语法树)。

Paser有两类常见实现方式:

1) top-down parsing

自顶向下类型的parser从根节点开始构造语法分析树,逐步向叶子节点方向进行。这种方法可以较容易地手工构造出高效的语法分析器。

与此类parser相关的常见术语有inherited attributesLL parser

2) bottom-up parsing

自底向上的方法从叶子节点开始,逐步构造出根节点。这种方法可以处理更多种文法和翻译计划,故直接从文法生成语法分析器的软件工具通常采用bottom-up的方法。

与此类parser相关的常见术语有synthesized attributesLR parser

关于目前业界常见的parsers(如LL-parser/LR-parser)的总结,可以参考wikipedia的parser条目

2. 语法制导翻译(Syntax-Directed Translation, SDT)

语法制导翻译指的是一个转换过程,其目的是将输入的字符串翻译成一系列具有语义的动作,这是通过向文法产生式附加规则或程序片段来实现的。SDT为向语法附加语义动作(semantic actions)提供了一个简单的方法。

SDT有两个重要的相关概念:语法制导定义(Syntax-Directed Definition, SDD)和语法制导翻译计划(Syntax-Directed Translation Scheme, SDTS)。

2.1 语法制导定义(SDD)

SDD是一种特殊的context-free grammar,其特殊之处在于它为每个文法符号(grammar symbol)附加了属性(如符号的数据类型、指令数目、指令位置等),并且为这些文法符号构成的产生式附加了语义规则(semantic rules),其中语义规则定义了产生式中的符号的关联属性值的求值规则。下面是语法制导定义的示例,它为左侧的产生式附加了右侧的语义规则。

2.2 语法制导翻译计划(SDTS)

SDTS也是一种特殊的context-free grammar,其特殊之处在于它在产生式体中嵌入了被称为语义动作(semantic actions)的程序片段。语法制导翻译计划与语法制导定义相似,只是显式指定了语义规则的计算顺序。下面是语法制导翻译计划的示例,它在产生式中嵌入了语义动作。

2.3 SDD和SDTS的区别与联系

Stanford某CS课程关于龙书的Lecture Notes对这两个概念的区别描述是:

SDDs are useful for specifying translations.

SDTSs are useful for implementing translations.

即语法制导定义(SSDs)指定附加在产生式上的语义规则;而语法制导翻译计划(SDTSs)在合适的时机(通常是根据产生式推导输入的token流期间)实现了这些语义动作。

根据wikipedia关于Syntax-directed translation的介绍,当采用bottom-up parsing的方法且SDD采用S-attributed文法时,SDD实现起来最简单。此时,可以通过在产生式体最右边嵌入语义动作的方式来构造语法制导翻译计划,这些动作在产生式被推导时执行。这种把所有的语义动作嵌入在产生式最右的SDT被称为后缀(postfix)翻译计划。

3. 具体语法树(Concrete Syntax Tree, CST)和抽象语法树(Abstract Syntax Tree, AST)

具体语法树CST其实就是语法分析树(常简称为parse tree),如下图是龙书第2.2.3节给出的关于表达式"9-5+2"在产生式为"list -> list + digit"时的语法分析树。

在具体语法树中,树的内部节点表示非终结符,叶子节点全部为终结符,这些终结符构成了可以由对应的产生式推导出来的输入串。

抽象语法树AST是一种数据结构,在表达式的AST中,每个内部节点代表一个操作符,而节点的子节点代表该操作符的操作数。下图是龙书第2.5.1节给出的关于表达式"9-5+2"在产生式为"list -> list + digit"时的抽象语法树。

对比AST和CST可知,AST省略了很多出现在CST中的辅助符号,这使得AST显得很简洁,在编译器的实现语法分析时,处理AST显然更高效。

值得注意的是,CST只是个概念上的语法树,它在原则上保证了编译器对源码文件的无歧义语法分析,不过编译器实现语法分析时,CST显得过于冗余,所以,CST的简化版本AST才是大部分编译器在语法分析时真正构建的数据结构

关于CST和AST的更多讨论,可以参考StackOverflow的这篇帖子What is the difference between an Abstract Syntax Tree and a Concrete
Syntax Tree?
或参考这篇文章Abstract vs. Concrete Syntax Trees

【参考资料】

1. 龙书第2.3-2.5节

2. Stanford Lecture Notes for DragonBook:
Syntax-Directed Definitions

3. wikipedia: Types of parsers

4. wikipedia: Attribute grammar (Inherited-Attributes && Synthesized-Attributes)

5. wikipedia: Syntax-directed translation

6. StackOverflow: What is the difference between
an Abstract Syntax Tree and a Concrete Syntax Tree?

7. Abstract vs. Concrete Syntax Trees

========================== EOF =========================

时间: 2024-10-23 17:02:44

【龙书笔记】语法分析涉及的基础概念简介的相关文章

JavaScript随笔记(一)基础概念以及变量类型

一.JavaScript中的基础概念 1.defer属性 一般我们在引用外部js文件的时候往往是将引用文件的位置放在标签当中,比如那么在标签中引入多个js文件时,浏览器会按照引入顺序加载执行这些引入的js文件,如果加载执行的这些js文件的时间比较长,那么页面就会处在等待期间.在下载引入的js文件时,现在的浏览器大多都是会并行下载的,不会去单线程的下载,这样提高了效率,但仍然会阻塞一些其他资源的下载比如说图片的下载,这样就因为js的下载执行而阻塞了UI渲染,会在页面上形成空白页面,这时我们可以有多

【Machine Learn】机器学习及其基础概念简介

机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结合视频学习和书籍基础的笔记所得.本系列文章将采用理论结合实践方式编写.首先介绍机器学习和深度学习的范畴,然后介绍关于训练集.测试集等介绍.接着分别介绍机器学习常用算法,分别是监督学习之分类(决策树.临近取样.支持向量机.神经网络算法)监督学习之回归(线性回归.非线性回归)非监督学习(K-means聚

【龙书笔记】用Python实现一个简单数学表达式从中缀到后缀语法的翻译器(采用递归下降分析法)

上篇笔记介绍了语法分析相关的一些基础概念,本篇笔记根据龙书第2.5节的内容实现一个针对简单表达式的后缀式语法翻译器Demo. 备注:原书中的demo是java实例,我给出的将是逻辑一致的Python版本的实现. 在简单后缀翻译器代码实现之前,还需要介绍几个基本概念. 1. 自顶向下分析法(top-down parsing) 顾名思义,top-down分析法的思路是推导产生式时,以产生式开始符号作为root节点,从上至下依次构建其子节点,最终构造出语法分析树.在具体实现时,它会把输入字符串从左到右

【龙书笔记】编译器简介及程序构建过程综述

备注:本文是近期重新阅读编译器经典教材<Compilers Principles, Techniques, & Tools>一书(又称DragonBook,龙书)的其中一篇读书笔记. 1. 什么是编译器 从本质来看,平时提到的"编程语言"其实都是一些助记符,用于向其他人或机器描述我们想要完成的逻辑运算.这些易于人类理解的语言想要被计算机理解并正确执行,就必须被转换成机器码,而完成这一转换过程的软件系统就是编译器. 简言之,编译器其实也是一个计算机程序,它可以读取用一

Directx10 龙书笔记- 雾效的实现

雾 : 说白了就是一层有颜色的(一般是白色,灰色) 蒙蒙的感觉 混在光线里面. 不管是白天还是黑天. 龙书里面是这样实现的: 1.  给雾定义一个颜色 float3 gFogColor={0.7f,0.7f,0.7f}; 2. 然后呢在顶点着色器里面计算出 顶点级别的雾化需要的颜色加成比例 加成比例: 意思是当距离摄像机,就是你的眼睛越远,雾的浓度越大,就是颜色越深. 根据这个得出一个(0,1)的和距离有关的比例系数 vout.fogLerp = saturate((d-gFogStart)/g

Directx10 龙书笔记- 第7章课后题 实现火焰动画

火焰的图片我是没找到,找到了几张雷电的,就在d3dcoder.net 的directx10那本书代码下载的Bolt Animations for Chapter 9  里面 里面很多张图片,由于c++也是初学,一时来不及弄字符串拼接的函数. 只能定义很多个帧bmp 然后一个一个载入了 具体代码是建立在那个"crate" 例子工程, 就是那个木箱子的代码基础上. 添加的代码如下: ID3D10ShaderResourceView* mDiffusePic[9]; 我定义了一个能装9张图片

《Cocos2d-x实战:C++》学习笔记(1)——基础概念

1.导演(Director) 导演类(v3.0之前是CCDirector)用于管理场景对象,采用单例设计模式,在整个工程中只有一个实例对象.由于是单例模式,能够保存一致的配置信息,便于管理场景对象.用getInstance()方法获取Director的实例.导演对象的职责如下: 访问和改变场景 访问Cocos2d-x的配置信息 暂停.继续.和停止游戏 转换坐标 Director类的类关系 2.场景(Scene) 场景类(v3.0之前是CCScene)是构成游戏的界面,类似于电影中的场景.场景大致

DirectX10 龙书笔记- 一个颜色立方体程序

这篇是作为学习笔记之用,详细代码在Introduction to 3D Game Programming with Directx10里面的扉页,有个网址 www.d3dcoder.net 里面可以下载 这个程序的效果是: 这个demo展示了基本的directx基本的渲染流程. 首先是渲染管线: 它的作用是根据虚拟摄像机视角生成2D图像的基本步骤. 主要是类为ColoredCubeApp class ColoredCubeApp : public D3DApp { public: Colored

kvm学习笔记(一,基础概念)

前言 阿里云的云主机,采用的kvm,今天就花了点时间研究了下. 一.安装 官方文档参考:http://www.linux-kvm.org/page/HOWTO 二.快速建立一个基于vnc的虚拟机安装 桥接网卡 命令创建虚拟机 virt-install #--network bridge:br0 如果主机网卡不是桥接模式注释掉,默认走NAT模式 --name vm12 --ram=1024 --vcpus=1 --disk path=./vm12.img,size=10 --graphics vn