简体   繁体   English

Sprache:语法中的左递归

[英]Sprache: left recursion in grammar

I am developing a parser for a language similar to SQL and I have the problem of creating some of the rules of language, such as: expression IS NULL and expression IN (expression1, expression2, ...) with priority between logical and mathematical operators. 我正在为类似于SQL的语言开发解析器,我遇到了创建一些语言规则的问题,例如: expression IS NULLexpression IN (expression1, expression2, ...) ,逻辑和数学运算符之间具有优先级。

I uploaded a GitHub test project https://github.com/anpv/SpracheTest/ but this variant is not good. 我上传了一个GitHub测试项目https://github.com/anpv/SpracheTest/,但这个变种并不好。
I tried to use the following rules: 我试图使用以下规则:

private static readonly Parser<AstNode> InOperator =
    from expr in Parse.Ref(() => Expression)
    from inKeyword in Parse.IgnoreCase("in").Token()
    from values in Parse
        .Ref(() => Expression)
        .DelimitedBy(Comma)
        .Contained(OpenParenthesis, CloseParenthesis)
    select new InOperator(expr, values);

private static readonly Parser<AstNode> IsNullOperator =
    from expr in Parse.Ref(() => Expression)
    from isNullKeyword in Parse
         .IgnoreCase("is")
         .Then(_ => Parse.WhiteSpace.AtLeastOnce())
         .Then(_ => Parse.IgnoreCase("null"))
    select new IsNullOperator(expr);

private static readonly Parser<AstNode> Equality =
    Parse
        .ChainOperator(Eq, IsNullOperator.Or(InOperator).Or(Additive), MakeBinary);

which throws ParseException in code like ScriptParser.ParseExpression("1 is null") or ScriptParser.ParseExpression("1 in (1, 2, 3)"): "Parsing failure: Left recursion in the grammar." 它在代码中抛出ParseException ,如ScriptParser.ParseExpression("1 is null")ScriptParser.ParseExpression("1 in (1, 2, 3)"): "Parsing failure: Left recursion in the grammar." .

How can I look-ahead for Expression, or do other variants exist to solve this problem? 我怎样才能预测Expression,或者是否存在其他变体来解决这个问题?

The answer is, unfortunately, the Sprache cannot parse a left-recursive grammar. 答案是,不幸的是,Sprache无法解析左递归语法。 I stumbled on comments in the source code talking about how buggy support for left-recursive grammars had been removed when researching this question (which was also how I found your question) - see the source code . 我偶然发现源代码中的评论,讨论了在研究这个问题时我是如何删除对左递归语法的错误支持(这也是我如何找到你的问题) - 请参阅源代码

In order to deal with this problem you need to reorganize how you do your parsing. 为了解决这个问题,您需要重新组织解析方式。 If you are writing a simple expression parser, for example, this is a common problem you have to deal with. 例如,如果您正在编写一个简单的表达式解析器,那么这是您必须处理的常见问题。 Searching the web there is lots of discussion of how to remove left-recursion from a grammar, in particular, for expressions. 在网上搜索有很多关于如何从语法中删除左递归的讨论,特别是对于表达式。

In your case, I expect you'll need to do something like: 在你的情况下,我希望你需要做类似的事情:

term := everything simple in an expression (like "1", "2", "3", etc.)
expression := term [ IN ( expression*) | IS NULL | "+" expression | "-" expression | etc.]

or similar - basically - you have to unwind the recursion yourself. 或类似 - 基本上 - 你必须自己解除递归。 By doing that I was able to fix my issues with expressions. 通过这样做,我能够解决表达式问题。 I suspect any basic compiler book probably has a section on how to "normalize" a grammar. 我怀疑任何基本的编译器书可能都有关于如何“规范化”语法的部分。

It makes building whatever object you are returning from the parser a bit more of a pain, but in the select statement instead of doing "select new Expression(arg1, arg2)" I changed it to be a function call, and the function decides on the specific object being returned depending on what the arguments were. 它使你从解析器返回的任何对象构建更多的痛苦,但是在select语句中而不是“选择新的表达式(arg1,arg2)”我将其更改为函数调用,并且函数决定根据参数的内容返回特定对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM