标签(空格分隔): 未分类前端
本章内容是对本书第3章至第六章中介绍的编译技术的综合介绍.web
2.2:给出一个普遍使用的表示方法来描述语法,叫作上下文无关法
或者BNF(Backus-Naur范式)
.api
2.3:面向文法的编译技术:语法指导翻译
数组
2.4:语法分析数据结构
2.5:一个中缀转后缀的过程app
2.6:词法分析koa
2.8:构造语法树ssh
介绍一种用于描述程序设计语言语法的表示方法---"上下文无关法"
或简称文法
.被用于组织编译器前端.函数
Java的if-else
工具
文法
一个上下文无关法(context-free grammar)由4个元素组成:
非终结符号
表示一个终结符号串
的结合.(后面介绍)非终结符号
.根据文法推倒符号串时.首先从开始符号出发,不断地将某个非终结符号替换为该非终结符号的某个产生式的体.直到所有为终结符号.
parsing
的任务是: 接受一个终结符号串做为输入,找出从文法的开始符号推倒出该串的方法.
若是不能推倒出,则报告语法错误.
主要语法分析方法,在第四章中介绍
语法分析树
用图形方法展示了从文法的开始符号推倒出对应语言中的符号串的过程.
parse tree
有如下性质
e
非终结符号A
它的子节点从左至右有X1,X2..XN
,那么必然有产生式A->X1X2X3..XN
.文法:
须要推倒的语句: 9 - 5 + 2
语法树:
一个文法的语言的另外一个定义是任何可以由某颗语法分析树生成的符号串的集合.
为一个给点的终结符号串构建一颗语法分析树的过程称为对该符号穿进行语法分析
某些语法若是不严谨会产生二义性.好比将上述例子的语法改为
那么对以前的终结符号串的解释能够用两种语法树
前者的结果是6, 后者是2
显然有问题.因此一个好的文法不该该有二义性.
等号的文法:
结合性规则只能做用于同一级别的运算
当具备+
,-
,*
,\
,(
,)
时的文法
factor
不可被分开.term
可能被高优先级的运算符*
和/
分开expr
能够被任意优先级分开非终结字符
来肯定n个优先级的语法.
从如下代码能看出如何增长一个优先级.
语法制导翻译
是经过向一个文法的产生式附加一些规则或程序片断而获得的.
看不懂
语法制导定义(syntax-directed definition)
把每一个文法符号和一个属性集合相关联,而且把每一个产生式和一组语义规则(semantic rule
)相关联,这些规则用于计算与该产生式相关联的属性值.
注释语法分析树
:若是一颗语法分析树的各个结点上标记了相应的属性值,那么这颗语法分析树就称为注释语法分析树,简称注释分析树.
综合属性
:若是某个属性在语法分析树结点N上的值由N的子节点和N自己的属性值肯定,那么这个属性叫作综合属性
5.1.1节将会讲述一种继承属性
:继承属性在某个语法分析树的结点的值由其自己,兄弟,父节点属性值决定.
##关于语法制导一个十分不错的例子
上述例子的语法制导定义具备如下重要性质:
关于树的遍历就再也不赘述了
以前上述的语法翻译的例子将字符串做为属性值附加在结点上,从而获得翻译结果.
咱们来考虑一种不须要操做字符串的方法,经过运行程序片断
,逐步生成相同的翻译结果.
语法分析
是决定如何使用一个文法生成一个终结符号串的过程.
递归降低
的语法分析方法,该方法用于语法分析和实现语法制导翻译器.
Yacc
的工具直接根据方案生成一个翻译器.对于任何上下文无关法,都能构造出一个O(n^3)的语法分析器,可是对于实际的语言设计,基本都是线性时间构造出来的.
自顶向上
,自底向上
.
自顶向上语法
,构造过程从根节点开始,逐步向叶子节点
进行.
自底向上语法
则相反
向前看(lookahead)
符号.
为一个非终结符号 选择产生式是一个尝试并犯错的过程,咱们首先选择一个产生式,若是这个产生式不合适将会进行回溯,再尝试另外一个产生式.
预测语法分析
的特殊状况不须要回溯.
递归降低分析方法(recursive-descent parsing)
是一种自顶向下的语法分析方法,他使用一组递归过程来处理输入.
这里咱们考虑递归降低方法
的一个简单形式,称为预测分析法(predictive parsing)
预测分析法
中,各个非终结符对应的过程当中的控制流能够由向前看无二义的肯定.在分析输入串时出现的过程调用序列隐式地定义了该输入串的一颗语法分析树.关于计算的方法在4.2.2中介绍
预测分析法要求时
当知足可以使用预测分析器时:
对于语法动做如何处理
左递归:
右递归:
右递归对于左结合运算的翻译会变得困难
4.3.3节将考虑更通常的左递归形式
(1)
void S(){ swithch( lookahead ) { case +: match(+);S();S();break; case -: match(-);S();S();break; case a; match(a);break; default: report("syntax error"); } }
(2)要注意最终的结果,并消除左递归
void S(){ if(lookahead == "("){ match("("); S(); match(")"); S(); } }
(3)两个产生式的FIRST都是0,须要注意
void S() { if(lookahead==0) { match(0); if(lookahead!=1) S(); match(1); } else report("syntax error"); }
使用前三节技术,咱们将使用Java语言编写一个语法制导翻译器.
如今咱们处于矛盾中:
另外一方面,咱们须要一个明显不一样的可以支持语法分析过程的文法;
因此先使用易于翻译的文法,而后当心的转换,使之可以语法分析.
咱们将消除2-21的左递归,获得一个适用于预测递归降低翻译器的文法.
设计一个翻译器是,名为抽象语法树(abstract syntax tree)
的数据结构是一个很好的起点.
语法分析树叫作具体语法树(concrete syn-tax tree)
,相应的文法叫作该语言的具体文法(concrete syntax)
2个左递归产生式和一个非左递归产生式
通常都会预读一些字符放在缓冲区.有两个好处
>
仍是>=
等本节的词法分析器会预读一个字符,本节中的词法分析器不变式断言以下:
当词法分析器返回一个词法单元时:
- 变量
peek
要么保存当前词法单元词素后的那个字符,要么保存空白
当在输入流出现一个数位序列时,词法分析器将向语法分析器传送一个词法单元.
num
和根据数位计算出来的值 如:<num,31>
关键词(keyword)
:大多数程序使用for
,do
,if
这样的固定字符串做为标点符号,或者用于某种构造,这些字符串加作关键词.
关键词一般也知足标识符的组成规则,当将关键词做为保留字时,相对容易解决.
使用一个字符串表来保存字符串.
符号表(symbol table)
是一种供编译器用于保存有关源程序构造的各类信息的数据结构.
一颗 有前向边的树
支持三种操做
两种最重要的中间表现形式
指望<=
,>=
以后的结构是boolean
咱们将说明如何经过遍历语法树来生成三地址代码.
具体来讲,咱们将显示如何编写一个抽象语法树的函数,并同时生成必要的三地址代码.
If
是类Stmt
的一个子类.Stmt
的子类都有一个构造函数和一个gen
gen
是一个生成三地址代码的函数.咱们将考虑包含二目运算符op
,数组访问,和赋值运算,并包含常量及标识符的表达式,以此来讲明对表达式的翻译.
lvalue
,rvalue