LL1语法用于算术表达式和赋值

时间:2018-11-09 22:18:33

标签: parsing ocaml grammar ambiguous-grammar

我想为算术方程式和变量赋值设计一个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

1 个答案:

答案 0 :(得分:1)

assignment -> ID ASSIGN expr | expr

(我忽略了typ部分,因为我认为它是偶然到达的)

这里的问题是ID ASSIGN exprexpr都可以以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返回的表达式不仅仅是一个标识符,则会引发错误,作业的左侧必须是标识符。