boost::spirit::错误:'struct xxx'中没有名为'value_type'的类型

问题描述 投票:0回答:1

我正在尝试我的第一个精神解析器,似乎我遇到了属性传播问题。尝试 plantuml 语法。如果我破解它就该死,如果我不破解就该死......

完整要点在这里:https://coliru.stacked-crooked.com/a/023ec430b509e1be

它的本质,我认为是这样的:

using ast_node =  boost::variant<
    ast_null,
    ast_transition,
    boost::recursive_wrapper<ast_state>,
    boost::recursive_wrapper<ast_region>,
    ast_machine
>;
using ast_nodes_t = std::vector<ast_node>;

struct ast_transition
{
    //std::string _id;
    std::string _fromState;
    std::string _toState;
    std::string _event;
    std::string _guard;
    std::string _effect;
};
BOOST_FUSION_ADAPT_STRUCT(
    ast_transition,
    //(std::string, _id)
    (std::string, _fromState)
    (std::string, _toState)
    (std::string, _event)
    (std::string, _guard)
    (std::string, _effect)
)

struct ast_region
{
    ast_nodes_t _subtree;
};
BOOST_FUSION_ADAPT_STRUCT(
    ast_region,
    (ast_nodes_t, _subtree)
)



   // possible "fix" for "error: no type named 'value_type' in 'struct ast_region'" but causes infinite matching loop on region(s)
   //region = eps >> *transition
   region = *transition
               ;

    bs::qi::rule<ITER, ast_transition(), SKIPPER>    transition;
    bs::qi::rule<ITER, ast_region(), SKIPPER>        region;
    bs::qi::rule<ITER, ast_nodes_t(), SKIPPER>       regions;

这给出了:

/usr/local/include/boost/spirit/home/support/container.hpp:130:12: error: no type named 'value_type' in 'struct ast_region'

任何如何调整容器属性的想法将不胜感激,谢谢!

我试图根据 plantuml 状态机描述进行建模:

  • 状态机是区域的集合
  • 区域是状态和转换的集合
  • 状态是区域和转换的集合
c++ boost-spirit
1个回答
0
投票

我只能假设您遗漏了代码来解释位置跟踪基础和迭代器传递(我希望您使用

on_sucess
,而不仅仅是
on_error
)。

我简化/重塑了事物以便进行审查。最后,我认为唯一真正需要的改变似乎是您已经评论过的:

regions     = *region;

原理请参见

现在无限循环表明

region
与空输入匹配。由于过渡至少需要
rstring
,而这至少需要一个字符,因此您应该能够通过需要至少一个过渡来解决此问题:

    region      = qi::eps >> +transition;

我最终得到了这个示例,它还以我知道的最节能的方式修复了调试输出:

实时编译器资源管理器

#define BOOST_SPIRIT_DEBUG 1
#include <boost/fusion/include/adapted.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <fstream>
#include <iomanip>

namespace bs = boost::spirit;
namespace bp = boost::phoenix;

namespace Ast {
    /*
       - a state machine is a collection of regions
       - a region is a collection of states & transitions
       - a state is a collection of regions & transitions
       */
    struct state;
    struct region;
    struct machine;

    struct location {
        size_t      _line{0};
        size_t      _col{0};
        std::string _file;
    };

    using node_base = location;
    // struct node_base : location {};

    struct null : location {};

    struct transition : location {
        std::string /*_id,*/ _fromState, _toState, _event, _guard, _effect;
    };

    using node    = boost::variant<          //
        null, transition,                 //
        boost::recursive_wrapper<state>,  //
        boost::recursive_wrapper<region>, //
        boost::recursive_wrapper<machine>>;
    using nodes_t = std::vector<node>;

    struct state : location {
        nodes_t _subtree;
    };
    struct region : location {
        nodes_t _subtree;
    };
    struct machine : location {
        nodes_t _subtree;
    };

    using boost::fusion::operator<<;
} // namespace Ast

BOOST_FUSION_ADAPT_STRUCT(Ast::null) // or provide operator<<...
BOOST_FUSION_ADAPT_STRUCT(Ast::machine, _subtree)
BOOST_FUSION_ADAPT_STRUCT(Ast::region, _subtree)
BOOST_FUSION_ADAPT_STRUCT(Ast::state, _subtree)
BOOST_FUSION_ADAPT_STRUCT(Ast::transition, /*_id,*/ _fromState, _toState, _event, _guard, _effect)
BOOST_FUSION_ADAPT_STRUCT(Ast::node_base, _line, _col, _file)

namespace plantuml {
    namespace qi       = bs::qi;
    namespace encoding = qi::ascii;

