单位网站中文域名到期续费,网站怎样做微信公众号,闵行网络推广,华蓥网站建设一、编译器究竟是什么#xff1f; 在前端开发的世界里#xff0c;我们经常会听到 “编译器” 这个词。就拿 Babel 来说#xff0c;在它的官网上#xff0c;最显眼的一句话就是#xff1a;“Babel is a JavaScript compiler”。那什么是 JavaScript 编译器呢#xff1f;又…一、编译器究竟是什么 在前端开发的世界里我们经常会听到 “编译器” 这个词。就拿 Babel 来说在它的官网上最显眼的一句话就是“Babel is a JavaScript compiler”。那什么是 JavaScript 编译器呢又该如何去学习和理解编译器呢让我们一起来揭开它的神秘面纱。 编译器简单来说就是一种电脑程序它的主要工作就是把用某种编程语言写的源代码转换成另一种编程语言。比如说Babel 就可以把 ES6、ES7 或者 JSX 这些新的语法转换成 ES5 或者其他指定版本就像是给代码做了一次 “变形记”。 其实在我们日常的前端开发中有很多工具都用到了编译器的技术比如 Less/Saas 用于处理样式TypeScript/coffeeScript 用于处理脚本还有 Eslint 用于代码检查等等。正是因为有了这些工具前端工程化才能发展得越来越好。
二、编译器的基本思路
一词法分析 (Lexical Analysis)
目的
词法分析的主要任务就是把我们写的文本代码分割成一个个小小的 “token”就像是把一句话拆分成一个个的单词。比如说“init、main、x、;、、3” 这些都可以是 token。同时它还会把那些注释、空格、回车等对代码运行没有实际作用的字符去掉让代码变得更加 “纯粹”。
生成方式
生成 token 主要有两种办法 正则表达式这种方法需要写大量的正则表达式而且这些正则之间还可能会有冲突维护起来比较麻烦性能也不是很高。所以正则表达式一般只适合一些简单的模板语法对于真正复杂的语言就不太合适了。而且有些语言可能还没有自带的正则引擎呢。自动机自动机就像是一个智能的小机器可以很好地生成 token。其中有穷状态自动机finite state machine是一个很重要的概念。它在有限个输入的情况下会在不同的状态之间转移最终达到一个终止状态。有穷状态自动机又可以分为 “确定有穷状态自动机”DFA - Deterministic finite automaton和 “非确定有穷自动机”NFA - Non-deterministic finite automaton。DFA 在输入一个状态时只会得到一个固定的状态可以认为是一种特殊的 NFA而 NFA 当输入一个字符或者条件时会得到一个状态机的集合。JavaScript 正则采用的就是 NFA 引擎。 二语法分析 (Syntactic Analysis)
我们平时说的编译原理其实就是把一种语言转换为另一种语言。编译原理研究的是形式语言这种语言不需要知道太多的背景知识而且没有歧义。和自然语言不一样自然语言很难处理因为很难分清哪些是名词、动词、形容词。比如说 “进口汽车”这里的 “进口” 到底是动词还是形容词呢所以我们要解析一门语言前提是这门语言有严格的语法规定。 在 1956 年乔姆斯基把文法按照规范的严格性分成了 0 型、1 型、2 型和 3 型共 4 种。一般的计算机语言用的是 2 型文法也叫上下文无关文法CFG。因为 0 型和 1 型文法定义太宽松会增加解析的难度降低效率而 3 型文法限制又太多不利于语言设计的灵活性。 语法分析的目的就是把词法分析得到的 token 流结合文法规则通过一定的算法生成一颗抽象语法树AST。AST 在前端领域非常重要比如说 Babel 插件的原理就是es6 代码通过 Babylon.parse 生成 AST然后用 babel-traverse 处理得到新的 AST最后再生成 es5 代码。
从生成 AST 的效率和实现难度来看主要有两种解析算法自顶向下的分析方法和自底向上的分析方法。自底向上算法可以分析的文法范围比较广但是实现起来比较难自顶向下算法实现相对简单能解析的文法范围也不错所以一般的编译器都会采用深度优先索引的方式。
三代码转换Transformation
当我们得到 AST 之后通常会先把它转换成另一种 AST这样可以生成更符合我们预期的 AST这个过程就叫做代码转换。代码转换有很多优势 易移植它和具体的机器没有关系所以可以作为中间语言为生成多种不同型号的目标机器码服务。机器无关优化可以对中间码进行优化提高代码的质量。层次清晰把 AST 先映射成中间代码再映射成目标代码这样可以让编译算法更加清晰。 对于一个编译器来说在转换阶段通常有两种形式
同语言的 AST 转换和 AST 转换为新语言的 AST。
一般的做法是对之前的 AST 从上至下进行解析称为 traversal然后有一个映射表称为 visitor把对应的类型做相应的转换。
四代码生成 (Code Generation)
在实际处理代码的过程中我们可能会递归地分析最终生成的 AST对于每种 type 都有一个对应的函数来处理。最终我们的目标代码就会在这一步输出。在前端领域我们的目标代码可能就是 HTML 了。
三、完整链路 (Compiler)
一个完整的编译器过程可以用下面的代码来表示
input tokenizer tokens; // 词法分析
tokens parser ast; // 语法分析生成 AST
ast transformer newAst; // 中间层代码转换
newAst generator output; // 生成目标代码