最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Boost::spirit::qi compiler error when trying to integrate a skip parser - Stack Overflow

programmeradmin1浏览0评论

I'm trying for the first time to write my own grammar with spirit::qi, and I don't succeed in integrating a skip parser that should ignore C style comments as well as whitespaces. Here's my source file (I reduced the grammar to just a few rules, in order to be more concise:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "formulaNode.h"

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;

using FormulaNodePtr = compiler::FormulaNode*;
using ExpressionPtr = compiler::Expression*;

template <typename Iterator>
struct ArithmeticGrammar : qi::grammar<Iterator, FormulaNodePtr(), qi::space_type> {
    ArithmeticGrammar() : ArithmeticGrammar::base_type(formula, "Formula") {
        using namespace qi;

        localSkipper = qi::space | ("/*" >> *(qi::char_ - "*/") >> "*/");

        formula = unsignedFactor [_val = _1];

        unsignedFactor =
            numericConstant [_val = phoenix::new_<compiler::Constant>(_1)];

        numericConstant = qi::as_string[
            qi::lexeme[  -qi::char_('-') >>
                (+qi::digit >> -(qi::char_('.') >> +qi::digit)) >>
                -(qi::char_('e') >> -qi::char_('-') >> +qi::digit) 
            ]];
    }

    qi::rule<Iterator, FormulaNodePtr(), qi::space_type> formula;
    qi::rule<Iterator, ExpressionPtr(), qi::space_type> unsignedFactor;
    qi::rule<Iterator, std::string(), qi::space_type> numericConstant;
    qi::rule<Iterator, qi::space_type> localSkipper;
};

// Parsing function
bool parseExpression(const std::string& input, FormulaNodePtr& result)
{
    using Iterator = std::string::const_iterator;
    ArithmeticGrammar<Iterator> grammar;

    Iterator it = input.begin();
    Iterator end = input.end();

    bool success = qi::phrase_parse(it, end, grammar, grammar.localSkipper, result);

    if (!success || it != end)
    {
        if (result == nullptr) {
            std::cout << "Parsing failed\n";
        }
        delete result;
        result = nullptr;
    }

    return success && (it == end);
}

int main()
{
    std::string input;
    std::cout << "Enter input: ";
    std::getline(std::cin, input);

    while (!input.empty()) {
        FormulaNodePtr result = nullptr;
        if (parseExpression(input, result))
        {
            std::cout << "Parsed successfully. Expression tree:" << std::endl;
            result->print(std::cout, 0);
            delete result;
        } else {
            std::cout << "Parsing failed. Please enter a valid expression." << std::endl;
        }
        std::getline(std::cin, input);
    }

    return EXIT_SUCCESS;
}

The way I use the skipper parser is taken from various internet examples. Yet when I try to compile this, I get this error message - can someone explain that to me?

g++ -std=c++11 -Wall -Wextra -pedantic Main2.cpp -o parser
In file included 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 Main2.cpp:1:
/usr/include/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<compiler::FormulaNode*&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >; Attribute = compiler::FormulaNode*; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = compiler::FormulaNode*(); 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::standard> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/usr/include/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<compiler::FormulaNode*&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >; Attribute = compiler::FormulaNode*; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, compiler::FormulaNode*(), 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>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/usr/include/boost/spirit/home/qi/parse.hpp:164:13:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
/usr/include/boost/spirit/home/qi/parse.hpp:197:32:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
Main2.cpp:49:83:   required from here
/usr/include/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<compiler::FormulaNode*&, 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<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> >, compiler::FormulaNode*(), 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>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >&)’
if (f(first, last, context, skipper))
                 ^~
In file included from /usr/include/boost/function/detail/maybe_include.hpp:43,
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 Main2.cpp:1:
/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<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<compiler::FormulaNode*&, 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::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, 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> >&’
In file included 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 Main2.cpp:1:
/usr/include/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 = const boost::spirit::unused_type; Skipper = boost::spirit::unused_type; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = 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>; T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/usr/include/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 = const boost::spirit::unused_type; Skipper = boost::spirit::unused_type; Attribute = const boost::spirit::unused_type; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>]’
/usr/include/boost/spirit/home/qi/skip_over.hpp:27:30:   required from ‘void boost::spirit::qi::skip_over(Iterator&, const Iterator&, const T&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >]’
/usr/include/boost/spirit/home/qi/parse.hpp:169:26:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
/usr/include/boost/spirit/home/qi/parse.hpp:197:32:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
Main2.cpp:49:83:   required from here
/usr/include/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::spirit::unused_type&, 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<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::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>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::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,
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 Main2.cpp:1:
/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<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::spirit::unused_type&, 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> >&’

When I replace "grammar.localSkipper" with "qi::space", it compiles without error. But of course, I don't have comment skipping.

I'm trying for the first time to write my own grammar with spirit::qi, and I don't succeed in integrating a skip parser that should ignore C style comments as well as whitespaces. Here's my source file (I reduced the grammar to just a few rules, in order to be more concise:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "formulaNode.h"

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;

using FormulaNodePtr = compiler::FormulaNode*;
using ExpressionPtr = compiler::Expression*;

