前兩篇博客已經(jīng)把源代碼分析和分析結(jié)果轉(zhuǎn)換的這兩個(gè)過(guò)程寫(xiě)完了精堕,還剩下最后一個(gè)過(guò)程 —— 新代碼的生成基跑。
新代碼的生成
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 代碼字符串的過(guò)程。
具體來(lái)說(shuō)锡宋,switch
語(yǔ)句根據(jù)傳給 codeGenerator
的節(jié)點(diǎn)對(duì)象(node
)的 type
屬性來(lái)決定采用哪種處理方式:
如果
type
為Program
儡湾,將節(jié)點(diǎn)對(duì)象的body
屬性進(jìn)行map
,處理函數(shù)為codeGenerator
执俩,實(shí)際上是將body
中的元素一一遞歸徐钠,返回了數(shù)組后,元素間進(jìn)行換行役首,但該例中body
只有一個(gè)元素不會(huì)換行尝丐。最終將輸出的字符串返回。如果
type
為ExpressionStatement
衡奥,那么將節(jié)點(diǎn)對(duì)象的expression
屬性交給codeGenerator
進(jìn)行遞歸爹袁,并將返回的結(jié)果加上分號(hào)之后一并返回。如果
type
為CallExpression
杰赛,那么返回的字符串是這樣的,將節(jié)點(diǎn)對(duì)象的callee
屬性交給codeGenerator
遞歸矮台,遞歸的結(jié)果拼上左括號(hào)乏屯,再拼上node.arguments.map(codeGenerator).join(', ')
(這類(lèi)似于type
為Program
時(shí)的處理方式,只是這時(shí)要map
的數(shù)組是arguments
瘦赫,產(chǎn)生的數(shù)組元素間加上逗號(hào)和空格)辰晕,最后再拼上右括號(hào),完成之后將結(jié)果返回确虱。如果
type
為Identifier
含友,返回節(jié)點(diǎn)對(duì)象的name
屬性。如果
type
為NumberLiteral
校辩,返回節(jié)點(diǎn)對(duì)象的value
屬性窘问。如果
type
為StringLiteral
,節(jié)點(diǎn)對(duì)象的value
屬性加上雙引號(hào)之后返回宜咒,但該例中不存在StringLiteral
惠赫。如果都不是,拋出一個(gè)錯(cuò)誤故黑。