私は、実際の文法を使用して wiki パーサーを作成しようとしている、まだ初期段階のプロジェクトを持っています。適度に完成していると思われるクレオール語の文法を見つけ、第三者によって (ANTLR を使用して) 動作することが確認されました。
私は物事を前進させ始めましたが、いくつかのハードルにぶつかりました。これは、pyparsing で一般的なつまずきのブロックであると想定しています。
escaped
: ESCAPE STAR STAR
| ESCAPE .
// '.' in a parser rule means arbitrary token, not character
;
これについて私が思いついたのは次のとおりです。
ESCAPE = Literal('~')
STAR = Literal('*')
escaped = ESCAPE + STAR + STAR | ESCAPE + Word(printables, max=1)
単一の文字に一致する pyparsing で他に何も見つかりませんでしたが、これはうまくいくようです。ただし、ヘッダーの内容を見ると、次の部分式があります。
heading_content
: heading_markup heading_content ( heading_markup )?
| ( ~( EQUAL | ESCAPE | NEWLINE | EOF ) | escaped )+
;
私はフォワードを使用していますが、2番目の部分では、次のようになりました。
OneOrMore(CharsNotIn("=~\r\n") | escaped)('heading_content')
これは "test" と "test~=" に一致しますが、"test" の部分のみに一致する "test~=foo" には一致しません。何故ですか?
第二に、CharsNotIn 以外のコンテンツ部分を指定する別の方法があるかどうか疑問に思っていましたか?
今、私が本当に困惑しているのは、フォーマットされていないテキスト部分を一致させようとすることです。これは、あらゆる種類のプレーン テキストを照合するためのコアです。これで、文法は次のように指定されます。
text_unformatted
: ( ~( ITAL
| STAR
| LINK_OPEN
| IMAGE_OPEN
| NOWIKI_OPEN
| EXTENSION
| FORCED_LINEBREAK
| ESCAPE
| NEWLINE
| EOF )
| forced_linebreak
| escaped )+
ここで壁にぶち当たりました。上記の単純なビットは次のように定義されます。
# STAR, ESCAPE and escaped defined above
ITAL = Literal('//')
LINK_OPEN = Literal('[[')
IMAGE_OPEN = Literal('{{')
NOWIKI_OPEN = Literal('{{{')
EXTENSION = Literal('@@')
FORCED_LINEBREAK = Literal(r'\\')
CR = Literal('\r')
LF = Literal('\n')
NEWLINE = Optional(CR) + LF | CR
ただし、 OneOrMore(NotAny(...) | FORCED_LINEBREAK | escaped) の素朴なアプローチは機能せず、無限にループしてしまいました。ドキュメントをもう少し読むと、NotAny が実際には一致を返さないことがわかりました。では、これをどのように一致させるのでしょうか。単一の「{」が完全に有効であるため、CharNotIn(...) は使用できません。
ポインターを高く評価しました。