Я пытался создать собственный класс Parser в Boost.Spirit (2.3), но это не сработало.Код:
template <class Iter>
class crule : public boost::spirit::qi::parser<crule<Iter> >
{
rule<Iter> r_;
public:
crule(const rule<Iter>& r) : r_(r) {}
template <class T>
crule(const T& t) : r_(t) {}
template<class Ctx, class Skip>
bool parse(Iter& f, const Iter& l, Ctx& context, Skip& skip, typename rule<Iter>::template attribute<Ctx, Iter>::type& attr) const {
return r_.parse(f, l, context, skip, attr);
}
template <class Ctx>
boost::spirit::info what(Ctx& context) const {
return r_.what(context);
}
template <class Context, class It>
struct attribute {
typedef typename rule<Iter>::template attribute<Context, It>::type type;
};
};
и хотя я (по крайней мере, думаю, что выполнил) все требования , я получаю ошибки, когда пытаюсь использовать этот класс в выражении синтаксического анализа:
shell_grammar.h:134: error: no match for 'operator!' in '!shell_grammar<Iter>::token(boost::spirit::qi::rule<Iter, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>) [with Iter = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >](boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>(((const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>&)((const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>*)(&((shell_grammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*)this)->shell_grammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::reserved_words)))))'
shell_grammar.h:134: note: candidates are: operator!(bool) <built-in>
Я пытался взглянуть на реализацию других парсетов (например, not_predicate
), но не могу понять, в чем разница, которая заставляет его работать.
Motvation
Причина, по которой я это делаю, связана с этим вопросом .Я хочу разобрать язык оболочки POSIX, который имеет своеобразные лексические правила.В частности, «анализатор шкипера» должен применяться даже в лексемах, но он должен отличаться от синтаксического анализатора «уровня фразы».Это то, что директива lexeme
не может сделать, и skip
не пропускает заранее (AFAIK), что мне тоже нужно.Поэтому я хочу создать функцию
something token(std::string);
, которая бы возвращала правило, соответствующее токену.Одним из способов является создание моей собственной оболочки rule
, которая будет служить терминалом (поскольку один rule
не может использоваться для его ссылочной семантики), другой - создание нового синтаксического анализатора (который будет нетерминальным в proto
),и реализовать в нем синтаксический анализ токена оболочки.