使用 boost spirit x3 解析为递归变体的问题
problems parsing into recursive variant using boost spirit x3
我目前正在尝试使用 boost spirit x3 解析为 x3::variant
。
变体看起来像:
typedef x3::variant<
nil,
x3::forward_ast<LambdaType>,
x3::forward_ast<ClassType>
> Type
LambdaType 和 ClassType 看起来像:
struct LambdaType {
std::vector<Type> parameters_;
Type return_type_;
};
struct ClassType{
std::vector<std::string> name_;
std::vector<Type> template_args_;
};
如果我尝试解析为类型或这些结构之一,我会收到编译器错误,它告诉我无法将 const boost::spirit::x3::char_class
分配给 Type
,
我对此感到困惑,因为我不想分配 const boost::spirit::x3::char_class
。
我有一个实例 here,它有一个解析器并在您尝试编译它时显示问题和错误。
我一整天都在尝试解决这个问题,现在我不知道为什么这不起作用。
如有任何帮助,我将不胜感激。
您将 x3::space
作为最后一个参数传递给 x3::parse
,因此它会将其绑定到解析器的属性。
你当然不想那样。
如果您想通过船长,请使用 x3::phrase_parse
。
PS 如您所写,您的解析器还有一个问题:它在 type/lambdaType 中有左递归。我认为这是因为您删除了标识符解析 (x3::string("foo")
) 所以如果您将输入固定为 (foo, foo) => foo
:
#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace x3 = boost::spirit::x3;
namespace ast{
struct LambdaType;
struct ClassType;
struct nil{};
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_;
};
}
BOOST_FUSION_ADAPT_STRUCT(ast::LambdaType, parameters_, return_type_)
BOOST_FUSION_ADAPT_STRUCT(ast::ClassType, name_, template_args_)
namespace parser{
typedef x3::rule<struct lambda_type_class, ast::LambdaType> lambda_type_type;
typedef x3::rule<struct class_type_class, ast::ClassType> class_type_type;
typedef x3::rule<struct type_class, ast::Type> type_type;
const class_type_type class_type = "class_type";
const lambda_type_type lambda_type = "lambda_type";
const type_type type_p = "type";
auto const type_p_def = class_type | lambda_type;
auto const lambda_type_def =
("(" >> -(type_p%",") >> ")" >> "=>" >> type_p)
| (x3::repeat(1)[type_p%","] >> "=>" >> type_p)
;
auto const class_type_def =
(x3::string("foo")%"::") >> -("<" >> type_p%"," >> ">")
;
BOOST_SPIRIT_DEFINE(
lambda_type,
class_type,
type_p
)
}
int main()
{
std::string input = "(foo, foo) => foo";
x3::phrase_parse(input.begin(), input.end(), parser::type_p, x3::space);
}
有调试输出
<type>
<try>(foo, foo) => foo</try>
<class_type>
<try>(foo, foo) => foo</try>
<fail/>
</class_type>
<lambda_type>
<try>(foo, foo) => foo</try>
<type>
<try>foo, foo) => foo</try>
<class_type>
<try>foo, foo) => foo</try>
<success>, foo) => foo</success>
<attributes>[[[f, o, o]], []]</attributes>
</class_type>
<success>, foo) => foo</success>
<attributes></attributes>
</type>
<type>
<try> foo) => foo</try>
<class_type>
<try> foo) => foo</try>
<success>) => foo</success>
<attributes>[[[f, o, o]], []]</attributes>
</class_type>
<success>) => foo</success>
<attributes></attributes>
</type>
<type>
<try> foo</try>
<class_type>
<try> foo</try>
<success></success>
</class_type>
<success></success>
</type>
<success></success>
</lambda_type>
<success></success>
</type>
我目前正在尝试使用 boost spirit x3 解析为 x3::variant
。
变体看起来像:
typedef x3::variant<
nil,
x3::forward_ast<LambdaType>,
x3::forward_ast<ClassType>
> Type
LambdaType 和 ClassType 看起来像:
struct LambdaType {
std::vector<Type> parameters_;
Type return_type_;
};
struct ClassType{
std::vector<std::string> name_;
std::vector<Type> template_args_;
};
如果我尝试解析为类型或这些结构之一,我会收到编译器错误,它告诉我无法将 const boost::spirit::x3::char_class
分配给 Type
,
我对此感到困惑,因为我不想分配 const boost::spirit::x3::char_class
。
我有一个实例 here,它有一个解析器并在您尝试编译它时显示问题和错误。
我一整天都在尝试解决这个问题,现在我不知道为什么这不起作用。
如有任何帮助,我将不胜感激。
您将 x3::space
作为最后一个参数传递给 x3::parse
,因此它会将其绑定到解析器的属性。
你当然不想那样。
如果您想通过船长,请使用 x3::phrase_parse
。
PS 如您所写,您的解析器还有一个问题:它在 type/lambdaType 中有左递归。我认为这是因为您删除了标识符解析 (x3::string("foo")
) 所以如果您将输入固定为 (foo, foo) => foo
:
#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace x3 = boost::spirit::x3;
namespace ast{
struct LambdaType;
struct ClassType;
struct nil{};
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_;
};
}
BOOST_FUSION_ADAPT_STRUCT(ast::LambdaType, parameters_, return_type_)
BOOST_FUSION_ADAPT_STRUCT(ast::ClassType, name_, template_args_)
namespace parser{
typedef x3::rule<struct lambda_type_class, ast::LambdaType> lambda_type_type;
typedef x3::rule<struct class_type_class, ast::ClassType> class_type_type;
typedef x3::rule<struct type_class, ast::Type> type_type;
const class_type_type class_type = "class_type";
const lambda_type_type lambda_type = "lambda_type";
const type_type type_p = "type";
auto const type_p_def = class_type | lambda_type;
auto const lambda_type_def =
("(" >> -(type_p%",") >> ")" >> "=>" >> type_p)
| (x3::repeat(1)[type_p%","] >> "=>" >> type_p)
;
auto const class_type_def =
(x3::string("foo")%"::") >> -("<" >> type_p%"," >> ">")
;
BOOST_SPIRIT_DEFINE(
lambda_type,
class_type,
type_p
)
}
int main()
{
std::string input = "(foo, foo) => foo";
x3::phrase_parse(input.begin(), input.end(), parser::type_p, x3::space);
}
有调试输出
<type>
<try>(foo, foo) => foo</try>
<class_type>
<try>(foo, foo) => foo</try>
<fail/>
</class_type>
<lambda_type>
<try>(foo, foo) => foo</try>
<type>
<try>foo, foo) => foo</try>
<class_type>
<try>foo, foo) => foo</try>
<success>, foo) => foo</success>
<attributes>[[[f, o, o]], []]</attributes>
</class_type>
<success>, foo) => foo</success>
<attributes></attributes>
</type>
<type>
<try> foo) => foo</try>
<class_type>
<try> foo) => foo</try>
<success>) => foo</success>
<attributes>[[[f, o, o]], []]</attributes>
</class_type>
<success>) => foo</success>
<attributes></attributes>
</type>
<type>
<try> foo</try>
<class_type>
<try> foo</try>
<success></success>
</class_type>
<success></success>
</type>
<success></success>
</lambda_type>
<success></success>
</type>