问题描述
我还有一个关于 How to extend default PEG.js arithmetic example to allow multiple expressions not single one?
的问题我有这个语法:
start = code:statements {
return {
"type": "Program","body": code
};
}
statements = head:(if / expression_statement) tail:(_ (if / expression_statement))* {
return [head].concat(tail.map(function(element) {
return element[1];
}));
}
expression_statement = expression:expression {
return {
"type": "ExpressionStatement","expression": expression
};
}
if = "if" _ expression:(comparison / expression) _ "then" body:(statements / _) "end" {
return {
"type": "IfStatement","test": expression,"consequent": {
"type": "BlockStatement","body": body
},"alternate": null
};
}
expression = expression:(arithmetic / literal) { return expression; }
literal = value:(string / Integer) {
return {"type": "Literal","value": value };
}
variable = variable:name {
return {
"type": "Identifier","name": variable
}
}
name = [A-Z_a-z][A-Z_a-z0-9]* { return text(); }
comparison = _ left:expression _ "==" _ right:expression _ {
return {
"type": "BinaryExpression","operator": "==","left": left,"right": right
};
}
string = "\"" ([^"] / "\\\\\"")* "\"" {
return JSON.parse(text());
}
arithmetic
= head:term tail:(_ ("+" / "-") _ term)* {
return tail.reduce(function(result,element) {
return {
"type": "BinaryExpression","operator": element[1],"left": result,"right": element[3]
};
},head);
}
term
= head:factor tail:(_ ("*" / "/") _ factor)* {
return tail.reduce(function(result,head);
}
factor
= "(" _ expr:arithmetic _ ")" { return expr; }
/ literal
Integer "integer"
= _ [0-9]+ { return parseInt(text(),10); }
_ "whitespace"
= [ \t\n\r]* {
return [];
}
解析器用于创建 JavaScript AST(使用 esprima 对象结构)。
我试图解析 ruby 之类的 if
语句:
这很好用,它创建了空的 if
:
if "foo" == "bar" then
end
但这无法解析:
if "foo" == "bar" then
10 + 10
end
它因错误而失败:
Parse Error: Expected "(","*","+","-","/","\"","if",or integer but "e" found.
Error in line 3
end
^
我还希望它可以处理多行:
if "foo" == "bar" then
10 + 10
10 * 10
end
我认为我应该在前面输入“end”,但我不确定在哪里。
编辑:我正在尝试这个:
statements = head:(if / expression_statement) tail:(_ &"end" / (if / expression_statement)*) {
return [head].concat(tail.map(function(element) {
if (element) {
return element[2];
}
}).filter(Boolean));
}
但它不适用于两个表达式行,如果我在最后使用 *
tail:(_ &"end" / (if / expression_statement))*
我遇到了无限循环解析器错误。我也尝试了 &"end" 的多种组合,但它们不起作用。我也在 GitHub pegjs/pegjs#57 上发现了这个问题,但它没有任何帮助。
解决方法
我已经用这段代码解决了这个问题:
statements = head:(if / expression_statement) tail:( (!"end" _ (if / expression_statement) .)*) {
return [head].concat(tail.map(function(element) {
if (element) {
return element[2];
}
}).filter(Boolean));
}