在精神x3的解析器规则中终止左递归

时间:2016-10-09 23:15:38

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

我目前仍然坚持使用boost spirit x3解析的规则。 这是te 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%",", ">"]

usng boost spirit x3,我试图解析下面的struct / variant:

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的实例,它不起作用,我也尝试改变变体解析器的顺序,它没有帮助,我得到无尽的回忆,或者没有行为我期待(或希望)。 任何人都可以帮我调试这个解析器吗? 我想我在解析器中有一些类型的左递归,是否有机会避免这种情况,或者没有机会重写语法? 这个gramar甚至可以用boost spirit x3解析吗?

编辑:

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

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将上面的语法解析为我的结构?

编辑II:

我希望=>是正确的关联,所以foo => bar => baz => baham
表示foo => (bar => (baz => bahama))

1 个答案:

答案 0 :(得分: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%",", ">"]

这第二个语法描述了exaclty相同的语言,但没有左递归,也没有改变语法的结构。 这实际上是运气,并且显然对每种语法都不起作用。