本日、『オッ!? どうすれば良いんだコレ!?』と、一瞬詰った進捗です。
何がどうなったのか
最初から結論を書くと、 nytra
と言う、オレオレ軽量マークアップ言語 (Markdown とかはてな記法とかそういう類い) の開発を今日していて、
- インライン記法の入れ子が出来ない!!1 (割と致命的)
- インライン記法がバグってる影響で空行を正しく処理出来ない
- そして、それに引き摺られてブロック記法が定義できない
と言う感じになったため、一から PEG.js の定義やらコードの書き方やらを見直す事となりました。
※ ただし、テストは一応は残った
もうちょっと詳しく
一応、僕の考えている構文では、
*これは太字* ## => <strong>これは太字</strong> /これは斜体/ ## => <em>これは斜体</em> */これは太字かつ斜体/* ## => <strong><em>これは太字かつ斜体</em></strong>
みたいなコトが出来る様にしたかったのですが、実際には、上記例の三番目が、
*/これは太字かつ斜体/* # => <strong>/これは太字かつ斜体/</strong>
みたいな出力結果になっていました。つまり 構文の入れ子が出来てない っていう。 そして、 PEG.js (と言うか PEG そのもの?) の場合、僕の理解が合っていれば 、
ある構文 A を含む別の構文 B は、ある構文 A に無限に出現する事は出来ない
という制約があり、これはまあ単純に言うと、
無限再帰な構文定義は出来ない
と言う感じになります。つまり、無限ループになる構文は定義出来なくてエラーになります。
では、この問題はどうすれば良いのか
先に結論から書くと、最初の例示した太字とか斜体の構文の話では、
太字構文 (A) と入れ子に出来る構文 (B) を、キッチリと定義する
と言う手法を取れば良いんじゃね、という結論になりました。
つまる所、入れ子可能な構文 (B) に入れ子元の構文 (A) が含まれる事が原因で無限再帰を起こすので、 その入れ子元の構文 (A) を除外した 入れ子可能な構文 (B') を作れば良いよねって話です。
ただし、実際にはこれ、インラインの ○○ 構文を作る毎に、その ○○ 構文を含まない構文 ×× を定義する破目になるので、
うお〜、なんかこれ 手書き だと テストやら構文定義でもの凄く組合せ爆発しそうだぞ〜
と言う感じな予感がしたため、とりあえず、下記の、
- PEG.js の構文定義を自動定義する生成器を作る
- その生成器を使って PEG.js がパーズ出来る形の定義ファイルを作る
- 自動生成した PEG.js の定義ファイルから、実際のバーザを吐く
という手法を取るか……という所で今日の作業は終えました。はい。
以上
まぁ、とりあえず今日の作業はそんな感じでした。はい。