构建AST
1. 先用BNF定义3个语法
运算表达式 <Expression> ::= <AddExpression><EOF> 加法表达式 <AddExpression> ::= <MultipleExpression> | <AddExpression><+><MultiplicativeExpression> | <AddExpression><-><MultiplicativeExpression> 乘法表达式 <MultipleExpression> ::= <Number> | <MultipleExpression><*><Number> | <MultipleExpression></><Number>
2.按照定义的语法来编写解析函数
function expression(source) { // source[0]位置尽可能多地聚合出一个AddExpression addExpression(source) // 符合Expression语法定义 if (source[0].type === 'AddExpression' && source[1] && source[1].type === 'EOF') { let node = { type: "Expression", children: [source.shift(), source.shift()] } source.unshift(node) } // 出口,如果第0项不是Expression,则是抽象语法树解析错误 if (source[0].type === 'Expression') { return source[0] } else { throw new Error('解析AST不正确') } } function addExpression(source) { // MultipleExpression --> AddExpression if (source[0].type === 'MultipleExpression') { let node = { type: "AddExpression", children: [source[0]] } source.shift(); source.unshift(node) // 继续递归,寻求合并 return addExpression(source); } // AddExpression聚合 if (source[0].type === 'AddExpression' && source[1] && (source[1].type === '+' || source[1].type === '-')) { let node = { type: "AddExpression", children: [source.shift(), source.shift()] } multipleExpression(source) node.children.push(source.shift()) source.unshift(node) // 继续递归,寻求合并 return addExpression(source); } // source[0]位置尽可能多地聚合出一个MultipleExpression multipleExpression(source) // 递归出口,如果第0项不是AddExpression,则一直递归自己 if (source[0].type === 'AddExpression') { return source } // 递归自己 return addExpression(source) } function multipleExpression(source) { // number --> MultipleExpression if (source[0].type === 'number') { let node = { type: "MultipleExpression", children: [source[0]] } source.shift(); source.unshift(node) // 继续递归,寻求合并 return multipleExpression(source); } // MultipleExpression聚合 if (source[0].type === 'MultipleExpression' && source[1] && (source[1].type === '*' || source[1].type === '/')) { let node = { type: "MultipleExpression", children: [source.shift(), source.shift()] } node.children.push(source.shift()) source.unshift(node) // 继续递归,寻求合并 return multipleExpression(source); } // 递归出口,如果第0项不是MultipleExpression,则一直递归自己 if (source[0].type === 'MultipleExpression') { return source } }
3.