パーサーがマークダウンのようにトークンパターンを検索する方法を説明できますか?
ネストされたパターンが含まれるとすぐに、中括弧パターン[]()
のみに一致するものを思いつくかもしれません。
例えばこのようなもので
foo [**baz**](baz) qux
トークナイザーはおそらくexplodesこれらのトークンへの文字列
"foo ", "[", "**", "baz", "**", "]", "(", "baz", ")", " qux"
そしてそれをパーサーに渡してパターンを認識し、それがリンクであり、中括弧が一致し、さらにラベル内の太字スタイルを理解します。
それはある種の状態マシンだと思いますが、実際にはそうしますthink[
が発生するとすぐに何かが意味される可能性があるため、トークンを格納し、後続のトークンが一致しない場合この状態を破棄し、区切りトークンを通常のリテラルに変えます。つまり、(
の終了後に]
がなかった場合は、前に戻って他のすべての意味を変更する必要がありました。複雑すぎると思いますか?
私がそれを見ると、実装するのは簡単だったように見えますが、もしinventのアルゴリズムが必要な場合、それはできませんでした。
見たところ簡単に実装できたようですが、アルゴリズムを考案しようとしてもできませんでした。
ありがたいことにいくつかの人々はすでに持っています:)
それは複雑なトピックであり、そこにはたくさんありますが、簡単に要約すると:
トークナイザーが文字列をトークンに分解するのは正しいことです。次に、パーサーは文法を内部に定義し、通常はBNFのようなものを使用して、断片を合わせます。
"foo ", "[", "**", "baz", "**", "]", "(", "baz", ")", " qux"
次のような文法で解析できます:
line = <rounds> | <squares> | <markdown_stuff> | <line>
rounds = '(' <line> ')'
squares = '[' <line> ']'
markdown_stuff = <italics> | <bold> | <Word_text>
italics = '*' <Word_text> '*'
bold = '**' <Word_text> '**'
Word_text = <Word_char> | <Word_char> <Word_text>
Word_char= 'a', 'b', 'c', 'd'... etc 'A', 'B', 'C', etc '0', '1', '2', '3', etc '_'
再帰的であることに注意してください。 Word_text
のようないくつかのルールは直接自分自身を参照し、<line>
のような他のルールは<line>
を参照するものを参照します。 (python language doc はそのような例でいっぱいです)
あなたの言語のための文法を作った後、あなたは例えば書くでしょう。それを「読み取る」ための再帰的降下パーサー。または、より一般的には、YACCやANTLRなどのツールを使用して、文法に基づいてパーサーを直接作成します。
ステートマシンについて:YACCは、パーサーを巨大なステートテーブルの観点から実装していると思います。使って久しぶりです。