我一直在使用Boost库中的Spirit Qi用C++编写语法。作为该语言的新手,很难习惯该库的语法和怪癖,但现在我有点理解它的工作原理。

使用qi::lexeme时出现错误。我的实际语法很大,因此我制作了一个小代码段,其中存在相同的问题。以下代码编译没有错误:

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

#include <set>
#include <iostream>
#include <string>
#include <complex>

namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    typedef boost::tuple<char, char> range;
}

namespace client
{
    template <typename Iterator>
    struct employee_parser : qi::grammar<Iterator, range(), ascii::space_type>
    {
        employee_parser() : employee_parser::base_type(start)
        {
            using qi::lit;
            using qi::lexeme;
            using ascii::char_;

            range_rule =
                char_("a-z") >> lit("-") >> char_("a-z")
                | char_("A-Z") >> lit("-") >> char_("A-Z")
                | char_("0-9") >> lit("-") >> char_("0-9")
                ;

            start = range_rule;
        }

        qi::rule<Iterator, range(), ascii::space_type> range_rule;
        qi::rule<Iterator, range(), ascii::space_type> start;
    };
}

int main()
{
    typedef std::string::const_iterator iterator_type;
    typedef client::employee_parser<iterator_type> employee_parser;
    employee_parser g;
    return 0;
}

现在,如果我替换start = range_rule;行并改用start = lexeme[range_rule];,编译将失败。

当我从the docs中读取时,lexeme[a]应该保留主题解析器的属性,因此我无法理解为什么它会失败。输出错误很大并且很隐蔽,所以我没有任何线索:
In file included from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14:0,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
                 from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp: In instantiation of ‘bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/reference.hpp:43:72:   required from ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/directive/lexeme.hpp:66:64:   required from ‘typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type boost::spirit::qi::lexeme_directive<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = boost::tuples::tuple<char, char>; Subject = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >; typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type = bool]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54:   required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser = boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>; mpl_::false_ = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:24:   required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser
= boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:138:22:   required from ‘static R boost::detail::function::function_obj_invoker4<FunctionObj, R, T0, T1, T2, T3>::invoke(boost::detail::function::function_buffer&, T0, T1, T2, T3) [with FunctionObj = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:936:38:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1074:16:   required from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type = int]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1127:5:   required from ‘typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >,
mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:183:19:   required from ‘static void boost::spirit::qi::rule<Iterator,
T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::true_ = mpl_::bool_<true>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:221:32:   required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3,
T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
cpp/tests/test2.cpp:40:19:   required from ‘client::employee_parser<Iterator>::employee_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’
cpp/tests/test2.cpp:56:21:   required from here
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:304:17: error: no match for call to ‘(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>}) (__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >&)’
                 if (f(first, last, context, skipper))
                 ^~
In file included from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/maybe_include.hpp:43:0,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/function_iterate.hpp:14,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function.hpp:70,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:16,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
                 from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
                 from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763:17: note: candidate: boost::function4<R, T1, T2, T3, T4>::result_type boost::function4<R, T1, T2, T3, T4>::operator()(T0, T1, T2, T3) const [with R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]
     result_type operator()(BOOST_FUNCTION_PARMS) const
                 ^~~~~~~~
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763:17: note:   no known conversion for argument 4 from ‘const boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&’

最佳答案



是的,它保留属性。它确实而不是保留该船长(出于明显的原因),并且您的range_rule声明了一个船长。编译器消息包含以下信息:

BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
            !is_same<Skipper, unused_type>::value),
            "The rule was instantiated with a skipper type but you have not pass any. "
            "Did you use `parse` instead of `phrase_parse`?");

因此,从range_rule中删除船长。具有讽刺意味的是,仅将其删除将隐式使其表现得像一个词素,因此无论如何您都不需要它周围的lexeme[]

另请参阅Boost spirit skipper issues

简而言之:
  • 无法在没有一个
  • 的情况下调用需要跳过程序的规则
  • 可以从带有船长上下文的解析器中调用隐式lexeme规则

  • 我通常将规则进行分组以表示尽可能多的内容,并在其前面加上注释,例如:
      private:
        qi::rule<Iterator, range(), ascii::space_type> start;
    
        // lexmes
        qi::rule<Iterator, range()> range_rule;
    

    但是我通常还会封装该船长,除非调用者更改船长确实有意义(?!)。

    另请参阅类似的任务:
  • Parsing comma-separated list of ranges and numbers with semantic actions
  • method for expand a-z to abc...xyz form

  • 建议的修复

    Live On Coliru
    #include <boost/config/warning_disable.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/phoenix_operator.hpp>
    #include <boost/spirit/include/phoenix_object.hpp>
    #include <boost/fusion/include/adapt_struct.hpp>
    #include <boost/fusion/include/io.hpp>
    #include <boost/fusion/include/boost_tuple.hpp>
    
    #include <set>
    #include <iostream>
    #include <string>
    #include <complex>
    
    namespace client
    {
        namespace qi = boost::spirit::qi;
        typedef boost::tuple<char, char> range;
    }
    
    namespace client
    {
        template <typename Iterator>
        struct employee_parser : qi::grammar<Iterator, range()>
        {
            employee_parser() : employee_parser::base_type(start)
            {
                using qi::lit;
                using qi::lexeme;
                using qi::ascii::char_;
    
                range_rule =
                    char_("a-z") >> lit("-") >> char_("a-z")
                  | char_("A-Z") >> lit("-") >> char_("A-Z")
                  | char_("0-9") >> lit("-") >> char_("0-9")
                  ;
    
                start = qi::skip(qi::ascii::space) [ range_rule ];
            }
    
          private:
            qi::rule<Iterator, range()> start;
    
            // lexmes
            qi::rule<Iterator, range()> range_rule;
        };
    }
    
    int main()
    {
        typedef std::string::const_iterator iterator_type;
        typedef client::employee_parser<iterator_type> employee_parser;
        employee_parser g;
    
        std::string const input("a-k");
        client::range r;
        return parse(begin(input), end(input), g, r)
            ? 0
            : 1;
    }
    

    09-08 04:43