【问题标题】:Template compilation errors with Boost::Spirit::Qi for simple grammarBoost::Spirit::Qi 简单语法的模板编译错误
【发布时间】:2015-03-24 00:04:59
【问题描述】:

我正在尝试解析语法:

@ ( )  

使用 Boost::Spirit::Qi。

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

这是我在 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 ==========

ma​​in.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。

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

我在解析器函数中正确使用语法吗?

【问题讨论】:

    标签: c++ parsing boost grammar boost-spirit-qi


    【解决方案1】:

    编译器错误直接将你带到这一行:

        // 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,最好读取模板实例化跟踪中出现的块周围的 cmets!

    问题显然是你需要通过一个船长。你打算这样做:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多