【问题标题】:Prevent the Boost Spirit Symbol parser from accepting a keyword too early防止 Boost Spirit Symbol 解析器过早接受关键字
【发布时间】:2014-03-24 11:41:00
【问题描述】:

如何防止 Boost Spirit Symbol 解析器在以有效关键字(符号)开头时接受关键字(符号)。我希望该构造无法整体解析“ONEMORE”并且无法成功解析“ONE”,因为这是一个有效的关键字,然后在“MORE”上失败。

下面是代码的实际输出:

Keyword as a number: 1
Keyword as a number: 2
Keyword as a number: 1
Invalid keyword: MORETHREE

这就是我喜欢的样子:

Keyword as a number: 1
Keyword as a number: 2
Invalid keyword: ONEMORE
Keyword as a number: 3

代码只是说明问题的一个示例。

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

void printNumber( unsigned u )
{
    cout << "Keyword as a number: " << u << endl;
}

void printInvalidKeyword( const string &s )
{
    cout << "Invalid keyword: " << s << endl;
}

template <typename Iterator>
struct keyword_parser : qi::grammar<Iterator, ascii::space_type>
{
    struct mySymbols_ : qi::symbols<char, unsigned>
    {
        mySymbols_()
        {
            add
            ("ONE"   , 1)
            ("TWO"   , 2)
            ("THREE" , 2)
            ;
        }

    } mySymbols;

    keyword_parser() : keyword_parser::base_type(start)
    {
        using qi::_1;
        using qi::raw;
        using ascii::char_;

        start %= *(
                   mySymbols[&printNumber]
                    |
                   invalid[&printInvalidKeyword]
                   );

        invalid = +char_;

    }

    qi::rule<Iterator, ascii::space_type> start;
    qi::rule<Iterator, std::string(), ascii::space_type> invalid;
};

int main()
{
    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef keyword_parser<iterator_type> keyword_parser;

    std::string s = "ONE TWO ONEMORE THREE";
    iterator_type b = s.begin();
    iterator_type e = s.end();
    phrase_parse(b, e, keyword_parser(), space);

    return 0;
}

【问题讨论】:

    标签: c++ boost symbols boost-spirit


    【解决方案1】:

    qi::repository::distinct或自己采取一些措施:

    start %= *(
               keyword  [cout << val("Keyword as a number: ") << _1 << endl]
             | invalid  [cout << val("Invalid keyword: ")     << _1 << endl]
             );
    
    keyword = mySymbols >> !(char_("a-zA-Z0-9_"));
    
    invalid = +ascii::graph;
    

    被声明为的规则

    qi::rule<Iterator, ascii::space_type> start;
    
    // lexemes do not ignore embedded skippables
    qi::rule<Iterator, int()> keyword;
    qi::rule<Iterator, std::string()> invalid;
    

    Live On Coliru

    打印:

    Keyword as a number: 1
    Keyword as a number: 2
    Invalid keyword: ONEMORE
    Keyword as a number: 2
    

    完整来源:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <iostream>
    #include <string>
    
    using namespace std;
    namespace qi    = boost::spirit::qi;
    namespace phx   = boost::phoenix;
    namespace ascii = boost::spirit::ascii;
    
    template <typename Iterator>
    struct keyword_parser : qi::grammar<Iterator, ascii::space_type>
    {
        struct mySymbols_ : qi::symbols<char, unsigned>
        {
            mySymbols_()
            {
                add
                ("ONE"   , 1)
                ("TWO"   , 2)
                ("THREE" , 2)
                ;
            }
    
        } mySymbols;
    
        keyword_parser() : keyword_parser::base_type(start)
        {
            using qi::_1;
            using ascii::char_;
            using phx::val;
    
            start %= *(
                       keyword  [cout << val("Keyword as a number: ") << _1 << endl]
                     | invalid  [cout << val("Invalid keyword: ")     << _1 << endl]
                     );
    
            keyword = mySymbols >> !(char_("a-zA-Z0-9_"));
    
            invalid = +ascii::graph;
    
        }
    
        qi::rule<Iterator, ascii::space_type> start;
        // lexemes do not ignore embedded skippables
        qi::rule<Iterator, int()> keyword;
        qi::rule<Iterator, std::string()/*IMPLICIT LEXEME:, ascii::space_type*/> invalid;
    };
    
    int main()
    {
        using boost::spirit::ascii::space;
        typedef std::string::const_iterator iterator_type;
        typedef keyword_parser<iterator_type> keyword_parser;
    
        std::string s = "ONE TWO ONEMORE THREE";
        iterator_type b = s.begin();
        iterator_type e = s.end();
        phrase_parse(b, e, keyword_parser(), space);
    
        return 0;
    }
    

    【讨论】:

    • 有些事情很简单,除非你看不到它:-) 谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 2015-01-25
    • 1970-01-01
    相关资源
    最近更新 更多