Как мне избежать ошибок компилятора Spirit

Я пытаюсь использовать no_skip директива для разбора ввода формы:

state PASS
<tab> state FAIL

я использую ascii::blank как мой шкипер Я получаю ошибку компиляции при переносе no_skip[ trans_assign_expr ] разобрать на вкладке.

Как я могу исправить эту ошибку, и вообще, как я понимаю эти ошибки, чтобы я мог исправить будущие? Документация Boost Spirit никогда не охватывает этот аспект использования Spirit 🙁

Это ошибка

В файле, включенном в /usr/include/boost/spirit/home/qi/nonterminal/grammar.hpp:18:0,
из /usr/include/boost/spirit/include/qi_grammar.hpp:16,
из ../src/RJstate.cpp:9:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp: В функции-члене 'bool boost :: spirit :: qi :: rule :: parse (Итератор, const Iterator, Context, const Skipper, Attribute) const [с Context = boost :: spirit :: context, boost :: fusion :: vector0>, Skipper = boost :: spirit :: qi :: detail :: unused_skipper>>, атрибут = const boost :: spirit :: unused_type , Iterator = __gnu_cxx :: __ normal_iterator>, T1 = boost :: proto :: exprns _ :: expr>, 0l>, T2 = boost :: spirit :: unused_type, T3 = boost :: spirit :: unused_type, T4 = boost: : дух :: unused_type]:
/usr/include/boost/spirit/home/qi/reference.hpp:43:71: создается из 'bool boost :: spirit :: qi :: reference :: parse (Итератор, const Iterator, Context, const Skipper, Attribute ) const [с Итератором = __gnu_cxx :: __ normal_iterator>, Context = boost :: spirit :: context, boost :: fusion :: vector0>, Skipper = boost :: spirit :: qi :: detail :: unused_skipper>>, Атрибут = const boost :: spirit :: unused_type, Subject = const boost :: spirit :: qi :: rule>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost: : spirit :: unused_type, boost :: spirit :: unused_type>] '
/usr/include/boost/spirit/home/qi/directive/no_skip.hpp:64:63: создается из 'bool boost :: spirit :: qi :: no_skip_directive :: parse (Итератор, константный итератор, контекст, const Skipper , Атрибут) const [с помощью Iterator = __gnu_cxx :: __ normal_iterator>, контекст = boost :: spirit :: context, boost :: fusion :: vector0>, шкипер = boost :: spirit :: qi :: char_class>, атрибут = const boost :: spirit :: unused_type, Subject = boost :: spirit :: qi :: reference>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit: : unused_type, boost :: spirit :: unused_type>>] '
/usr/include/boost/spirit/home/qi/detail/fail_function.hpp:45:74: создается из 'bool boost :: spirit :: qi :: detail :: fail_function :: operator () (const Component) const [с компонентом = boost :: spirit :: qi :: no_skip_directive>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, Iterator = __gnu_cxx :: __ normal_iterator>, Context = boost :: spirit :: context, boost :: fusion :: vector0>, Skipper = boost :: spirit :: qi :: char_class>] '
/usr/include/boost/fusion/algorithm/query/detail/any.hpp:42:83: [пропуская 8 контекстов создания]
/usr/include/boost/function/function_template.hpp:132:42: создается из статического R boost :: detail :: function :: function_obj_invoker4 :: invoke (boost :: detail :: function :: function_buffer, T0, T1 , T2, T3) [с FunctionObj = boost :: spirit :: qi :: detail :: parser_binder>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>, boost :: fusion :: cons>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, boost :: fusion :: nil>>>>, mpl _ :: bool_>, R = bool, T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator>, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class>] '
/usr/include/boost/function/function_template.hpp:913:60: создается из 'void boost :: function4 :: assign_to (Functor) [с Functor = boost :: spirit :: qi :: detail :: parser_binder>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>, boost :: fusion :: cons>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, boost :: fusion :: nil> >>>, mpl _ :: bool_>, R = bool, T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator>, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class>] '
/usr/include/boost/function/function_template.hpp:722:7: создается из 'boost :: function4 :: function4 (Functor, typename boost :: enable_if_c :: value> :: value, int> :: type) [ с Functor = boost :: spirit :: qi :: detail :: parser_binder>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>, boost :: fusion :: cons>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, boost :: fusion :: nil>>>>, mpl _ :: bool_>, R = bool, T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator>, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class>, повышение имени типа :: enable_if_c :: value> :: value, int> :: type = int] '
/usr/include/boost/function/function_template.hpp:1064:16: создается из 'boost :: function :: function (Functor, typename boost :: enable_if_c :: value> :: value, int> :: type) [ с Functor = boost :: spirit :: qi :: detail :: parser_binder>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>, boost :: fusion :: cons>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, boost :: fusion :: nil>>>>, mpl _ :: bool_>, R = bool, T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator>, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class>, повышение имени типа :: enable_if_c :: value> :: value, int> :: type = int] '
/usr/include/boost/function/function_template.hpp:1105:5: создается из 'typename boost :: enable_if_c :: value> :: value, boost :: function> :: type boost :: function :: operator = ( Функтор) [с Functor = boost :: spirit :: qi :: detail :: parser_binder>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>, boost :: fusion :: cons>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>>>, boost :: fusion :: nil>>>>, mpl _ :: bool_>, R = bool, T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator >, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class>, typename boost :: enable_if_c :: value> :: value, boost :: function> :: type = boost :: function>, const __gnu_cxx :: __ normal_iterator>, boost :: spirit :: context, boost :: fusion :: vector0>, const boost :: spirit :: qi :: char_class> )>]
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:198:13: создается из ‘boost :: spirit :: qi :: rule boost :: spirit :: qi :: rule :: operator = (const Expr) [с Expr = boost :: proto :: exprns _ :: expr>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>, const boost :: proto :: exprns _ :: expr, 0l >>, 2l>, const boost :: proto :: exprns _ :: expr, 0l>, boost :: spirit :: qi :: rule>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type , boost :: spirit :: unused_type >>, 2l >>, 2l>, Iterator = __gnu_cxx :: __ normal_iterator>, T1 = boost :: proto :: exprns _ :: expr>, 0l>, T2 = boost :: spirit: : unused_type, T3 = boost :: spirit :: unused_type, T4 = boost :: spirit :: unused_type, boost :: spirit :: qi :: rule = boost :: spirit :: qi :: rule>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type>] '
../src/RJstate.cpp:49:7: создается из ‘fsm_grammar :: fsm_grammar () [with Iterator = __gnu_cxx :: __ normal_iterator>, Skipper = boost :: proto :: exprns _ :: expr>, 0l>]’
../src/RJstate.cpp:112:50: создается отсюда
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:277:17: ошибка: нет совпадения для вызова '(const function_type {aka const boost :: function>, const __gnu_cxx :: __ normal_iterator>, boost :: spirit :: context, boost :: fusion :: vector0>, const boost :: spirit :: qi :: char_class>)>}) (__gnu_cxx :: __ normal_iterator>, const __gnu_cxx :: __ normal_iterator>, boost :: spirit :: qi :: rule>, boost :: proto :: exprns _ :: expr>, 0l>, boost :: spirit :: unused_type, boost :: spirit :: unused_type, boost :: spirit :: unused_type> :: context_type, const boost :: spirit :: qi :: detail :: unused_skipper>>) '
/usr/include/boost/function/function_template.hpp:1043:7: примечание: кандидат - это:
/usr/include/boost/function/function_template.hpp:1006:1: примечание: boost :: function4 :: result_type boost :: function4 :: operator () (T0, T1, T2, T3) const [с R = bool , T0 = __gnu_cxx :: __ normal_iterator>, T1 = const __gnu_cxx :: __ normal_iterator>, T2 = boost :: spirit :: context, boost :: fusion :: vector0>, T3 = const boost :: spirit :: qi :: char_class >, boost :: function4 :: result_type = bool]
/usr/include/boost/function/function_template.hpp:1006:1: примечание: нет известного преобразования для аргумента 4 из 'const boost :: spirit :: qi :: detail :: unused_skipper>>' to 'const boost :: spirit :: qi :: char_class> '

