簡體   English   中英

如何編寫一個boost :: spirit :: qi解析器來做什么? 在正則表達式中?

[英]How to write a boost::spirit::qi parser to do what '?' does in regex?

假設我們有一個正則表達式“ start :( ?:([0-9] {1,2}))?([0-9]。*)”。

會匹配

std::string string1 = "start: 01 0ab";

std::string string2 = "start: 0ab";

我們還可以分別獲取2個匹配的字符串。

我嘗試使用boost :: spirit :: qi解析器來解析string2,但它無法匹配。

qi::rule<std::string::const_iterator, std::string()> rule1 = qi::repeat(1,2)[qi::digit];
qi::rule<std::string::const_iterator, std::string()> rule2 = qi::digit >> *qi::char_;
std::vector<std::string> attr;
auto it_begin = string2.begin();
auto it_end = string2.end();
if (qi::parse(
    it_begin,
    it_end,
    qi::lit("start:")
         >> -(qi::lit(" ") >> rule1)
         >> qi::lit(" ") >> rule2
         >> qi::eoi,
    attr))
    std::cout<<"match"<<std::endl;
else
    std::cout<<"not match"<<std::endl;

我們當然可以使用先行運算符來檢查rule1背后的內容,但是有沒有更通用的方法來實現正則表達式運算符'? 謝謝!

我不確定期望有什么問題。 這是否則產生歧義規則的唯一方法,因為PEG語法總是貪婪的。

但是,也許您沒有找到最優雅的形式,因為您正在尋找“更好”的東西。 這就是我要做的。

我會使用船長來匹配空格¹:

    if (qi::phrase_parse(it_begin, it_end,
                "start:" >> -rule1 >> rule2 >> qi::eoi,
                qi::space, attr))

規則仍然是詞素的地方(因為聲明時沒有使用船長):

qi::rule<It, std::string()> const 
    rule1 = qi::digit >> qi::digit >> &qi::space,
    rule2 = qi::digit >> *qi::graph;

注意qi::graph不匹配空格,其中*qi::char_只是貪婪地匹配任何東西

生活在Coliru

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

int main() {
    using It = std::string::const_iterator;

    // implicitly lexemes (no skipper in rule declaration)
    qi::rule<It, std::string()> const 
        rule1 = qi::digit >> qi::digit >> &qi::space,
        rule2 = qi::digit >> *qi::graph;

    for (std::string const input : { "start: 01 0ab", "start: 0ab", }) {
        std::vector<std::string> attr;

        auto it_begin = input.begin();
        auto it_end   = input.end();

        if (qi::phrase_parse(it_begin, it_end, "start:" >> -rule1 >> rule2 >> qi::eoi, qi::space, attr))
            std::cout << "match\n";
        else
            std::cout << "not match\n";

        if (it_begin!=it_end)
            std::cout<<"Remaining unparsed input: '" << std::string(it_begin, it_end) << "'\n";
    }
}

打印

match
match

¹這假設多個/不同的空格是可以的。 如果換行符不算作空格,請使用qi::blank而不是qi::space

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM