Exa*_*gon 11 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%",", ">"]
Run Code Online (Sandbox Code Playgroud)
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_;
};
Run Code Online (Sandbox Code Playgroud)
我有一个关于我目前在这里尝试的实例,它不起作用,我也尝试改变变体解析器的顺序,它没有帮助,我得到无尽的回忆,或者没有我期望(或希望)的行为.任何人都可以帮我调试这个解析器吗?我想我在解析器中有一些类型的左递归,是否有机会避免这种情况,或者没有机会重写语法?这个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
Run Code Online (Sandbox Code Playgroud)
但是现在有下一个问题,我怎样才能使boost精神x3将这些规则解析为给定的结构?我无法想象现在返回A的one_arg_lambda是什么或者解析器,one_arg_lambda解析器应该解析为一个LambdaType结构,但是根据A解析为什么现在不是必需的.所以问题是现在,我怎样才能得到一个非左递归解析器,它使用boost-spirit-x3将上面的语法解析为我的结构?
编辑二:
我想=>是正确联想所以foo => bar => baz => baham
意味着foo => (bar => (baz => bahama))
我解决了这个问题,而且解决方案非常简单。诀窍是改变语法,所以我没有左递归,并且它很好地解析到我的结构中。
所以我改变了
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%",", ">"]
Run Code Online (Sandbox Code Playgroud)
到
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%",", ">"]
Run Code Online (Sandbox Code Playgroud)
第二个语法描述了完全相同的语言,但没有左递归,并且没有改变语法的结构。这实际上是运气,显然并不适用于所有语法。