2

ポール・マクガイアがこれを見つけて私を救ってくれることを願っています...

「regex インバーター」のサンプル スクリプトを取得しましたhttp://pyparsing.wikispaces.com/file/view/invRegex.py

Python の名前付きグループをサポートするためにハッキングしようとしています。(?P<blob_key>[a-zA-Z0-9-_=]+)

私は pyparsing が初めてで、正規表現パーサーはおそらく学習するための最良の方法ではないことに気付きました (結果を使って何か実用的なことをしようとしているだけです)。

以下のようにパーサー関数を編集しました。

def parser():
    global _parser
    if _parser is None:
        lbrack = Literal("[")
        rbrack = Literal("]")
        lbrace = Literal("{")
        rbrace = Literal("}")
        lparen = Literal("(")
        rparen = Literal(")")
        pyspec = Literal("?P")
        langle = Literal("<")
        rangle = Literal(">")

        reMacro = Combine("\\" + oneOf(list("dws")))
        escapedChar = ~reMacro + Combine("\\" + oneOf(list(printables)))
        reLiteralChar = "".join(c for c in printables if c not in r"\[]{}().*?+|")

        reRange = Combine(lbrack + SkipTo(rbrack,ignore=escapedChar) + rbrack)
        reLiteral = ( escapedChar | oneOf(list(reLiteralChar)) )
        reDot = Literal(".")
        repetition = (
            ( lbrace + Word(nums).setResultsName("count") + rbrace ) |
            ( lbrace + Word(nums).setResultsName("minCount")+","+ Word(nums).setResultsName("maxCount") + rbrace ) |
            oneOf(list("*+?")) 
            )

        reNamedGroup = Combine(lparen + pyspec + langle + SkipTo(rangle) + rangle
                               + SkipTo(rparen, include=True) + rparen)

        reNamedGroup.setParseAction(handleNamedGroup)
        reRange.setParseAction(handleRange)
        reLiteral.setParseAction(handleLiteral)
        reMacro.setParseAction(handleMacro)
        reDot.setParseAction(handleDot)

        reTerm = ( reLiteral | reNamedGroup | reRange | reMacro | reDot )
        reExpr = operatorPrecedence( reTerm,
            [
            (repetition, 1, opAssoc.LEFT, handleRepetition),
            (None, 2, opAssoc.LEFT, handleSequence),
            (Suppress('|'), 2, opAssoc.LEFT, handleAlternative),
            ]
        )
        _parser = reExpr

    return _parser

これをテスト正規表現に対して実行するreNamedGroupと、名前付きグループを正しく見つけて処理しているように見えます(ログインSkipToや他の方法をいくつかスタックしました...)が、同時に出力にまったく参加していないようで、私のhandleNamedGroup関数が呼び出されることはありません。

ログ出力は次のようになります。

invert(r'serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/')
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 12
DEBUG:root: *** 15, A-Z
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 12
DEBUG:root: *** 15, A-Z
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 24
DEBUG:root: *** 32, blob_key
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 33
DEBUG:root: * 49, [')'], [a-zA-Z0-9-_=]+
DEBUG:root: ** ['[a-zA-Z0-9-_=]+', ')']
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 24
DEBUG:root: *** 32, blob_key
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 33
DEBUG:root: * 49, [')'], [a-zA-Z0-9-_=]+
DEBUG:root: ** ['[a-zA-Z0-9-_=]+', ')']
DEBUG:root: handleLiteral: ['s']
DEBUG:root: handleLiteral: ['e']
DEBUG:root: handleLiteral: ['r']
DEBUG:root: handleLiteral: ['v']
DEBUG:root: handleLiteral: ['e']
DEBUG:root: handleLiteral: ['_']
DEBUG:root: handleLiteral: ['b']
DEBUG:root: handleLiteral: ['l']
DEBUG:root: handleLiteral: ['o']
DEBUG:root: handleLiteral: ['b']
DEBUG:root: handleLiteral: ['/']
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 12
DEBUG:root: *** 15, A-Z
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 12
DEBUG:root: *** 15, A-Z
DEBUG:root: handleRange: ['[A-Z]']
DEBUG:root: handleRepetition: [[[ABCDEFGHIJKLMNOPQRSTUVWXYZ], '{', '2', '}']]
DEBUG:root: handleLiteral: ['/']
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 24
DEBUG:root: *** 32, blob_key
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 33
DEBUG:root: * 49, [')'], [a-zA-Z0-9-_=]+
DEBUG:root: ** ['[a-zA-Z0-9-_=]+', ')']
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 24
DEBUG:root: *** 32, blob_key
DEBUG:root: serve_blob/[A-Z]{2}/(?P<blob_key>[a-zA-Z0-9-_=]+)/, 33
DEBUG:root: * 49, [')'], [a-zA-Z0-9-_=]+
DEBUG:root: ** ['[a-zA-Z0-9-_=]+', ')']
DEBUG:root: handleSequence: [[Lit:s, Lit:e, Lit:r, Lit:v, Lit:e, Lit:_, Lit:b, Lit:l, Lit:o, Lit:b, Lit:/, <libs.exreg.exreg.GroupEmitter object at 0x34cfa30>, Lit:/]]

** で始まる行は、skipResから返された値SkipToです ... 私には正しいように見えます。私が困惑している部分は、なぜ彼らが無視されているのかということです。

私はやみくもにコピーアンドペーストしているだけであることを痛感しています...うまくいくものを綿密にコピーしようとしましたreRange...しかし、範囲は機能しますが、私の同様のビットは機能しません。

おそらく、周囲の括弧は、解析の後の段階で出力から解析された名前付きグループを「隠している」と推測していますが、その方法についてはわかりません。

4

1 に答える 1

1

reNamedGroup式のparensでは何もしたくありません。括弧で囲まれたreグループには他に定義された文法はありませんが、それらは最も確実に機能することに注意してください。このパーサーでは、パーレンはoperatorPrecedence式の一部として処理されます。reNamedGroupの定義を次のように変更しました。

reNamedGroup = pyspec + langle + SkipTo(rangle) + rangle

そして、operatorPrecedenceにすべての親のグループ化を任せます。

[OP編集]上記の変更だけでも一種の作業ですが、指定されたグループからのすべての出力はいずれか
で始まるため、パーツが何らかの形で出力にリークしています。結局、スタック形式で書き直す必要はありませんでした(コメントを参照)。次の追加の変更により、正しく機能するようになりました。P?pyspec

reTerm = ( reLiteral | reRange | reMacro | reDot )
reExpr = operatorPrecedence( reTerm,
    [
    (reNamedGroup.suppress(), 1, opAssoc.RIGHT, handleNamedGroup),
    (repetition, 1, opAssoc.LEFT, handleRepetition),
    (None, 2, opAssoc.LEFT, handleSequence),
    (Suppress('|'), 2, opAssoc.LEFT, handleAlternative),
    ]
) 
于 2012-06-21T21:20:20.010 に答える