と言う話です。
話の前提とか理由
大体、
という辺りの問題。
で、もうちょっと詳し書くと、今作っている nytra
という軽量マークアップ言語 (markdown とかはてな記法とかの類い) では PEG.js を使って構文定義をしていて、かつ、インラインの軽量マークアップ言語を定義する際に、
各構文が、自身の構文を除く、他のすべてのインライン構文を子要素として持つ
と言う定義を書かないと上手く動かなそうな感じが有りました。
それで、その辺りを上手く動かすために、上記の構文定義をしたないとなー、という感じだったんですが、 その構文定義を手作業で書こうとすると、どう考えてもミスが出そうだし、 あと同じ様な構文を各構文毎に定義するのが正直つらみしか無さそうだったので、
じゃ、テンプレート処理すれば良いじゃん
ってなって、
とりあえずサクっと何も考えずに使える
ejs
使うかー
という意思決定をして、実際使ってみたら便利だった、というのが今回の話です。
今現在の処理の流れ
実際のパーザのコードを生成する流れとしては、
ejs
を含んだPEG.js
用のコードを書くejs
のテンプレート処理をしてPEG.js
のコードを生成する- 生成した
PEG.js
のコードから実際のパーザのコードを吐かせる
という感じになっています。 そして、下記が実際にパーザを生成する時に使ってるコードです:
"use strict"; const ejs = require("ejs"); const peg = require("pegjs"); const fs = require("fs"); const path = require("path"); "inline.pegjs.ejs block.pegjs.ejs".split(" ").forEach((fn) => { fs.readFile(path.join(__dirname, fn), (err, template) => { if (err !== null) { throw err; } var source = ejs.render(template.toString(), {}, {}); var output = peg.generate(source, { output: "source", format: "commonjs" }); fs.writeFile( path.join(__dirname, "..", "dist", fn.replace(".pegjs.ejs", ".js")), output, (err) => { if (err !== null) { throw err; } } ); }); });
なんか割とザツいですね。
ejs + PEG.js + HAST を組み合わせると、軽量マークアップ言語を作るの凄く楽
今現在、 nytra
のコードは、
の三つを組み合わせつつ書いているのですが、HAST
とその周辺ツールのおかげで、
Abstract Syntax Tree を自前で用意しなくて済んでいるし、あと、
HAST
から HTML に変換するのも HAST
の周辺ツールを使うだけで生成できちゃってるので、
そう言った意味合いでは、
ejs
+PEG.js
+HAST
という組み合わせを見付けられた、というのは、今回凄く良かったかなーとか思っています。はい。
以上
なんか今日は割とザツに記事書いてますが、大体そんな感じでした。はい。