如果要解释执行或转换一段语言,那么就无法在识别语法规则的同时达到目标,只有那些简单的,比如将wiki markup转换成html的功能,可以通过一遍解析来完成,这种应用叫做 syntax-directed应用. 更负载的功能,需要我们在完成parse的同时构建某种中间表示形式(Intermediate representation),简称为IR.实际上,我们一般构建一种叫做AST(abstract syntax tree)的结构,它保存了所有的token以及token之间的语法关系.在一个语言应…
每个编程的人都学习过树遍历算法,但是AST的遍历并不是开始想象的那么简单.有几个因素会影响遍历算法:1)是否拥有节点的源码:2)是否子节点的访问方式是统一的:3)ast是homogeneous或heterogeneous:4)遍历的过程中是否需要修改ast:5)以何种顺序呢遍历.这一章会讨论常用的四个ast遍历模式. Pattern 12, Embedded Heterogeneous Tree Walker, AST的node类包含了对应的访问方法,后者执行嵌入的操作,并访问所有的子节点.这种…
前面的章节我们学会了如何解析语言.构建AST,如何访问重写AST,有了这些基础,我们可以开始进行"语义分析"了. 在分析语义的一个基本方面是要追踪"符号",符号是语句定义的变量.函数,我们通过建立一种叫做"符号表"的基础结构来完成此项工作. 有两种模式的符号表: Pattern 16, Symbol Table for Monolithic Scope,所有的符号存在于单一的作用域内,早期的BASIC使用这种模式: Pattern 17, Sym…
前面讲述了如何验证语句,这章讲述如何构建一个解释器来执行语句,解释器有两种,高级解释器直接执行语句源码或AST这样的中间结构,低级解释器执行执行字节码(更接近机器指令的形式). 高级解释器比较适合DSL,而不适合通用编程语言:一般来说,DSL更需要简单.廉价的实现,不是很在乎执行效率:这个笔记只学习高级解释器,下面的文字如果提到解释器就是指"高级"解释器.为了简单起见,下面的讨论假定目标DSL是动态类型的. 解释器有两种模式: Pattern 24,Syntax-Directed In…
语句的语义取决于其语法结构和相关符号:前者说明了了要"做什么",后者说明了操作"什么对象".所以即使语法结构正确的,如果被操作的对象不合法,语句也是不合法的.语言一般有很多语义规则,有些是运行时的(dynamic semantics),比如"不能除以零"."不能越界访问数组":有些是编译时的(static semantics).运行时&编译时的界限取决于具体的语言,python是动态类型的语言,所有的值编译时都不会指定…
本章学习一种新的作用域,叫做数据聚合作用域(data aggregate scope),和其他作用域一样包含符号,并在scope tree里面占据一个位置. 区别在于:作用域之外的代码能够通过一种特殊的表达式user.name来访问数据成员:以下两个模式分别描述非面向对象语言和面向对象语言的数据聚合作用域. Pattern 18, Symbol Table for Data Aggregates,描述了如何定义和访问简单的数据聚合,比如C struct; Pattern 19, Symbol T…
上一章节讲述了基本的语言解析模式,LL(k)足以应付大多数的任务,但是对一些复杂的语言仍然显得不足,已付出更多的复杂度.和运行时效率为代价,我们可以得到能力更强的Parser. Pattern 5 :回朔解析器(Backtracking Parser),这种解析器晖尝试规则的每个分支来进行匹配,与LL(k)比较的话,Backtracking Parser支持任意长度的预读token,这种Parser的能力极强,运行时的代价可能会很大. Pattern 6 :Memoizing Parser, 这…
语言翻译器可以从一种计算机语言翻译成另外一种语言,比如一种DSL的标量乘法axb翻译成java就变成a*b:如果DSL里面有矩阵运算,就需要翻译成for循环.翻译器需要完全理解输入语言的所有结构,并选择输出结构:简单的关键字或模式替换几乎肯定不会奏效."语言翻译"是一个庞大的主题,这一章只关注大体的策略和几个基本模式. Pattern 29, Syntax-Directed Translator,在parser里面嵌入操作,直接产生输出: Pattern 30, Rule-Based…
语法分析器的任务是确定某个单词流是否能够与源语言的语法适配,即设定一个称之为上下文无关语言(context-free language)的语言集合,语法分析器建立一颗与(词法分析出的)输入单词流对应的正确语法树.语法分析树的建立过程主要有两种方法:自顶向下语法分析法和自底向上分析法.AST作为语法分析树(parse tree)的一种简写方式,它独立于具体编程语言(C++.Java.C等),而且与语法分析树的建立过程无关(自顶向下和自底向上逻辑等价),是联系编译器前端.后端的重要接口.Clang的…
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! JavaScript 是如何工作的:深入V8引擎&编写优化代码的5个技巧! JavaScript 是如何工作的:内存管理+如何处理4个常见的内存泄漏 ! JavaScript 是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式! JavaScript 是如何工作的:…