【问题标题】:boost spirit parser look ahead parsing提升精神解析器前瞻解析
【发布时间】:2017-05-24 22:31:32
【问题描述】:

我想解析一个格式如下的字符串: 字符串编号。 我不知道如何为 boost qi 解析器编写语法。

现在我的语法如下: +qi::char_("a-zA-Z0-9_-") >> lit('_') >> qi::int_

但看起来它不起作用。 示例字符串是: ab_bcd_123 --> 令牌(ab_bcd,123) ab_123 ---> 记号(ab, 123)

【问题讨论】:

    标签: c++ parsing c++11 boost boost-spirit


    【解决方案1】:

    但看起来它不起作用。

    那是因为0-9 吃掉了数字。这应该有效:

    +qi::char_("a-zA-Z_") >> '_' >> qi::uint_
    

    如果您也想允许ab-3_bcd_123,请设备先行检测您是否已到达终点,例如eoi:

    qi::raw[
        (+qi::alnum|'-') % (!('_' >> qi::uint_ >> eoi))
    ] >> '_' >> qi::uint_
    

    虽然到现在为止,我都会忘记它并做:

    qi::lexeme [ +qi::char_("a-zA-Z0-9_-") ] [ _val = split_ident(_1) ];
    

    Live On Coliru

    #include <boost/fusion/adapted/std_pair.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace qi = boost::spirit::qi;
    
    using NumberedIdent = std::pair<std::string, int>;
    
    namespace Demo {
        struct SplitIdent {
            NumberedIdent operator()(std::vector<char> const& v, bool& pass) const {
                std::string s(v.begin(), v.end());
                try {
                    auto n = s.rfind('_');
                    pass = n > 0;
                    return { s.substr(0, n), std::stoi(s.substr(n+1)) };
                } catch(...) { 
                    pass = false; return {s, 0}; 
                }
            }
        };
    
        using It = std::string::const_iterator;
        using namespace qi;
    
        static boost::phoenix::function<SplitIdent> split_ident;
    
        rule<It, NumberedIdent()> const rule
            = lexeme [ +char_("a-zA-Z0-9_-") ] [ _val = split_ident(_1, _pass) ];
    }
    
    int main() {
        for (std::string const input : {
               "ab_bcd_123",
               "ab-3_bcd_123 = 'something'",
               // failing:
               "ab_bcd_123_q = 'oops'",
               "ab_bcd_123_ = 'oops'",
               "_123 = 'oops'",
               "_",
               "q",
               ""
               }) 
        {
            NumberedIdent parsed;
            Demo::It f = input.begin(), l = input.end();
    
            bool ok = parse(f, l, Demo::rule, parsed);
    
            if (ok) {
                std::cout << "SUCCESS: ['" << parsed.first << "', " << parsed.second << "]\n";
            } else {
                std::cout << "parse failed ('" << input << "')\n";
            }
    
            if (f != l) {
                std::cout << "  remaining input '" << std::string(f,l) << "'\n";
            }
        }
    
    }
    

    打印:

    SUCCESS: ['ab_bcd', 123]
    SUCCESS: ['ab-3_bcd', 123]
      remaining input ' = 'something''
    

    然后是所有失败的测试用例(按设计):

    parse failed ('ab_bcd_123_q = 'oops'')
      remaining input 'ab_bcd_123_q = 'oops''
    parse failed ('ab_bcd_123_ = 'oops'')
      remaining input 'ab_bcd_123_ = 'oops''
    parse failed ('_123 = 'oops'')
      remaining input '_123 = 'oops''
    parse failed ('_')
      remaining input '_'
    parse failed ('q')
      remaining input 'q'
    parse failed ('')
    

    【讨论】:

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