使用boost spirit x3解析为递归变体的问题

时间:2016-10-09 20:18:46

标签: c++ parsing boost-spirit 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_;
};

如果我尝试解析一个Type或其中一个结构,我收到一个编译错误,告诉我我无法将const boost::spirit::x3::char_class分配给Type, 我很困惑,因为我不想分配const boost::spirit::x3::char_class。 我有一个实例here,当你尝试编译它时,它有一个解析器并显示问题和错误。 我试图解决这个问题一整天,现在我不知道为什么这不起作用。 如果对此有任何帮助,我将非常感谢。

1 个答案:

答案 0 :(得分:3)

您将ax.colorbar(im, fraction=0.046, pad=0.04) 作为最后一个参数传递给x3::space,因此它会将其绑定到解析器的属性。

当然你不想那样。

如果您想传递队长,请使用x3::parse

PS 正如编写的解析器还有一个问题:它在类型/ lambdaType中有左递归。我认为这是因为您删除了标识符解析(x3::phrase_parse),所以如果您将输入修改为x3::string("foo"),则此处为:

<强> Live On Coliru

(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);
}