Это мой код

#define BOOST_SPIRIT_DEBUG

#include <iostream>
#include <vector>
#include <iterator>
#include <fstream>

// forwards to <boost/spirit/home/qi/nonterminal/grammar.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
// forwards to <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/include/qi_rule.hpp>

#include <boost/spirit/include/qi.hpp>

#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/qi_no_skip.hpp>

#include <boost/spirit/include/phoenix.hpp>

#include "TestParser.hpp"
///////////////////////////////////////////////////////////////////////////////

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

template <typename Iterator, typename Skipper=qi::space_type>
struct fsm_grammar : qi::grammar<Iterator, Skipper>
{
fsm_grammar() : fsm_grammar::base_type(script)
{
using boost::spirit::double_;
using boost::spirit::ascii::char_;
using boost::spirit::ascii::alnum;
using boost::spirit::ascii::alpha;
using boost::spirit::lit;
using boost::spirit::qi::eol;
using boost::spirit::qi::eoi;
using boost::spirit::lexeme;
using boost::spirit::qi::no_skip;
using boost::spirit::qi::_1;
using boost::spirit::qi::_val;

//id = char_("a-zA-Z")[_val += _1] >> *char_("a-zA-Z_0-9")[_val += _1];
id = lexeme[ alpha[_val += _1] >> *alnum[_val += _1] >> !alnum ];
state_id = "state" >> id;
start_expr = "start" >> id;
trans_assign_expr = lit("\t") >> state_id >> +(char_('a','z'));
trans_expr = state_id >> eol >> no_skip[ trans_assign_expr ];
assign_expr = char_("a-zA-Z");
states_list = "states" >> +(id);
expr = (trans_expr | start_expr | states_list) >> +eol;
script = *expr >> eoi;

BOOST_SPIRIT_DEBUG_NODE(script);
BOOST_SPIRIT_DEBUG_NODE(states_list);
BOOST_SPIRIT_DEBUG_NODE(expr);
BOOST_SPIRIT_DEBUG_NODE(start_expr);
BOOST_SPIRIT_DEBUG_NODE(assign_expr);
BOOST_SPIRIT_DEBUG_NODE(trans_expr);
BOOST_SPIRIT_DEBUG_NODE(trans_assign_expr);
BOOST_SPIRIT_DEBUG_NODE(state_id);
BOOST_SPIRIT_DEBUG_NODE(id);

std::string val = "PASS";
//test_parser("  ",+char_("a-zA-Z"));
}

qi::rule<Iterator, Skipper> script;
qi::rule<Iterator, Skipper> states_list;
qi::rule<Iterator, Skipper> expr;
qi::rule<Iterator, Skipper> trans_expr;
qi::rule<Iterator, Skipper> trans_assign_expr;
qi::rule<Iterator, Skipper> assign_expr;
qi::rule<Iterator, Skipper> start_expr;
qi::rule<Iterator, Skipper> state_id;
qi::rule<Iterator, std::string()> id;
};

