传递参数来提升精神自定义解析器

时间:2015-04-20 22:07:58

标签: c++ boost-spirit boost-spirit-qi

我正在尝试按照此处的说明创建自定义解析器:http://boost-spirit.com/home/articles/qi-example/creating-your-own-parser-component-for-spirit-qi/。在本文中,解析器没有参数,即我不能写qi::parse(first, input.end(), +qi::alpha >> custom_parser::iter_pos("my argument"));之类的东西。如何修改示例以传递参数?我试过这个:

using namespace boost::spirit;

namespace parsernm { BOOST_SPIRIT_TERMINAL(aparser); }

namespace boost { namespace spirit {
    template <typename A0>
    struct use_terminal<
        qi::domain
      , terminal_ex<
            parsernm::tag::aparser
          , fusion::vector1<A0>
          >
      > : mpl::true_
    {};
}}

namespace parsernm
{
    struct aparser_impl : boost::spirit::qi::primitive_parser<aparser_impl>
    {
        aparser_impl(int _param)
          : param(_param)
        {}

        template <typename Iterator, typename Context, typename Skipper, typename Attribute>
        bool parse(Iterator& first, Iterator const& last, Context&,
                   Skipper const& skipper, Attribute& attr) const
        {
            return true;
        }

        template <typename Context>
        boost::spirit::info what(Context&) const {
            return boost::spirit::info("aparser");
        }

        int param;
    };
}

namespace boost { namespace spirit { namespace qi {
    template <typename Modifiers>
    struct make_primitive<parsernm::tag::aparser, Modifiers>
    {
        typedef parsernm::aparser_impl result_type;

        template <typename Terminal>
        result_type operator()(Terminal const& term, unused_type) const
        {
            return result_type(fusion::at_c<0>(term.args));
        }
    };
}}}

int main(int argc, char* argv[])
{
    std::string input("");
    std::string::iterator first = input.begin();
    bool result = qi::parse(first, input.end(), parsernm::aparser(10));

    return 0;
}

结果是boost \ spirit \ home \ qi \ detail \ parse.hpp(32):错误C2338:error_invalid_expression。

1 个答案:

答案 0 :(得分:4)

我明白了。必须将BOOST_SPIRIT_TERMINAL更改为BOOST_SPIRIT_TERMINAL_EXmake_primitive应如下所示:

namespace boost { namespace spirit { namespace qi {
    template <typename Modifiers, typename A0>
    struct make_primitive<
        terminal_ex<
            parsernm::tag::aparser
          , fusion::vector1<A0>
          >
      , Modifiers
      >
    {
        typedef parsernm::aparser_impl result_type;

        template <typename Terminal>
        result_type operator()(Terminal const& term, unused_type) const
        {
            return result_type(fusion::at_c<0>(term.args));
        }
    };
}}}