I'm having trouble getting a small boost::spirit grammar to compile. It's a small part of a larger grammar that I'm having trouble with and I'm trying to test smaller parts to find my problem. Basicly what this grammar should do is parse a double value which has any number of leading/trailing spaces. However when I try to compile I get a whole list of problems which I don't understand. Any help would be welcome! The code: grammar.h
#ifndef GRAMMAR_H
#define GRAMMAR_H
#include <boost/spirit/include/qi.hpp>
template <typename Iterator>
struct point_double_grammar : boost::spirit::qi::grammar<Iterator, double()>
{
/**
* Constructor used to create the grammar.
* @param is_point boolean indicating if the point is used as decimal.
* @author Luc Kleeven
**/
point_double_grammar() : point_double_grammar::base_type(d)
{
d = *boost::spirit::qi::lit(' ') >> boost::spirit::qi::double_ >> *boost::spirit::qi::lit(' ');
}
boost::spirit::qi::rule<Iterator, double()> d;
};
#endif // GRAMMAR_H
main.cpp
#include "grammar.h"
int main(int argc, char *argv[])
{
point_double_grammar<std::string::iterator> point_grammar();
bool result = false;
double d = 0.0;
std::string p1 = "575040.3400";
std::string p2 = "117380.1200";
std::string p3 = "-001.22916765";
std::string p4 = "063.39171738";
std::string p5 = "2.5";
std::string::iterator it;
std::string::iterator last;
it = p1.begin();
last = p1.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it ==
last);
if(result)
{
std::cout << p1 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p2.begin();
last = p2.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it ==
last);
if(result)
{
std::cout << p2 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p3.begin();
last = p3.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p3 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p4.begin();
last = p4.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p4 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p5.begin();
last = p5.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p5 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
return EXIT_SUCCESS;
}
When I try to compile I get the following errors:
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/detail/parse_auto.hpp:14:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/auto.hpp:16,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:15,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp: In function 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]':
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:83:9: error: no matching function for call to 'assertion_failed(mpl_::failed************ (boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]::error_invalid_expression::************)(point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > > (*)()))'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:83:9: note: candidate is:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/mpl/assert.hpp:79:48: note: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/expr.hpp:6:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/expr.hpp:120,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/core.hpp:17,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/proto.hpp:12,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/support/meta_compiler.hpp:19,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/meta_compiler.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/action/action.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/action.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp: At global scope:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp: In instantiation of 'boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>':
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/utility/enable_if.hpp:59:10: instantiated from 'boost::disable_if<boost::proto::is_expr<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>, void>, void>'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/support/meta_compiler.hpp:212:16: instantiated from 'boost::spirit::result_of::compile<boost::spirit::qi::domain, point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), boost::spirit::unused_type, void>'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:86:82: instantiated from 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]'
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp:50:49: error: field 'boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>::child0' invalidly declared function type
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/detail/parse_auto.hpp:14:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/auto.hpp:16,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:15,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp: In function 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]':
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:86:82: error: request for member 'parse' in 'boost::spirit::compile [with Domain = boost::spirit::qi::domain, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), typename boost::spirit::result_of::compile<Domain, Expr, boost::spirit::unused_type>::type = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > > (&)()]((* & expr))', which is of non-class type 'point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()'
Note that I'm compiling using boost 1.48.0 and mingw 4.6.1 on a windows 7 machine.
Change this line:
point_double_grammar<std::string::iterator> point_grammar();
To:
point_double_grammar<std::string::iterator> point_grammar;
You've declared a function taking no arguments that returns a grammar. Instead, you want to instantiate the grammar.
Sharth has already answered your question, you should accept that answer of course.
I wanted to share a few other things, you might find helpful.
<iomanip>
to control the output format (see std::setprecision
below)Here is the full example
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator, typename Skipper>
struct point_double_grammar : qi::grammar<Iterator, double(), Skipper>
{
point_double_grammar() : point_double_grammar::base_type(d)
{
d = qi::double_;
}
qi::rule<Iterator, double(), Skipper> d;
};
static const char *const testcases[] = {
"575040.3400",
"117380.1200",
"-001.22916765",
"063.39171738",
"2.5",
NULL
};
int main()
{
typedef std::string::const_iterator It;
point_double_grammar<It, qi::space_type> point_grammar;
for(const char* const* it=testcases; *it; ++it)
{
const std::string input(*it);
It it = input.begin(), last = input.end();
double d = 0.0;
bool result = (qi::phrase_parse(it, last, point_grammar, qi::space, d) && it ==
last);
if(result)
std::cout << input << " == "
<< std::setprecision(10) << d << std::endl;
else
std::cerr << "Parsing failed!" << std::endl;
}
}
With C++11 you'd even write:
for (const std::string input : {
"575040.3400", "117380.1200", "-001.22916765", "063.39171738", "2.5" })
{
auto it = input.begin(), last = input.end();
etc. For the record, the output is:
575040.3400 == 575040.34
117380.1200 == 117380.12
-001.22916765 == -1.22916765
063.39171738 == 63.39171738
2.5 == 2.5
Without std::setprecision(10)
the output would be, e.g. 575040.3400 == 575040
for the first line. Consider using Boost Karma for output generation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With