如何使用PEG.js为左关联运算符构建 AST(抽象语法树)?
我试图根据我在互联网上找到的信息编写一些代码,但我似乎犯了一个错误。
我编写的代码为大多数表达式生成了不正确的 AST。
表达
12-6-4-2*1-1
预期 AST
{
"left": {
"left": {
"left": {
"left": 12,
"operator": "-",
"right": 6
},
"operator": "-",
"right": 4
},
"operator": "-",
"right": {
"left": 2,
"operator": "*",
"right": 1
}
},
"operator": "-",
"right": 1
}
生成的 AST
{
"left": {
"left": {
"left": 12,
"operator": "-",
"right": 6
},
"operator": "-",
"right": 4
},
"operator": "-",
"right": {
"left": 2,
"operator": "*",
"right": {
"left": 1,
"operator": "-",
"right": 1
}
}
}
代码
{
function operator(first, rest) {
if (rest.length === 0) return first;
return { left: first, right: rest };
};
function makeOperator(left, operator, right) {
return { left: left, operator: operator[0], right: clean(right[1]) };
};
function clean(expression) {
if (!expression.right) return expression;
var result = makeOperator(expression.left, expression.right[0], expression.right[0]);
for (var counter = 1, len = expression.right.length; counter < len; counter++) {
result = makeOperator(result, expression.right[counter], expression.right[counter]);
}
return result;
};
}
Start = E
E
= expression:E1
{ return clean(expression); }
E1
= expression:E2 rest:(("+" / "-") E2)*
{ return operator(expression, rest); }
E2
= expression:Value rest:(("*" / "/") E1)*
{ return operator(expression, rest); }
Value
= Number
/ BracketedExpression
Number
= [1-9][0-9]*
{ return parseInt(text(), 10); }
BracketedExpression
= "(" expression:E1 ")"
{ return expression; }
我非常感谢任何有关如何为左关联和右关联运算符构建 AST 的帮助或示例代码。
编辑:正如@Bergi 指出的那样,问题在于E2
用作E1
运算符列表其余部分的表达式而不是Value
. 但是,Bergi 写的代码比我的要简单得多。