我想为算术方程式和变量赋值设计一个LL1语法。我从这种语法开始:
我对算术表达式有一个明确的语法:
db.posts.aggregate([
{
$sort: { date: -1 }
},
{
$limit: 8
},
{
$lookup: {
from: "comments",
let: { postId: "$_id" },
pipeline: [
{ $match: { $expr: { $eq: [ "$$postId", "$post_id" ] } } },
{ $sort: { date: -1 } },
{ $limit: 2 }
],
as: "comments"
}
}
])
但是,我不确定如何将变量分配合并到E作品中。
我以前的尝试方式是:
E → T E’
E’ → | + E
T → id T’
T’ → | * T
答案 0 :(得分:1)
assignment -> ID ASSIGN expr | expr
(我忽略了typ
部分,因为我认为它是偶然到达的)
这里的问题是ID ASSIGN expr
和expr
都可以以ID
开头(或者如果T
包含ID
作为选项,至少可以这样) ,我以为是这样),所以这不是LL(1)。不过它是LL(2),因此,如果您对此感到满意,则可以在解析器的andalso next_token = ASSIGN
条件中添加一个if
并完成该操作。
如果您确实需要将其设为LL(1),恐怕必须调整解析器允许的语言(也就是说,没有LL(1)语法完全匹配相同的语言)作为您当前的语法)。一种简单的解决方法是在分配之前简单地添加一个SET
之类的关键字,尽管这很丑陋。
另一种选择是允许任意表达式作为=
的左操作数,从而指定分配规则:
assignment -> exp (ASSIGN exp)?
哪个是LL(1)。这样做的缺点是,它允许使用许多无意义的代码,例如1+2 := 42
,但是您可以在语法之外进行修复。也就是说,您用于解析分配的代码可以简单地调用parse_exp
,然后,如果下一个标记是ASSIGN
,并且parse_exp
返回的表达式不仅仅是一个标识符,则会引发错误,作业的左侧必须是标识符。