成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用JavaScript實現一個編譯器

開發 前端
Babel is a JavaScript compiler!這是Babel官方對于babel的定義。身為前端工程師,因此有必要了解編譯原理,幸運的是,“The Super Tiny Compiler”開源項目利用JavaScript寫了一個簡單的編譯器。

 現在前端開發中,我們常常會用到babel來編譯例如react、vue框架的代碼,以支持更多的(更古老的)瀏覽器,babel編譯代碼的過程就是編譯原理的應用之一。

Babel is a JavaScript compiler!這是Babel官方對于babel的定義。身為前端工程師,因此有必要了解編譯原理,幸運的是,“The Super Tiny Compiler”開源項目利用JavaScript寫了一個簡單的編譯器。

麻雀雖小,五臟俱全,通過對該項目的學習,一起加深對編譯過程的理解,以提升我們寫出更高質量的程序!

一、收益

通過掌握(了解)編譯原理,將有如下收益:

加深對編程語言的認識,無論何種編程語言,萬變不離其宗

殊途同歸,有利于理解babel等轉譯器、eslint、prettier、less等工具的工作原理,可開發相關插件

可以造更多輪子了🐶

二、編譯過程概述

編譯過程的具體實現主要分為三步驟:

  1. 代碼解析(parse)
  2. 代碼轉換(Transformation)
  3. 代碼生成(Code Generation)

通過上述三步驟,可以將我們的原代碼,轉換(編譯)到目標代碼,例如把javascript代碼轉換到python一樣。

編譯過程

“The Super Tiny Compiler”項目中是將LISP語言編譯為C語言,如下案例:

  1. *                  LISP(source)             C(target) 
  2. *   2 + 2          (add 2 2)                 add(2, 2) 
  3. *   4 - 2          (subtract 4 2)            subtract(4, 2) 
  4. *   2 + (4 - 2)    (add 2 (subtract 4 2))    add(2, subtract(4, 2)) 

二、轉換過程

基于“The Super Tiny Compiler”項目,實現一個將LISP函數轉換到C語言函數編寫形式!

  1. (源代碼)LISP CODE: (add 2 (subtract 4 2)) 
  2. (目標代碼)C CODE:    add(2, subtract(4, 2)) 

2.1 解析(Parse)

具象到具象的轉換是很難的,但抽象到具象的轉換往往是容易的。

解析的過程中包含了兩個關鍵步驟詞法分析(Lexical Analysis)和語法分析(Syntactic Analysis),解析就是一個具象到抽象的過程。

2.1.1 詞法分析

詞法分析的過程,主要是將原代碼(字符串),通過分詞的方式生成一個具有描述程序語義的token列表。

分詞的原理:逐個讀取源代碼中的字符,與預設的關鍵詞、字符串、數字、操作符等LISP語言定義的語法相關規則,轉換成 {type: 'xx', value: 'xx'} 的具有描述意義的形式

例如LISP:(add 2 (subtract 4 2)),經過詞法分析會得到如下結果:

  1.     { type: 'paren',  value: '('        }, 
  2.     { type: 'name',   value: 'add'      }, 
  3.     { type: 'number', value: '2'        }, 
  4.     { type: 'paren',  value: '('        }, 
  5.     { type: 'name',   value: 'subtract' }, 
  6.     { type: 'number', value: '4'        }, 
  7.     { type: 'number', value: '2'        }, 
  8.     { type: 'paren',  value: ')'        }, 
  9.     { type: 'paren',  value: ')'        }, 

這樣一個列表(暫稱作:tokens列表)按照順序下來很好的描述了源代碼中的字符串和編程語義。

2.1.2 語法分析

詞法分析后得到的tokens列表已經可以描述LISP的語法,但是還并不抽象,因為直觀看來,我們無法解讀這個程序的意思,這就需要將其轉換為AST(Abstract Syntax Tree,抽象語法樹)。

為什么要將其轉換到AST,AST能更好的描述源代碼的語義、描述結構更加通用,tokens列表只是描述了“符號”的意義,可以將詞法分析過程看作是分類過程,而語法分析的過程,則是將符號組合,使其具有了執行順序以及執行規則的語法,抽象語法樹,因為更抽象,因而能更高效率轉換到其他形式。

操作LISP得到的AST能更好轉換到C語言的AST,因為他們的AST結構都是類似的,操作AST比tokens更容易。

語法分析的過程,將tokens列表轉化成為一個樹結構:

  1.   type: 'Program'
  2.   body: [ 
  3.     { 
  4.       type: 'CallExpression'
  5.       name'add'
  6.       params: [ 
  7.         { 
  8.           type: 'NumberLiteral'
  9.           value: '2'
  10.         }, 
  11.         { 
  12.           type: 'CallExpression'
  13.           name'subtract'
  14.           params: [ 
  15.             { 
  16.               type: 'NumberLiteral'
  17.               value: '4'
  18.             }, 
  19.             { 
  20.               type: 'NumberLiteral'
  21.               value: '2'
  22.             } 
  23.           ] 
  24.         } 
  25.       ] 
  26.     } 
  27.   ] 

2.2 代碼轉換(Transform)

代碼轉換的過程是將傳入的AST結構,通過在AST上例如增、刪、改屬性,將傳入AST轉換為C語言需要的標準AST結構。

為了實現轉換,我們增加了一個 traverser(ast, visitor) 函數,這個函數接收parse過程得到的AST和visitor規則轉換對象。

