2017-11-08 3 views
1

ポストスキップを行うための最も慣用的な方法は何ですか?より具体的には、トップルールにマッチした後、入力に「スキップ不可能な」(ガベージ)文字がないことを確認します。ポストスキップによる慣用的な完全一致

auto const blankOrComment 
    = ascii::space 
    | x3::lexeme ['#' >> *(x3::char_ - x3::eol) >> -x3::eol ] 
    ; 

auto const program = rule<AstProgram>("program") 
    = *(as<AstDefinition> (definition > ";")) 
    ; 

auto const programEntry = x3::skip(blankOrComment) [program]; 

ひとつのアイデア、私は非常に醜い考慮すると、メインのイテレータの位置がエンドイテレータでない場合は、その後blankOrCommentのための独立した解析コールを行うことでした。私が持っている現在の良いアイデアは、ルートルールを変更することです:

auto const programEntry = x3::skip(blankOrComment) [program >> x3::omit[*blankOrComment]]; 

もっと慣用的な方法がありますか?

答えて

1

最も簡単なハックが>> epsにタックすることである。同様に、あなたはそのpostskipハックを行うことができます

auto const skipper 
    = space 
    | '#' >> *(char_ - eol) >> (eol|eoi) 
    ; 

:私は船長より自己記述を作るために努力したいLive On Coliru

注意より自己記述的:

auto const post_skip = eps; 
    auto const program = "program" >> post_skip; 

Live On Coliru

#include <iostream> 
#define BOOST_SPIRIT_X3_DEBUG 
#include <boost/spirit/home/x3.hpp> 

namespace Parser { 
    namespace x3 = boost::spirit::x3; 

    namespace rules { 
     using namespace x3; 

     auto const skipper 
      = space 
      | '#' >> *(char_ - eol) >> (eol|eoi) 
      ; 

     auto const post_skip = eps; 
     auto const program = "program" >> post_skip; 

    } 

    auto const programEntry = x3::skip(rules::skipper) [rules::program]; 
} 

int main() { 
    using It = std::string::const_iterator; 
    for (std::string const input : { 
      "", 
      " program ", 
      "#hello\n program # comment\n", 
    }) { 
     It f = input.begin(), l = input.end(); 

     if(parse(f, l, Parser::programEntry)) { 
      std::cout << "Parse success\n"; 
     } else { 
      std::cout << "Parse failed\n"; 
     } 

     std::cout << "Remaining: '" << std::string(f,l) << "'\n"; 
    } 
} 

プリント

Parse failed 
Remaining: '' 
Parse success 
Remaining: '' 
Parse success 
Remaining: ''