简单语法的 Boost::Spirit::Qi 模板编译错误

Template compilation errors with Boost::Spirit::Qi for simple grammar

我正在尝试解析语法:

@ ( )  

使用 Boost::Spirit::Qi。

我使用 phrase_parse 进行了解析,现在我正在创建语法 class(一次一个步骤)。

这是我在 Visual Studio 2010 年(在 Windows 7 上)的失败消息:

1>------ Build started: Project: Event_Grammar, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\boost_1_57_0\boost\spirit\home\qi\nonterminal\rule.hpp(304): error C2664: 'bool boost::function4<R,T0,T1,T2,T3>::operator ()(T0,T1,T2,T3) const' : cannot convert parameter 4 from 'const boost::spirit::unused_type' to 'const boost::spirit::qi::char_class<Tag> '
1>          with
1>          [
1>              R=bool,
1>              T0=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>> &,
1>              T1=const std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>> &,
1>              T2=boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type &,boost::fusion::nil_>,boost::fusion::vector0<>> &,
1>              T3=const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,boost::spirit::char_encoding::ascii>> &
1>          ]
1>          and
1>          [
1>              Tag=boost::spirit::tag::char_code<boost::spirit::tag::space,boost::spirit::char_encoding::ascii>
1>          ]
1>          Reason: cannot convert from 'const boost::spirit::unused_type' to 'const boost::spirit::qi::char_class<Tag>'
1>          with
1>          [
1>              Tag=boost::spirit::tag::char_code<boost::spirit::tag::space,boost::spirit::char_encoding::ascii>
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          c:\boost_1_57_0\boost\spirit\home\qi\reference.hpp(43) : see reference to function template instantiation 'bool boost::spirit::qi::rule<Iterator,T1,T2,T3,T4>::parse<Context,Skipper,Attribute>(Iterator &,const Iterator &,Context &,const Skipper &,Attribute &) const' being compiled
1>          with
1>          [
1>              Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,
1>              T1=boost::spirit::ascii::space_type,
1>              T2=boost::spirit::unused_type,
1>              T3=boost::spirit::unused_type,
1>              T4=boost::spirit::unused_type,
1>              Context=const boost::spirit::unused_type,
1>              Skipper=boost::spirit::unused_type,
1>              Attribute=const boost::spirit::unused_type
1>          ]
1>          c:\boost_1_57_0\boost\spirit\home\qi\detail\parse.hpp(46) : see reference to function template instantiation 'bool boost::spirit::qi::reference<Subject>::parse<Iterator,const boost::spirit::unused_type,boost::spirit::unused_type,const boost::spirit::unused_type>(Iterator &,const Iterator &,Context &,const Skipper &,Attribute &) const' being compiled
1>          with
1>          [
1>              Subject=const boost::spirit::qi::rule<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,boost::spirit::ascii::space_type,boost::spirit::unused_type,boost::spirit::unused_type,boost::spirit::unused_type>,
1>              Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,
1>              Context=const boost::spirit::unused_type,
1>              Skipper=boost::spirit::unused_type,
1>              Attribute=const boost::spirit::unused_type
1>          ]
1>          c:\boost_1_57_0\boost\spirit\home\qi\detail\parse_auto.hpp(166) : see reference to function template instantiation 'bool boost::spirit::qi::detail::parse_impl<Expr>::call<Iterator>(Iterator &,Iterator,const Expr &)' being compiled
1>          with
1>          [
1>              Expr=Event_Grammar<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,boost::spirit::ascii::space_type>,
1>              Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
1>          ]
1>          c:\mks_sandboxes\script_compiler_dissector\shared libraries\multiple platform\script language\src\event_grammar\src\event_parser.hpp(22) : see reference to function template instantiation 'bool boost::spirit::qi::parse<Iterator,Event_Grammar<Iterator,Skipper>>(Iterator &,Iterator,Expr &)' being compiled
1>          with
1>          [
1>              Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,
1>              Skipper=boost::spirit::ascii::space_type,
1>              Expr=Event_Grammar<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>,boost::spirit::ascii::space_type>
1>          ]
1>          c:\mks_sandboxes\script_compiler_dissector\shared libraries\multiple platform\script language\src\event_grammar\src\main.cpp(41) : see reference to function template instantiation 'bool Event_Parser<std::_String_const_iterator<_Elem,_Traits,_Alloc>>(Iterator,Iterator)' being compiled
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Alloc=std::allocator<char>,
1>              Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

main.cpp:

/*!
 *  \file   main.cpp
 *  \brief  This file contains code to validate the Script Compiler
 *          Event grammar.
 *  \note   This project uses the Boost::Spirit library for parsing.
 */
#include <iostream>
#include <string>
#include <cstdlib>

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

#include "event_parser.hpp"

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

using qi::double_;
using qi::_1;
using ascii::space;
using ascii::char_;
using phoenix::ref;
using qi::phrase_parse;

int main(void)
{
    const char  program_header[] =
        "\n"
        "Event Grammar Tester:\n"
        "    A program to validate the grammar for\n"
        "    a Script Language Event.\n"
        "\n";

    std::cout.write(program_header, sizeof(program_header) - 1);

    const std::string   parse_test_string = "@ ( )";
    std::string         token_names;
    bool result = Event_Parser(parse_test_string.begin(), parse_test_string.end());

    std::cout << "Parsing ";
    if (result)
    {
        std::cout << "succeeded";
    }
    else
    {
        std::cout << "failed";
    }
    std::cout << " for statement \""
              << parse_test_string
              << "\"\n";

    std::cout << "\nPaused.  Press Enter to continue.\n";
    std::cin.ignore(1000000, '\n');

    return EXIT_SUCCESS;
}

event_parser.hpp

/*!
 *  \file   event_parser.hpp
 *  \brief  This file defines a parser Script Language Events, this is the root.
 *  \note   This file should be used with Boost::Spirit parsers.
 */
#ifndef EVENT_PARSER_HPP
#define EVENT_PARSER_HPP
#include "event_grammar.hpp"

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

template <typename Iterator>
bool
Event_Parser(Iterator first, Iterator last)
{
    using qi::parse;
    using ascii::space;
    using ascii::char_;

    Event_Grammar<Iterator, ascii::space_type>  parser;
    bool result = parse(first, last, parser);
    if (first != last)
        return false;
    return result;
}

#endif // EVENT_PARSER_HPP

event_grammar.hpp

/*!
 *  \file   event_grammar.hpp
 *  \brief  This class defines the grammar for the Script Language Events.
 *  \note   This class uses features from Boost::Spirit.
 */
#ifndef EVENT_GRAMMAR_HPP
#define EVENT_GRAMMAR_HPP

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


template <typename Iterator, typename Skipper>
struct Event_Grammar
    : boost::spirit::qi::grammar<Iterator, Skipper>
{
    Event_Grammar() : Event_Grammar::base_type(start)
        {
            using boost::spirit::ascii::char_;
            using boost::spirit::qi::eps;

            start = 
                (
                    char_('@') >> char_('(') >> char_(')')
                )
                ;

        }
    boost::spirit::qi::rule<Iterator, Skipper> start;
};


#endif // EVENT_GRAMMAR_HPP

我只是在寻找解析器的通过或失败。

我正在使用 Boost 1.57.0。

我的语法结构中缺少什么?

我是否正确使用了解析器函数中的语法?

编译器错误会将您直接引导至此行:

    // If you are seeing a compilation error here stating that the
    // fourth parameter can't be converted to a required target type
    // then you are probably trying to use a rule or a grammar with
    // an incompatible skipper type.
    if (f(first, last, context, skipper))

对于 Spirit,阅读模板实例化跟踪中出现的块周围的注释是个好主意!

问题很明显,你需要通过船长。您正计划这样做:

bool result = qi::phrase_parse(first, last, parser, ascii::space);

Live On Coliru

/*!
 *  \file   event_grammar.hpp
 *  \brief  This class defines the grammar for the Script Language Events.
 *  \note   This class uses features from Boost::Spirit.
 */
#ifndef EVENT_GRAMMAR_HPP
#define EVENT_GRAMMAR_HPP

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

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


template <typename Iterator, typename Skipper>
struct Event_Grammar
    : boost::spirit::qi::grammar<Iterator, Skipper>
{
    Event_Grammar() : Event_Grammar::base_type(start)
        {
            using boost::spirit::ascii::char_;
            using boost::spirit::qi::eps;

            start = 
                (
                    char_('@') >> char_('(') >> char_(')')
                )
                ;

        }
    boost::spirit::qi::rule<Iterator, Skipper> start;
};


#endif // EVENT_GRAMMAR_HPP

/*!
 *  \file   event_parser.hpp
 *  \brief  This file defines a parser Script Language Events, this is the root.
 *  \note   This file should be used with Boost::Spirit parsers.
 */
#ifndef EVENT_PARSER_HPP
#define EVENT_PARSER_HPP
//#include "event_grammar.hpp"

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

template <typename Iterator>
bool Event_Parser(Iterator first, Iterator last)
{
    using ascii::space;
    using ascii::char_;

    Event_Grammar<Iterator, ascii::space_type>  parser;
    bool result = qi::phrase_parse(first, last, parser, ascii::space);
    if (first != last)
        return false;
    return result;
}

#endif //ndef EVENT_PARSER_HPP
/*!
 *  \file   main.cpp
 *  \brief  This file contains code to validate the Script Compiler
 *          Event grammar.
 *  \note   This project uses the Boost::Spirit library for parsing.
 */
#include <iostream>
#include <string>
#include <cstdlib>

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

//#include "event_parser.hpp"

using qi::double_;
using qi::_1;
using ascii::space;
using ascii::char_;
using phoenix::ref;
using qi::phrase_parse;

int main(void)
{
    const char  program_header[] =
        "\n"
        "Event Grammar Tester:\n"
        "    A program to validate the grammar for\n"
        "    a Script Language Event.\n"
        "\n";

    std::cout.write(program_header, sizeof(program_header) - 1);

    const std::string   parse_test_string = "@ ( )";
    std::string         token_names;
    bool result = Event_Parser(parse_test_string.begin(), parse_test_string.end());

    std::cout << "Parsing ";
    if (result)
    {
        std::cout << "succeeded";
    }
    else
    {
        std::cout << "failed";
    }
    std::cout << " for statement \""
              << parse_test_string
              << "\"\n";

    return EXIT_SUCCESS;
}