visitor對象實際可理解為轉換規則,traverser函數在遍歷AST結構時,會根據visitor中定義的規則執行轉換,用于生成新的符合C語言描述標準的AST結構。

最后通過 transform(ast)(預處理,定義visitor對象) -> traverser(ast, visitor) 過程,得到一個新的AST結構:

  1.   type: 'Program'
  2.   body: [ 
  3.     { 
  4.       type: 'ExpressionStatement'
  5.       expression: { 
  6.         type: 'CallExpression'
  7.         callee: { 
  8.           type: 'Identifier'
  9.           name'add' 
  10.         }, 
  11.         arguments: [ 
  12.           { 
  13.             type: 'NumberLiteral'
  14.             value: '2' 
  15.           }, 
  16.           { 
  17.             type: 'CallExpression'
  18.             callee: { 
  19.               type: 'Identifier'
  20.               name'subtract' 
  21.             }, 
  22.             arguments: [ 
  23.               { 
  24.               type: 'NumberLiteral'
  25.               value: '4' 
  26.             }, 
  27.             { 
  28.               type: 'NumberLiteral'
  29.               value: '2' 
  30.             } 
  31.           ] 
  32.         } 
  33.       } 
  34.     } 
  35.   ] 

2.3 生成目標代碼(Code Generate)

最后通過解析符合C語言標準的AST,根據C語言的語法規則,轉換成為C語言格式

codeGenerator(newAst) 函數如下,接收新生成的AST結構:

  1. function codeGenerator(newAst) { 
  2.   switch (newAst.type) { 
  3.     case "Program"
  4.       return newAst.body.map(codeGenerator).join("\n"); 
  5.     case "ExpressionStatement"
  6.       return codeGenerator(newAst.expression) + ";"
  7.     case "CallExpression"
  8.       return ( 
  9.         codeGenerator(newAst.callee) + 
  10.         "(" + 
  11.         newAst.arguments.map(codeGenerator).join(", ") + 
  12.         ")" 
  13.       ); 
  14.     case "Identifier"
  15.       return newAst.name
  16.     case "NumberLiteral"
  17.       return newAst.value; 
  18.     case "StringLiteral"
  19.       return '"' + newAst.value + '"'
  20.     default
  21.       throw new TypeError(newAst.type); 
  22.   } 

同時還做了代碼的部分格式化,比如空格、換行符添加等。

此時自然會思考下,VScode編輯器中的Prettier代碼格式化插件是不是也是這么做的?

四、總結

推薦大家完整閱讀一下“The Super Tiny Compiler”開源項目,作者寫的代碼注釋也非常詳細。編譯(轉譯)的過程原理基本類似,還有很多優秀的項目,比如codeMirror、babel、esprima、acorn、recast都是值得閱讀的源碼,喜歡的小伙伴一定要去瞅瞅。

Reference

  • 《Babel Docs》- https://babeljs.io/docs/en/
  • 《the super tiny complier》- https://github.com/jamiebuilds/the-super-tiny-compiler/

 

責任編輯:姜華 來源: DYBOY
相關推薦

2016-11-08 18:53:08

編譯器

2020-08-26 09:05:03

函數編譯詞法

2020-11-30 06:20:13

javascript

2022-03-28 10:25:27

前端文件編譯器

2021-12-30 11:26:31

語言編譯器腳本

2014-04-14 15:54:00

print()Web服務器

2016-06-15 09:28:09

新型編譯器JavaScript類型

2020-10-16 08:26:07

JavaScript開發技術

2022-06-02 16:46:25

京東APP升級Android升級AGP

2021-04-08 13:54:52

LinuxIBM編譯器

2020-06-04 12:55:44

PyTorch分類器神經網絡

2012-07-18 11:31:50

ibmdw

2013-06-13 10:02:36

JavaScriptJavaScript編

2014-05-04 12:51:21

Javascript編譯器

2022-10-21 14:21:46

JavaScript筆記技能

2010-01-27 16:39:48

C++編譯器

2021-06-08 07:48:26

lambda表達式編譯器

2018-12-04 13:30:28

Javascript編譯原理前端

2020-01-10 18:04:01

Python編程語言Windows

2020-06-11 08:48:49

JavaScript開發技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕乱码一区二区三区 | 日韩无| 五月婷亚洲 | 欧美一区2区三区4区公司二百 | 一区二区影院 | 国产精品成人av | 国产午夜av片 | 欧美日韩综合视频 | 老司机深夜福利网站 | 韩国久久精品 | 99久久婷婷国产综合精品电影 | 三级视频久久 | 美女视频黄的免费 | 成人欧美一区二区三区在线观看 | 亚洲成人免费观看 | 九九热精品在线 | 国产精品久久久久久福利一牛影视 | 免费在线一区二区三区 | 久久久久久国产精品久久 | 操操日 | 亚洲天堂色 | 久久国产精品一区二区 | 国产ts一区 | 97av视频| 人妖一区 | 日韩 欧美 综合 | 在线āv视频 | 欧美精品在线播放 | 一区二区国产精品 | 国产精品a免费一区久久电影 | 久久久久久久久久久成人 | 亚洲婷婷六月天 | 一区在线观看 | 另类a v| 日韩黄色av | 国产高清在线精品 | 欧美jizzhd精品欧美巨大免费 | 欧美日在线 | 国产精品乱码一区二区三区 | 久久久久久免费免费 | 亚洲网站观看 |