代码之家  ›  专栏  ›  技术社区  ›  pschulz

提神词及其属性

  •  1
  • pschulz  · 技术社区  · 6 年前

    我正在使用一个跳过空白的解析器。有一次,我不想跳过,所以我想用 qi::lexeme lexeme 处理好了吗?

    下面是我想做的一个例子:

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/include/vector.hpp>
    
    namespace qi = boost::spirit::qi;
    namespace fu = boost::fusion;
    
    struct printer_type
    {
        void operator() (int i) const
        {
            std::cout << i << ' ';
        }
    
        void operator() (std::string s) const
        {
            std::cout << '"' << s << '"' << ' ';
        }
    
    } printer;
    
    int main() {
        for (std::string str : { "1foo 13", "42 bar 13", "13cheese 8", "101pencil13" }) {
            auto iter = str.begin(), end = str.end();
    
            qi::rule<std::string::iterator, qi::blank_type, fu::vector<int, std::string, int>()> parser = qi::int_ >> +qi::alpha >> qi::int_;
    
            fu::vector<int, std::string, int> result;
            bool r = qi::phrase_parse(iter, end, parser, qi::blank, result);
    
            std::cout << " --- " << std::quoted(str) << " --- ";
            if (r) {
                std::cout << "parse succeeded: ";
                fu::for_each(result, printer);
                std::cout << '\n';
            } else {
                std::cout << "parse failed.\n";
            }
    
            if (iter != end) {
                std::cout << " Remaining unparsed: " << std::string(iter, str.end()) << '\n';
            }
        }
    }
    

    注意这一行:

    qi::rule<std::string::iterator, qi::blank_type, fu::vector<int, std::string, int>()> parser = 
                          qi::int_ >> +qi::alpha >> qi::int_;
    

    好的,我们需要一个int,然后是一个字符串,然后是一个int。但是,我不想跳过第一个int和字符串之间的空白,这里不能有空格。如果我使用lexeme,合成的属性就会混乱。

    无障碍跑步 词素 给出以下结果:

    --- "1foo 13" --- parse succeeded: 1 "foo" 13 
     --- "42 bar 13" --- parse succeeded: 42 "bar" 13 
     --- "13cheese 8" --- parse succeeded: 13 "cheese" 8 
     --- "101pencil13" --- parse succeeded: 101 "pencil" 13 
    

    所以一切都很好,这很好。然而,第二个例子( 42 bar 13 词素 在第一个int和字符串周围( qi::lexeme[qi::int_ >> +qi::alpha] >> qi::int_;

    " 0  "1foo 13" --- parse succeeded: 1 "
     --- "42 bar 13" --- parse failed.
     Remaining unparsed: 42 bar 13
     --- "13cheese 8" --- parse succeeded: 13 " 0 
    " 0  "101pencil13" --- parse succeeded: 101 "
    

    旁白:我想略去 词素 并定义一个不跳过的子规则。在这种情况下,如何指定属性?

    然后子规则具有 fusion::vector<int, std::string>() fusion::vector<int, std::string, int>() fusion::vector<fusion::vector<int, std::string>, int>() (反正也不会编译)。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Nikita Kniazev    6 年前

    使用 no_skip 指令: qi::int_ >> qi::no_skip[+qi::alpha] >> qi::int_

     --- "1foo 13" --- parse succeeded: 1 "foo" 13 
     --- "42 bar 13" --- parse failed.
     Remaining unparsed: 42 bar 13
     --- "13cheese 8" --- parse succeeded: 13 "cheese" 8 
     --- "101pencil13" --- parse succeeded: 101 "pencil" 13 
    

    https://wandbox.org/permlink/PdS14l0b3qjJwz5S


    所以。。。。什么!?我一点也不知道发生了什么事,我很高兴有什么启示:)

    qi::lexeme[qi::int_ >> +qi::alpha] >> qi::int_ tuple<tuple<int,std::string>,int> 你已经触发了 trac 8013 这里有两次bug/misfeature(第一次用于整个序列解析器,第二次用于lexeme内的序列)`。