【问题标题】:Eleminating left recursion in parser rule of spirit x3消除精神 x3 解析器规则中的左递归
【发布时间】:2017-02-18 08:32:36
【问题描述】:

我目前遇到了一个我试图使用 boost spirit x3 解析的规则。 这是我要解析的 EBNF(使用精神中的 % 运算符作为列表):

type ::= class_type | lambda_type

lambda_type ::= more_arg_lambda | one_arg_lambda

more_arg_lambda ::= "(", type%",", ")", "=>", type

one_arg_lambda ::= type, "=>", type  <- here is the left recursion

class_type ::= identifier%"::", ["<", type%",", ">"]

使用 boost spirit x3,我正在尝试解析为以下结构/变体:

typedef x3::variant<
        nil,
        x3::forward_ast<LambdaType>,
        x3::forward_ast<ClassType>
    > Type;

struct LambdaType {
        std::vector<Type> parameters_;
        Type return_type_;
    };
struct ClassType{
        std::vector<std::string> name_; 
        std::vector<Type> template_args_;
    };

我有一个我目前正在尝试here 的活生生的例子,但它不起作用,我还尝试更改变体解析器的顺序,这没有帮助,我得到无尽的递归,或者没有行为我会期望(或希望)。

谁能帮我调试这个解析器?

我认为我在解析器中有某种​​类型的左递归,是否有机会避免这种情况或者没有机会重写语法? 这个语法甚至可以用 boost spirit x3 解析吗?

编辑:

我设法消除了这个语法中的左递归。 现在语法如下:

type ::= class_type | lambda_type

    lambda_type ::= more_arg_lambda | one_arg_lambda

    more_arg_lambda ::= "(", type%",", ")", "=>", type

    one_arg_lambda ::= class_type, "=>" type, A
                       | "(", type%",", ")", "=>", type, "=>", type, A

    class_type ::= identifier%"::", ["<", type%",", ">"]

    A::= "=>", type, A | eps

但是现在有下一个问题,我怎样才能让 boost spirit x3 将这些规则解析到给定的结构中?我无法想象Aone_arg_lambda 解析器现在返回了什么,one_arg_lambda 解析器应该解析成LambdaType 结构,但取决于A 解析成的内容,现在这不是必需的。所以现在的问题是,我怎样才能得到一个非左递归解析器,它使用 boost-spirit-x3 将上面的语法解析到我的结构中?

编辑二:

我希望 =&gt; 具有正确的关联性,所以 foo =&gt; bar =&gt; baz =&gt; baham
表示foo =&gt; (bar =&gt; (baz =&gt; bahama))

【问题讨论】:

  • 你能举一个结构的例子吗?这样更容易正确理解语法。
  • 你想要foo =&gt; bar =&gt; baz 是什么意思? ( foo =&gt; bar ) =&gt; bazfoo =&gt; ( bar =&gt; baz )?
  • 我希望它的意思是foo=&gt;(bar=&gt;baz)
  • This 是我的方法。如果没有其他人写答案(如果你觉得它有用,请随意使用这个例子作为基础)我会在赏金到期时写一个。
  • @jv_ 为什么不???

标签: c++ parsing boost-spirit boost-spirit-x3


【解决方案1】:

我解决了这个问题,而且解决起来非常简单。 诀窍是改变语法,所以我没有左递归,它很好地解析到我的结构中。

所以我改变了

type ::= class_type | lambda_type

lambda_type ::= more_arg_lambda | one_arg_lambda

more_arg_lambda ::= "(", type%",", ")", "=>", type

one_arg_lambda ::= type, "=>", type  <- here is the left recursion

class_type ::= identifier%"::", ["<", type%",", ">"]

type ::= class_type | lambda_type

lambda_type ::= more_arg_lambda | one_arg_lambda

more_arg_lambda ::= "(", type%",", ")", "=>", type

one_arg_lambda ::= class_type, "=>", type  <- here is the magic trick

class_type ::= identifier%"::", ["<", type%",", ">"]

第二个文法描述了完全相同的语言,但没有左递归,也没有改变文法的结构。 这实际上是运气,显然不适用于每种语法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 2022-08-09
    相关资源
    最近更新 更多