проблемы с разбором рекурсивного варианта с использованием boost spirit x3

В настоящее время я пытаюсь разобрать x3::variant, используя Boost Spirit x3. вариант выглядит так:

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. У меня есть живой пример здесь, который имеет парсер и показывает проблему и ошибку, когда вы пытаетесь его скомпилировать. Я пытаюсь решить эту проблему в течение всего дня, и сейчас я нахожусь в такой ситуации, когда понятия не имею, почему это не работает. За любую помощь в этом я был бы более чем благодарен.


person Exagon    schedule 09.10.2016    source источник


Ответы (1)


Вы передаете x3::space в качестве последнего аргумента x3::parse, поэтому он привязывает его к атрибуту анализатора.

Конечно, ты этого не хотел.

Используйте x3::phrase_parse, если вы хотите обойти шкипера.

PS Как написано, у вашего парсера есть дополнительная проблема: у него есть левая рекурсия в type/lambdaType. Я думаю, это потому, что вы заглушили синтаксический анализ идентификатора (x3::string("foo")), так что вот, если вы исправите ввод как (foo, foo) => foo:

Жить на Coliru

#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>
person sehe    schedule 09.10.2016
comment
Добавлены дополнительные подсказки и живой пример - person sehe; 09.10.2016
comment
это шутка, не так ли :(, я чувствую себя таким глупым прямо сейчас, я отлаживал последние 3 часа без какого-либо успеха. Большое спасибо за то, что открыли мне глаза - person Exagon; 09.10.2016
comment
Я также распознал левую рекурсию, вот мой вопрос об этом, Я никогда раньше не сталкивался с этой проблемой, и я изо всех сил пытаюсь избежать левой рекурсии. - person Exagon; 10.10.2016