【问题标题】:Boost Spirit failing on empty string inputBoost Spirit 在空字符串输入上失败
【发布时间】:2017-10-31 15:55:58
【问题描述】:

我正在尝试解析以下字符串并提取括号内的部分。

此字符串失败:

_找东西', '')_ 应该返回 part1 = '某事' 第 2 部分 = ''

这个字符串通过了:

_找东西', '*')_ 退货 part1 = '某事' 第 2 部分 = '*'

我认为问题在于“quoted_string”

    find_parser() : find_parser::base_type(start)
    {
        using qi::lit;
        using qi::lexeme;
        using standard_wide::char_;

        /// simple quoted string.
        quoted_string %= lexeme['\'' >> +(char_ - '\'') >> '\''];

        start %=
            -(lit("$(")) // optional
            >> lit("_FIND")
            >> '('
            >> quoted_string
            >> -(',' >> quoted_string) // 2nd parameter optional
            >> ")_"
            >> -(lit(")")) // optional
            ;
    }

我尝试像这样添加一个“空”字符串词素,但它不起作用。

        quoted_string %= lexeme['\'' >> +(char_ - '\'') >> '\''];
        empty_quoted_string %= lexeme['\'' >> +(qi::space - '\'') >> '\''];

        start %=
            lit("_FIND")
            >> '('
            >> (quoted_string|empty_quoted_string)
            >> -(',' >> (quoted_string|empty_quoted_string)) // 2nd parameter optional
            >> ")_"
            ;

我知道这一定是一件简单的事情,但我不能指手画脚。

感谢您的任何意见、提示或提示。

【问题讨论】:

    标签: c++11 boost-spirit


    【解决方案1】:
      lexeme['\'' >> +(char_ - '\'') >> '\''];
    

    +p 表示p 必须是match one-or-more times。如果必须接受空字符串,请使用Kleene-star operator, which allows zero-or-more matches

      lexeme['\'' >> *(char_ - '\'') >> '\''];
    

    现场演示

    解决了一些低效/风格问题

    还有一个错误,"$(_FIND('')""_FIND('')" 会被解析为“正确”

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/adapted/std_pair.hpp>
    
    using Params = std::pair<std::string, std::string>;
    
    namespace qi = boost::spirit::qi;
    
    template <typename It> 
    struct find_parser : qi::grammar<It, Params()> {
        find_parser() : find_parser::base_type(start)
        {
            using namespace qi;
    
            start = skip(space) [ "$(" >> find >> ")" | find ];
    
            find
                = '_' >> lit("FIND") >> lit('(')
                >> quoted_string >> -(',' >> quoted_string) // 2nd parameter optional
                >> ')' >> '_'
                ;
    
            quoted_string = "'" >> *~char_("'") >> "'";
    
            BOOST_SPIRIT_DEBUG_NODES((start)(find)(quoted_string))
        }
    
      private:
        qi::rule<It, Params()> start;
    
        // rules with skipper
        qi::rule<It, Params(), qi::space_type> find;
    
        // implicit lexemes
        qi::rule<It, std::string()> quoted_string;
    };
    
    int main() {
        using It = std::string::const_iterator;
        find_parser<It> const p;
    
        for (std::string const input : {
                "_FIND('Something', 'Something else')_",
                "_ FIND('Something', 'Something else') _",
                "$(_FIND('Something', 'Something else')_)",
                "$( _FIND( 'Something', 'Something else' )_ )",
                // second arg empty
                "_FIND('Something', '')_",
                "_ FIND('Something', '') _",
                "$(_FIND('Something', '')_)",
                "$( _FIND( 'Something', '' )_ )",
                // optional args omitted
                "_FIND('Something')_",
                "_ FIND('Something') _",
                "$(_FIND('Something')_)",
                "$( _FIND( 'Something' )_ )",
                })
        {
            std::cout << "-------- " << input << " ------------\n";
    
            It f = input.begin(), l = input.end();
            Params parsed;
            if (parse(f, l, p, parsed))
                std::cout << "Parsed: '" << parsed.first << "', '" << parsed.second << "'\n";
            else
                std::cout << "Parsing failed\n";
    
            if (f!=l)
                std::cout << "  -- Remaining unparsed: '" << std::string(f,l) << "'\n";
        }
    }
    

    【讨论】:

    • 哦!谢谢!!它是 * 而不是 +(我多么讨厌这样的东西)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多