2016-10-14 13 views
2

正規表現 "start :(?0-9] {1,2})?([0-9]。*)"があるとします。ブースト::スピリット::気パーサーを書く方法正規表現では?

それは我々はまた、それぞれ2マッチした文字列を取得することができます

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

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

と一致します。

私は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; 

私たちは、もちろんルール1の背後に何があるかチェックするために先読み演算子を使用できますが、正規表現演算子を実装するためのより一般的なアプローチがあります「?」 ?ありがとう!

答えて

3

私は何が間違っているのか分かりません。それは、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 doesnの」

私はspaces¹に一致するようにスキッパーを使用したいですtは空白に一致し、*qi::char_は単にと一致します。は貪欲です。

Live On 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::space

の代わりに qi::blankを使用してください。
関連する問題