从JSON解析器到Babel插件:前端工程师也能玩转语法制导翻译
当我们编写一个JSON.parse()的polyfill时,其实已经在不自觉地实践编译原理中最精妙的思想之一——语法制导翻译(Syntax-Directed Translation)。这种看似高深的理论,早已渗透在前端日常开发的各个角落。本文将带你用熟悉的JavaScript场景,重新发现那些被忽视的编译原理智慧。
1. 从JSON解析看属性计算的艺术
想象你正在实现一个简易JSON解析器。当遇到字符串 {"name": "Alice", "age": 25} 时,程序需要逐步构建出对应的JavaScript对象。这个过程完美诠释了**语法制导定义(SDD)**的核心思想。
1.1 解析器中的属性流动
考虑这个简化版的JSON文法规则:
javascript复制Object → "{" PairList "}"
PairList → Pair | Pair "," PairList
Pair → String ":" Value
在实现时,我们会自然地为每个语法单元附加属性:
javascript复制// 综合属性示例:自底向上传递值
function parseValue(token) {
if (token.type === 'NUMBER') {
const node = { type: 'Number', value: parseFloat(token.value) }
node.eval = () => node.value // 综合属性
return node
}
}
关键对比:
- 继承属性:类似函数参数传递(如当前作用域信息)
- 综合属性:类似函数返回值(如解析完成的AST节点)
1.2 实战:带类型检查的JSON扩展
假设我们要增强JSON解析器,支持类型注释(如 /* number */ 42)。这时需要混合使用两种属性:
javascript复制function parseTypedValue(tokenStream) {
const typeComment = lookAheadForComment()
const valueNode
