编译简单的提升精神语法

时间:2012-02-23 14:24:38

标签: c++ parsing mingw boost-spirit

我无法获得一个小的boost :: spirit语法来编译。这是一个较大的语法的一小部分,我遇到了麻烦,我正在尝试测试较小的部分来发现我的问题。 基本上这个语法应该做的是解析一个double值,它有任意数量的前导/尾随空格。但是当我尝试编译时,我得到了一些我不理解的问题清单。欢迎任何帮助! 代码: 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;
}

当我尝试编译时,我收到以下错误:

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> > >()'

请注意,我正在Windows 7计算机上使用boost 1.48.0和mingw 4.6.1进行编译。

2 个答案:

答案 0 :(得分:7)

更改此行:

point_double_grammar<std::string::iterator> point_grammar();

要:

point_double_grammar<std::string::iterator> point_grammar;

您已声明一个函数不带任何返回语法的参数。相反,你想要实例化语法。

答案 1 :(得分:3)

Sharth已经回答了你的问题,你当然应该接受这个答案。

我想分享一些其他的东西,你可能会觉得有帮助。

  • 正如我所提到的:格式化代码(代码适用于人类)
  • 尝试使用循环而不是复制代码。你没有解析双打列表。你正在解析一个双倍,5次
  • 避免使用C-isms(在顶部声明并初始化?)
  • 看看Qi Skippers:你手动'忽略'空白。齐为此目的有船长(见下面样本中的qi :: phrase_parse)
  • 考虑使用Boost Karma进行输出生成。至少使用<iomanip>来控制输出格式(请参阅下面的std::setprecision

以下是完整示例

#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;
    }
}

使用C ++ 11,你甚至可以写:

for (const std::string input : { 
        "575040.3400", "117380.1200", "-001.22916765", "063.39171738", "2.5" })
{
    auto it = input.begin(), last = input.end();

等。对于记录,输出是:

575040.3400 == 575040.34
117380.1200 == 117380.12
-001.22916765 == -1.22916765
063.39171738 == 63.39171738
2.5 == 2.5

如果没有std::setprecision(10),则输出将是,例如第一行575040.3400 == 575040考虑使用Boost Karma进行输出生成