template <typename Iterator>
struct ArithmeticGrammar : qi::grammar<Iterator, FormulaNodePtr(), qi::space_type> {
    ArithmeticGrammar() : ArithmeticGrammar::base_type(formula, "Formula") {
        using namespace qi;

        localSkipper = qi::space | ("/*" >> *(qi::char_ - "*/") >> "*/");

        formula = unsignedFactor [_val = _1];

        unsignedFactor =
            numericConstant [_val = phoenix::new_<compiler::Constant>(_1)];

        numericConstant = qi::as_string[
            qi::lexeme[  -qi::char_('-') >>
                (+qi::digit >> -(qi::char_('.') >> +qi::digit)) >>
                -(qi::char_('e') >> -qi::char_('-') >> +qi::digit) 
            ]];
    }

    qi::rule<Iterator, FormulaNodePtr(), qi::space_type> formula;
    qi::rule<Iterator, ExpressionPtr(), qi::space_type> unsignedFactor;
    qi::rule<Iterator, std::string(), qi::space_type> numericConstant;
    qi::rule<Iterator, qi::space_type> localSkipper;
};

// Parsing function
bool parseExpression(const std::string& input, FormulaNodePtr& result)
{
    using Iterator = std::string::const_iterator;
    ArithmeticGrammar<Iterator> grammar;

    Iterator it = input.begin();
    Iterator end = input.end();

    bool success = qi::phrase_parse(it, end, grammar, grammar.localSkipper, result);

    if (!success || it != end)
    {
        if (result == nullptr) {
            std::cout << "Parsing failed\n";
        }
        delete result;
        result = nullptr;
    }

    return success && (it == end);
}

int main()
{
    std::string input;
    std::cout << "Enter input: ";
    std::getline(std::cin, input);

    while (!input.empty()) {
        FormulaNodePtr result = nullptr;
        if (parseExpression(input, result))
        {
            std::cout << "Parsed successfully. Expression tree:" << std::endl;
            result->print(std::cout, 0);
            delete result;
        } else {
            std::cout << "Parsing failed. Please enter a valid expression." << std::endl;
        }
        std::getline(std::cin, input);
    }

    return EXIT_SUCCESS;
}

The way I use the skipper parser is taken from various internet examples. Yet when I try to compile this, I get this error message - can someone explain that to me?

g++ -std=c++11 -Wall -Wextra -pedantic Main2.cpp -o parser
In file included 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 Main2.cpp:1:
/usr/include/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<compiler::FormulaNode*&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >; Attribute = compiler::FormulaNode*; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = compiler::FormulaNode*(); 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::standard> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/usr/include/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<compiler::FormulaNode*&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >; Attribute = compiler::FormulaNode*; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, compiler::FormulaNode*(), 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>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/usr/include/boost/spirit/home/qi/parse.hpp:164:13:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
/usr/include/boost/spirit/home/qi/parse.hpp:197:32:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
Main2.cpp:49:83:   required from here
/usr/include/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<compiler::FormulaNode*&, 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<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> >, compiler::FormulaNode*(), 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>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >&)’
if (f(first, last, context, skipper))
                 ^~
In file included from /usr/include/boost/function/detail/maybe_include.hpp:43,
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 Main2.cpp:1:
/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<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<compiler::FormulaNode*&, 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::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, 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> >&’
In file included 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 Main2.cpp:1:
/usr/include/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 = const boost::spirit::unused_type; Skipper = boost::spirit::unused_type; Attribute = const boost::spirit::unused_type; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = 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>; T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/usr/include/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 = const boost::spirit::unused_type; Skipper = boost::spirit::unused_type; Attribute = const boost::spirit::unused_type; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>]’
/usr/include/boost/spirit/home/qi/skip_over.hpp:27:30:   required from ‘void boost::spirit::qi::skip_over(Iterator&, const Iterator&, const T&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >]’
/usr/include/boost/spirit/home/qi/parse.hpp:169:26:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
/usr/include/boost/spirit/home/qi/parse.hpp:197:32:   required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Expr = ArithmeticGrammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<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::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>; Attr = compiler::FormulaNode*]’
Main2.cpp:49:83:   required from here
/usr/include/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::spirit::unused_type&, 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<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::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>, boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::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,
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 Main2.cpp:1:
/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<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::spirit::unused_type&, 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> >&’

When I replace "grammar.localSkipper" with "qi::space", it compiles without error. But of course, I don't have comment skipping.

Share Improve this question edited Mar 12 at 17:00 miken32 42.8k16 gold badges125 silver badges174 bronze badges asked Mar 12 at 16:44 user29968769user29968769 232 bronze badges 4
  • Please use code block for error messages. – 3CxEZiVlQ Commented Mar 12 at 16:57
  • @miken32 This is a futile attempt to edit the error message - the indentation is lost when the OP has used the quotation block. – 3CxEZiVlQ Commented Mar 12 at 17:02
  • @3CxEZiVlQ sure but it's a slight improvement – miken32 Commented Mar 12 at 17:07
  • @3CxEZiVlQ Thank you for your hint; I'll do better with my next question. This was my first question and I got lost in the formatting tools. – user29968769 Commented Mar 13 at 10:57
