编译器是怎么工作的 —— 代码生成

前两篇博客已经把源代码分析和分析结果转换的这两个过程写完了,还剩下最后一个过程 —— 新代码的生成。

新代码的生成

codeGenerator.js

export default function codeGenerator(node) {
  switch (node.type) {
    case 'Program':
      return node.body.map(codeGenerator)
        .join('\n');
    case 'ExpressionStatement':
      return (
        codeGenerator(node.expression) +
        ';'
      );
    case 'CallExpression':
      return (
        codeGenerator(node.callee) +
        '(' +
        node.arguments.map(codeGenerator)
          .join(', ') +
        ')'
      );
    case 'Identifier':
      return node.name;
    case 'NumberLiteral':
      return node.value;
    case 'StringLiteral':
      return '"' + node.value + '"';
    default:
      throw new TypeError(node.type);
  }
}

test.js

import tokenizer from './tokenizer'
import parser from './parser'
import transformer from './transformer'
import codeGenerator from './codeGenerator'

const tokenizer_res = tokenizer('(add 2 (subtract 4 2))')
const parser_res = parser(tokenizer_res)
const transformer_res = transformer(parser_res)
const codeGenerator_res = codeGenerator(transformer_res)
console.log(codeGenerator_res)

// add(2, subtract(4, 2));

这一步就是将 transformer 输出的新 AST 处理并生成 JS 代码字符串的过程。

具体来说,switch 语句根据传给 codeGenerator 的节点对象(node)的 type 属性来决定采用哪种处理方式:

  • 如果 typeProgram,将节点对象的 body 属性进行 map,处理函数为 codeGenerator,实际上是将 body 中的元素一一递归,返回了数组后,元素间进行换行,但该例中 body 只有一个元素不会换行。最终将输出的字符串返回。

  • 如果 typeExpressionStatement,那么将节点对象的 expression 属性交给 codeGenerator 进行递归,并将返回的结果加上分号之后一并返回。

  • 如果 typeCallExpression,那么返回的字符串是这样的,将节点对象的 callee 属性交给 codeGenerator 递归,递归的结果拼上左括号,再拼上 node.arguments.map(codeGenerator).join(', ')(这类似于 typeProgram 时的处理方式,只是这时要 map 的数组是 arguments,产生的数组元素间加上逗号和空格),最后再拼上右括号,完成之后将结果返回。

  • 如果 typeIdentifier,返回节点对象的 name 属性。

  • 如果 typeNumberLiteral,返回节点对象的 value 属性。

  • 如果 typeStringLiteral,节点对象的 value 属性加上双引号之后返回,但该例中不存在 StringLiteral

  • 如果都不是,抛出一个错误。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,099评论 1 45
  • 最近一朋友去了趟美西,跟我讲了一个比较尴尬的事,她住的酒店没有热水壶,所以直接喝了水龙头的热水。。。。她朋友一脸严...
    至美旅行阅读 12,182评论 0 2
  • ▲形容词这些五颜六色终归要消褪荒诞夸张或讽刺的句子都如水漂般沉入湖底涟漪是唯一存在过的证据湖面破碎一个人在涌动他激...
    草夫阅读 277评论 1 0
  • 再多的怦然心动 也抗衡不了性格不对的互相折磨 抵不住天长地久的消耗 最终还是要和对的人在一起过 才不枉此生 就是...
    卢娅欣阅读 132评论 0 0
  • 以前写过很多博客,但都是给自己看的,是一些知识总结和生活感受。现在,要写一个给别人看的博客,希望读者能通过阅读获得...
    孙和David阅读 237评论 0 0