4

Решение

Как очень удачно указал Илонесмиз:

  • ищите статические утверждения (****** like this in the error 'novel' ******)
  • искать комментарии непосредственно (Я имею в виду, непосредственно) над «ошибочной» линией. Это включает точки, в которых были запущены экземпляры шаблона.

    Если вы видите здесь ошибку компиляции, утверждающую, что четвертый параметр не может быть преобразован в требуемый целевой тип, то вы, вероятно, пытаетесь использовать правило или грамматику с несовместимым типом шкипера.

    В этом случае, так как вы хотите использовать trans_assign_expr без шкипера, вы должны объявить это без одного:

    // no skippers
    qi::rule<Iterator, std::string()> id;
    qi::rule<Iterator> state_id;
    qi::rule<Iterator> trans_assign_expr;
    

Это делает его компиляцией. Выходные данные предполагают, что это не / работа /, хотя.

Я не уверен, что это то, что вы хотите сделать. поскольку lexeme в любом случае, кажется, здесь лучший вариант. Я бы упростил id правило:

id = lexeme [ alpha >> *alnum ];

lexeme уже имеет свойство локального отключения Skipper в использовании.

Вот небольшое изменение грамматики http://liveworkspace.org/code/70f3319342c567854b9f785ac13508d6

trans_assign_expr = state_id >> +(char_('a','z'));
trans_expr        = state_id >> no_skip [ eol >> '\t' ] >> trans_assign_expr;

Как видите, я включаю с eol в no_skip (чтобы избежать шкипера есть вкладку). Таким образом, шкипер еще в действительности в trans_assign_expr — что заставляет его принять дополнительное пространство. Учитывая вход

const char input[]="state PASS\n\t state FAIL more";

Выход сейчас

<script>
<try>state PASS\n\t state F</try>
<expr>
<try>state PASS\n\t state F</try>
<trans_expr>
<try>state PASS\n\t state F</try>
<state_id>
<try>state PASS\n\t state F</try>
<id>
<try> PASS\n\t state FAIL m</try>
<success>\n\t state FAIL more\n</success>
<attributes>[[P, A, S, S]]</attributes>
</id>
<success>\n\t state FAIL more\n</success>
<attributes>[]</attributes>
</state_id>
<trans_assign_expr>
<try> state FAIL more\n</try>
<state_id>
<try> state FAIL more\n</try>
<id>
<try> FAIL more\n</try>
<success> more\n</success>
<attributes>[[F, A, I, L]]</attributes>
</id>
<success> more\n</success>
<attributes>[]</attributes>
</state_id>
<success>\n</success>
<attributes>[]</attributes>
</trans_assign_expr>
<success>\n</success>
<attributes>[]</attributes>
</trans_expr>
<success></success>
<attributes>[]</attributes>
</expr>
<expr>
<try></try>
<trans_expr>
<try></try>
<state_id>
<try></try>
<fail/>
</state_id>
<fail/>
</trans_expr>
<start_expr>
<try></try>
<fail/>
</start_expr>
<states_list>
<try></try>
<fail/>
</states_list>
<fail/>
</expr>
<success></success>
<attributes>[]</attributes>
</script>
true
4

Другие решения

Других решений пока нет …