Как составить граматику чтобы она заработала?

115
19 сентября 2021, 15:50

Создаю граматику для вычисления выражения. Использую Boost.spirit.qi. Написал граматику следующего вида:

using namespace qi;
using It = std::string::iterator;
qi::rule<It, double(), qi::space_type> arith_expression, arith_term, arith_factor;
qi::rule<It, double(), qi::space_type> b_expression, b_term, b_factor;
auto literal = double_;
arith_factor = literal
        | '(' >> arith_expression >> ')'
        | '-' >> arith_factor
        | '+' >> arith_factor
        | '(' >> b_expression >> ')'
        ;
arith_term = arith_factor [_val = _1] >> *('*' >> arith_factor [_val *= _1]
                                         | '/' >> arith_factor [_val /= _1]
                                          );
arith_expression = arith_term [_val = _1] >> *('+' >> arith_term [_val += _1]
                                             | '-' >> arith_term [_val -= _1]
                                              )
                                 ;
qi::rule<It, double()> relation;
relation = arith_expression [_val = _1] >> *(qi::lit("==") >> arith_expression [_val = (_val == _1)] );
auto b_literal = double_;
b_factor = b_literal [_val = _1]
        | '(' >> b_expression [_val = _1] >> ')'
        | qi::lit("not") >> b_factor [_val = !_1]
        | relation [_val = _1]
        ;
b_term = b_factor  [_val = _1] >> *(qi::lit("and") >> b_factor [_val = (_val && _1)]);
b_expression = b_term [_val = _1] >> *(qi::lit("or") >> b_term [_val = (_val || _1)] );

Но почему то она не компилируется, хотя по отдельности и бинарное и арифметическое выражения работают отлично. Как только добавляю отношение(relation) то все начинает "падать" во время компиляции. Может быть я неправльно составил граматику при добавлении оператора отношения либо я не доконца понял boost.spirit.qi. Вот фрагмент ошибки компиляции:

error: no match for call to ‘(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<double&, 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::standard> >&)>}) (__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, double(), 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::standard> >, 0> >::context_type&, const boost::spirit::unused_type&)’ if (f(first, last, context, skipper)) ^~ In file included from /usr/include/boost/function/detail/maybe_include.hpp:43:0, from /usr/include/boost/function/detail/function_iterate.hpp:14, from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67, from /usr/include/boost/function.hpp:70, from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:16, from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14, from /usr/include/boost/spirit/home/qi.hpp:21, from /usr/include/boost/spirit/include/qi.hpp:16, from grammar.cpp:6: /usr/include/boost/function/function_template.hpp:754: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<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<double&, 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::standard> >&; boost::function4<R, T1, T2, T3, T4>::result_type = bool] result_type operator()(BOOST_FUNCTION_PARMS) const ^~~~~~~~ /usr/include/boost/function/function_template.hpp:754:17: note: no known conversion for argument 4 from ‘const boost::spirit::unused_type’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >&’

Answer 1

Разобрался.Нужно так: `

qi::rule expression, additive, multiplicative, relationship, factor;

expression = relationship [_val = _1];
relationship = additive [_val = _1]
        >> *(
              lit("==")  >> additive [_val = (_val == _1)]
            | lit("!=")  >> additive [_val = (_val != _1)]
            | lit("<" )  >> additive [_val = (_val < _1)]
            | lit(">" )  >> additive [_val = (_val > _1)]
            | lit("<=")  >> additive [_val = (_val <= _1)]
            | lit(">=")  >> additive [_val = (_val >= _1)]
            )
            ;
additive = multiplicative [_val = _1]
        >> *(
                lit("+")  >> multiplicative [_val += _1]
            |   lit("-")  >> multiplicative [_val += _1]
            |   lit("or") >> multiplicative  [_val == (_val || _1)]
            )
            ;
multiplicative = factor [_val = _1]
        >> *(
                lit("*")   >> factor [_val *= _1]
            |   lit("/")   >> factor [_val /= _1]
            |   lit("and") >> factor [_val = (_val && _1)]
            )
            ;
factor = double_ [_val = _1]
        | bool_  [_val = _1]
        | lit("(")   >> expression [_val = _1] >> lit(")")
        | lit("-")   >> factor [_val = -_1]
        | lit("+")   >> factor [_val = +_1]
        | lit("not") >> factor [_val = !(_1)]
        ;`
READ ALSO
Cделать правильный запрос SQL

Cделать правильный запрос SQL

Есть 2 таблицы products(id,product_name,price) и reviews(id,product_id,commentary)

109
Получение из D9 D6 34 01 (hex) числа 10258209 (dec)

Получение из D9 D6 34 01 (hex) числа 10258209 (dec)

Известен участок кода из C#:

118
Canvas кладет все Images из List на координаты первого Image

Canvas кладет все Images из List на координаты первого Image

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

139