美文网首页Web 前端开发
编译器是怎么工作的 —— 代码生成

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

作者: 边城少年_ | 来源:发表于2018-12-10 21:19 被阅读0次

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

新代码的生成

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

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

相关文章

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

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

  • 编译器的工作过程

    编译器的工作过程划分为:词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成。 词法分析器的任务是把...

  • Mac下的Java:生成.java文件和.class文件

    生成.java文件 1:打开文本编译器 文本编译器打开是这个样子滴: 2:写入java代码 生成.class文件 ...

  • 探索C#之6.0语法糖剖析

    自动属性默认初始化 使用方法: 编译器生成代码: 从生成代码中可以看出编译器是在实例化构造函数时,初始化属性信息的...

  • c++:模板

    编译器会根据代码自动生成函数。

  • 编译器前端和后端

    编译器粗略分为词法分析,语法分析,类型检查,中间代码生成,代码优化,目标代码生成,目标代码优化。把中间代码生成及之...

  • 编译原理——寄存器

    •代码生成是编译器的最后阶段。代码生成器通过前端产生的中间表示法或者通过代码优化器在代码优化阶段,映射到目标程序中...

  • Flutter 前端编译器编译流程分析

    1. 前端编译器和后端编译器的区别 编译流程粗略分为词法分析、语法分析、类型检查、中间代码生成、代码优化、目标代码...

  • TypeScript Downleveling - 什么是 Ty

    下列 TypeScript 代码: 使用 tsc 编译器编译之后生成的 JavaScript 代码: 为什么字符串...

  • 知识点OC文件生成C++文件

    生成 使用clang编译器将Objective-C代码编译成C语言代码, 并生成在一个.cpp的 C++文件中: ...

网友评论

    本文标题:编译器是怎么工作的 —— 代码生成

    本文链接:https://www.haomeiwen.com/subject/bitjhqtx.html