1

以下の文字列を解析する文法とレクサーを作成したいと思います。

100 reason phrase

正規表現は次のようになります: "\d{3} [^\r\n]*"

トークン定義:

template <typename Lexer>
struct custom_tokens : lex::lexer<Lexer>
{
    custom_tokens()
    {
        this->self.add_pattern
            ("STATUSCODE", "\\d{3}")                
            ("SP", " ")
            ("REASONPHRASE", "[^\r\n]*")
            ;                

        this->self.add                          
            ("{STATUSCODE}", T_STATUSCODE)
            ("{SP}", T_SP)
            ("{REASONPHRASE}", T_REASONPHRASE)
            ;
    }   
};

文法:

template <typename Iterator>
struct custom_grammar : qi::grammar<Iterator >
{
    template <typename TokenDef>
    custom_grammar(TokenDef const& tok)
        : custom_grammar::base_type(start)            
    {            
        start = (qi::token(T_STATUSCODE) >> qi::token(T_SP) >> qi::token(T_REASONPHRASE));
    }

    qi::rule<Iterator> start;
};

しかし、トークン「T_REASONPHRASE」は、「T_STATUSCODE」を含むすべてに一致するため、定義できないことに気付きました。私にできることは

  1. T_REASONPHRASE の定義を解除し、qi::lexeme を使用して custom_grammar 内にルールを記述しますか?

  2. lex state を使用してそれを行うことはできますか? たとえば、2 番目の状態で "T_REASONPHRASE" を定義し、最初の状態で T_STATUSCODE を確認した場合、残りを 2 番目の状態に解析しますか? 例を教えてください。

4

1 に答える 1

2

トークンは、(特定のレクサー状態の)トークン定義に追加された順序で「貪欲に」照合されるため、実際に問題があるとは思いません。

だから、与えられた

    this->self.add                          
        ("{STATUSCODE}", T_STATUSCODE)
        ("{SP}", T_SP)
        ("{REASONPHRASE}", T_REASONPHRASE)
        ;

T_STATUSCODE は常にT_REASONPHRASEの前に一致します (あいまいさがある場合)。


個別のレクサー状態の使用について、これは私がかつておもちゃのプロジェクトで使用したトークナイザーの抜粋です。

this->self = fileheader     [ lex::_state = "GT" ];

this->self("GT") =
    gametype_label |
    gametype_63000 | gametype_63001 | gametype_63002 |
    gametype_63003 | gametype_63004 | gametype_63005 |
    gametype_63006 |
    gametype_eol            [ lex::_state = "ML" ];

this->self("ML") = mvnumber [ lex::_state = "MV" ];

this->self("MV") = piece | field | op | check | CASTLEK | CASTLEQ 
         | promotion
         | Checkmate | Stalemate | EnPassant
         | eol              [ lex::_state = "ML" ]
         | space            [ lex::_pass = lex::pass_flags::pass_ignore ];

( gametype , : move lineおよび: moveGTとして読むと、目的は比較的明確になります。ここにandが存在することに注意してください: Lex は、同じトークンを異なる状態に追加することを許可していません)MLMVeolgametype_eol

于 2013-10-28T10:30:31.233 に答える