2

序文

レクサー/パーサーのルールに関連付けるために、独自の文脈自由文法仕様を作成しようとしています。これは、大文字の識別子がレクサー規則として分類され、小文字の識別子がパーサー規則として分類されるANTLRのものと同様であることを意図しています。文字列リテラルおよび/またはレクサー規則の正規表現の任意の組み合わせ、およびパーサー規則のレクサー/正規表現規則および/または他のパーサー識別子の任意の組み合わせを受け入れることを意図しています。の各ルールは、<識別子>:<式> の形式です。

文法の例を次に示します。

integer      : DIGIT+;        //parser rule containing at least one lexer rule
twodigits    : DIGIT DIGIT;   //parser rule containing two consecutive lexer rules
DIGIT        : [0-9];         //lexer rule containing regex
string       : '"' CHAR* '"'; //parser rule containing zero or more 
                              //  lexer rules, wrapped in two string literals
CHAR         : (LCHAR|UCHAR); //lexer rule containing two lexer rules which
                              //  will later evaluate to one of two tokens
LCHAR        : [a-z];         //lexer rule containing regex
UCHAR        : [A-Z];         //lexer rule containing regex
SPACE        : ' ';           //lexer rule containing string literal


問題

私が抱えている問題は、式の文字列の内容が変化する傾向があるため、式の文字列を一致させる機能です。
私はもともと次のように書いていました:
([a-zA-Z0-9_]*)(?:\s*)(?:\:)(?:\s*)((?:\'?).*(?:\'?)(?:\;))
一重引用符で囲まれた単一の文字列リテラル式には問題ありませんが、これを拡張して、複数の非貪欲な文字列リテラルと、任意の数の空白で区切られた結合ステートメントを許可する必要があります。これは後で別の正規表現操作によって処理されるため、一致した式内で潜在的な正規表現を一致させたり、式の分離された部分をキャプチャしたりすることには関心がありません。したがって、実際には識別子と式を検証するだけで済みます...

全体として、次の一致構文を使用して、文法の内容を調べるには regex_search 操作が必要です。

  • 1 つ以上の小文字または大文字で始まり、オプションで任意の数の英数字が続く有効な識別子(識別子が 1 で開始または終了しない限り、任意の数のアンダースコア文字を間に含めることができます)。
  • 任意の数の空白文字、タブ、改行などをキャプチャせずに。
  • それをキャプチャせずにコロン。
  • 任意の数の空白文字、タブ、改行などをキャプチャせずに。
  • 少なくとも 1 つ: (任意の順序で) 任意の数の文字列リテラル (引用符をキャプチャせずに単一引用符で囲む)、任意の数のレクサー/パーサー識別子、任意の数の正規表現 (角括弧で囲む)。この一致ルールの結果は、式全体を単一の文字列としてキャプチャする必要があり、後で後処理段階を通過します。
  • 任意の数の空白文字、タブ、改行などをキャプチャせずに。
  • オプションで、キャプチャされていない空白が続くセミコロン。
  • オプションで、任意の数のキャプチャされていないスペースと、それに続く単一のキャプチャされた行コメント
  • 任意の数の空白文字、タブ、改行などをキャプチャせずに。

質問

これを単一の regex_search 操作に入れることは可能ですか?
私はExpressoをいじりましたが、うまくいかないようです...


アップデート

これまでのところ、次のことを思い付くことができました。

#/////////////////////
# Identifier
#/////////////////////
(
    (?:[a-zA-Z]+)           # At least one lower/uppercase letter
    (?:
        (?:[a-zA-Z0-9_]*)   # Zero or more alphanumeric/underscore characters,
        (?:\w+)             # explicitly followed by one or more alphanumeric
    )?                      #   characters
)

#/////////////////////
# Separator
#/////////////////////
(?:\s*)                     # Any amount of uncaptured whitespace
(?:\:)                      # An uncaptured colon
(?:\s*)                     # Any amount of uncaptured whitespace

#///////////////////////
# Expression
#///////////////////////
(
    # String Literals:
    (?:\'?)                 # An optional single quote,
    (?:                     #   which is meant to start and end a string
        (?:[^'\\] | \\.)*   #   literal, but issues several problems for
    )                       #   me (see comments below, after this code block)
    (?:\'?)
    # Other expressions
    # ????????????
)

#/////////////////////
# Line End
#/////////////////////
(?:\s*)                     # Any amount of uncaptured whitespace
(?:\;)                      # An uncaptured colon
(?:\s*)                     # Any amount of uncaptured whitespace

ご覧のとおり、識別子セパレーター、および行末が完全に機能しています。しかし、表現は私が完全に立ち往生しているところです! 貪欲でない文字列リテラル、または行末の前の任意の文字セット、およびそれらの任意の数のいずれかが必要で

あることを正規表現ライブラリに伝えるにはどうすればよいですか? 単一の文字列リテラルのみを許可したとしても、 「最初の単一引用符が存在する場合、最後の単一引用符はオプションではありません」

とどのように言えますか?

4

1 に答える 1

0

完全ではない可能性があり、一致結果の処理方法に追加のコーディングが必要になる場合がありますが、これは機能するようです:

#/////////////////////
# Identifier
#/////////////////////
(
    (?:[a-zA-Z]+)
    (?:
        (?:[a-zA-Z0-9_]*)
        (?:\w+)
    )?
)

#/////////////////////
# Separator
#/////////////////////
(?:\s*\:\s*)

#///////////////////////
# Expression
#///////////////////////
(
    '(?:\\\\.|[^'])*'|[^']+     # Might need to be processed separately
)

#/////////////////////
# Line End
#/////////////////////
(?:\s*\;\s*)
于 2013-03-12T21:30:29.380 に答える