    template <typename It> struct skipper final : qi::grammar<It> {
        skipper() : skipper::base_type(rule) {}

        qi::rule<It> const rule = encoding::space | ("#" >> *~encoding::char_("\n") >> -qi::eol) |
            ("//" >> *~encoding::char_("\n") >> -qi::eol) | ("/*" >> *(encoding::char_ - "*/") >> "*/");
    };

    template <typename ITER, typename SKIPPER>
    struct plantuml_grammar final
        : qi::grammar<ITER, Ast::machine(), qi::locals<std::string>, SKIPPER /*bs::ascii::space_type*/> {
        plantuml_grammar(ITER first) : plantuml_grammar::base_type(start) {
            using qi::fail;
            using qi::on_error;
            using namespace qi::labels; // _a, _1, _val, _pass ...

            qstring    %= qi::lexeme['"' >> +(qi::char_ - '"') >> '"'];
            rstring    %= qi::raw[qi::lexeme[+qi::char_("a-zA-Z0-9_")]];
            transition %= rstring >> qi::lit("-->") >> rstring;
            region      = qi::eps >> +transition;
            regions     = *region;

            start = qi::lit("@startuml") //[ bp::push_back(bp::ref(_val._subtree), Ast::region()) ]
                >> regions >> qi::lit("@enduml");

            BOOST_SPIRIT_DEBUG_NODES((start)(regions)(region)(transition))
        }

        qi::rule<ITER, std::string()>                                    qstring;
        qi::rule<ITER, std::string()>                                    rstring;
        qi::rule<ITER, Ast::transition(), SKIPPER>                       transition;
        qi::rule<ITER, Ast::region(), SKIPPER>                           region;
        qi::rule<ITER, Ast::nodes_t(), SKIPPER>                          regions;
        qi::rule<ITER, Ast::machine(), qi::locals<std::string>, SKIPPER> start;

    }; // plantuml_grammar

    bool plantuml_parser(std::istream& in) {
        using base_iter_t        = bs::istream_iterator;
        using lp_iter_t          = bs::line_pos_iterator<base_iter_t>;
        using in_iter_t          = lp_iter_t;          // base_iter_t; //
        using skipper_t          = skipper<in_iter_t>; //
        using plantuml_grammar_t = plantuml_grammar<in_iter_t, skipper_t>;

        in_iter_t crtIt(base_iter_t(in >> std::noskipws));
        in_iter_t firstIt(crtIt);
        in_iter_t endIt;

        plantuml_grammar_t grammar(firstIt);

        Ast::node ast;

        skipper_t skip  = {};
        bool      match = qi::phrase_parse(crtIt, endIt, grammar,
                                           skip, // bs::ascii::space,
                                           ast);
        return match;
    }

} // namespace plantuml

int main() {
    std::string const test = R"--(
        @startuml
        
        #xDeploy -down-> xOperation
        Deploy --> Operation
        
        /*
        state Operation {
        
        [*] -down-> Operation_Launch
        
        Operation_Launch -down-> Operation_Auto_Monitor
        --
        [*] -down-> Operation_BizData_Collection
        
        Operation_BizData_Collection -down-> Operation_BizData_Anylasis
        --
        [*] -down-> Operation_Next_Preparation
        
        }
        
        Operation -down-> [*]
        */
        
        @enduml
    )--";
    // bool ret =  plantuml::plantuml_parser(test);

    std::istringstream in(test);
    bool               ret = plantuml::plantuml_parser(in);
}

印刷

<start>
  <try>\n        @startuml\n </try>
  <regions>
    <try>\n        \n        #x</try>
    <region>
      <try>\n        \n        #x</try>
      <transition>
        <try>Deploy --> Operation</try>
        <success>\n        \n        /*</success>
        <attributes>[[[D, e, p, l, o, y], [O, p, e, r, a, t, i, o, n], [], [], []]]</attributes>
      </transition>
      <transition>
        <try>\n        \n        /*</try>
        <fail/>
      </transition>
      <success>\n        \n        /*</success>
      <attributes>[[[[[D, e, p, l, o, y], [O, p, e, r, a, t, i, o, n], [], [], []]]]]</attributes>
    </region>
    <region>
      <try>\n        \n        /*</try>
      <transition>
        <try>@enduml\n    </try>
        <fail/>
      </transition>
      <fail/>
    </region>
    <success>\n        \n        /*</success>
    <attributes>[[[[[[D, e, p, l, o, y], [O, p, e, r, a, t, i, o, n], [], [], []]]]]]</attributes>
  </regions>
  <success>\n    </success>
  <attributes>[[[[[[[D, e, p, l, o, y], [O, p, e, r, a, t, i, o, n], [], [], []]]]]]]</attributes><locals>()</locals>
</start>
© www.soinside.com 2019 - 2024. All rights reserved.