Add a comment  | 

1 Answer 1

Reset to default 0

First, don't use raw pointers in semantic actions or as attribute types:

  • How can I use polymorphic attributes with boost::spirit::qi parsers?

Second, the skipper MUST be compatible with the rule's declared skipper type. See Boost spirit skipper issues. Most likely you will come across one of these asserts in the diagnostics:

        BOOST_STATIC_ASSERT_MSG(
            (is_convertible<Skipper const&, skipper_type>::value),
            "The passed skipper is not compatible/convertible to one "
            "that the rule was instantiated with");

In your code, the declared skipper type is qi::space_type BUT you try to pass localSkipper. Fixing the incorrect declaration of it without its own skipper:

qi::rule<Iterator> localSkipper;

Now fix the rules:

using Skipper = qi::rule<Iterator>;
qi::rule<Iterator, FormulaNodePtr(), Skipper> formula;
qi::rule<Iterator, ExpressionPtr(), Skipper>  unsignedFactor;

// lexemes
qi::rule<Iterator, std::string()> numericConstant;
Skipper                           localSkipper;

NOTE The numericConstant drops the skipper so it is implicitly a lexeme (see again above link). That means qi::lexeme[] can be avoided.

Consider replacing that rule with just numericConstant = qi::raw[ qi::double_ ];

Even better, do not expose the skipper at all, since it's not a "user-serviceable part":

private:
  using Skipper = qi::rule<Iterator>;
  qi::rule<Iterator, FormulaNodePtr(), Skipper> formula;
  qi::rule<Iterator, ExpressionPtr(), Skipper>  unsignedFactor;

  // lexemes
  qi::rule<Iterator, std::string()> numericConstant;
  Skipper                           localSkipper;

Now to avoid dangling references you have to very subtly alias the localSkipper in qi::skip:

start = qi::skip(localSkipper.alias())[formula];

Live Demo

Catering for all of the above (and missing code including a pointer conversion):

Live On Coliru

#define BOOST_ALLOW_DEPRECATED_HEADERS
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>

namespace compiler {
    struct Expression {
        virtual ~Expression() = default;
        virtual void print(std::ostream& os, int indent) const = 0;
    };

    struct Constant : Expression {
        Constant(const std::string& value) : value(value) {}

        void print(std::ostream& os, int indent) const override {
            os << std::string(indent, ' ') << "Constant: " << value << std::endl;
        }

        std::string value;
    };

    struct FormulaNode {
        FormulaNode(Expression* expression) : expression(expression) {}

        void print(std::ostream& os, int indent) const { expression->print(os, indent); }

        std::unique_ptr<Expression> expression;
    };
}

namespace qi      = boost::spirit::qi;
namespace phoenix = boost::phoenix;

using FormulaNodePtr = compiler::FormulaNode*;
using ExpressionPtr  = compiler::Expression*;

template <typename Iterator> //
struct ArithmeticGrammar : qi::grammar<Iterator, FormulaNodePtr()> {
    ArithmeticGrammar() : ArithmeticGrammar::base_type(start) {
        using namespace qi::labels;

        start          = qi::skip(localSkipper.alias())[formula];
        formula        = unsignedFactor[_val = phoenix::new_<compiler::FormulaNode>(_1)];
        unsignedFactor = numericConstant[_val = phoenix::new_<compiler::Constant>(_1)];

        numericConstant = qi::as_string[
              -qi::char_('-') >>
                (+qi::digit >> -(qi::char_('.') >> +qi::digit)) >>
                -(qi::char_('e') >> -qi::char_('-') >> +qi::digit) 
            ];
    }

  private:
    using Skipper = qi::rule<Iterator>;
    qi::rule<Iterator, FormulaNodePtr()>          start;
    qi::rule<Iterator, FormulaNodePtr(), Skipper> formula;
    qi::rule<Iterator, ExpressionPtr(), Skipper>  unsignedFactor;

    // lexemes
    qi::rule<Iterator, std::string()> numericConstant;
    Skipper localSkipper = qi::space | "/*" >> *(qi::char_ - "*/") >> "*/";
};

// Parsing function
bool parseExpression(std::string const& input, FormulaNodePtr& result) {
    using Iterator = std::string::const_iterator;
    static ArithmeticGrammar<Iterator> const grammar;

    if (!parse(begin(input), end(input), grammar >> qi::eoi, result)) {
        delete result;
        result = nullptr;
        return false;
    }

    return true;
}

int main() {
    std::cout << "Enter input: ";
    for (std::string input; getline(std::cin, input); std::cout<<"Enter input: ") {
        if (input.empty())
            break;

        FormulaNodePtr result = nullptr;
        if (parseExpression(input, result)) {
            std::cout << "Parsed successfully. Expression tree:" << std::endl;
            result->print(std::cout, 0);
            delete result;
        } else {
            std::cout << "Parsing failed. Please enter a valid expression." << std::endl;
        }
    }
}

Printing e.g.

发布评论

评论列表(0)

  1. 暂无评论