Skip to content

コード中の位置を取得してエラー報告できるDSLのパッケージを試しに創ってみた

Takashi Suwa edited this page Dec 20, 2020 · 2 revisions

コード位置を取得できる文字列リテラルを利用し,ステージ0の前処理で構文エラーが見つかったときにそのエラー位置を報告してくれるようなDSLの例を創りました.汎用性皆無ですが,いわゆるあみだくじを描画するDSLです(commit hashは d76e545):

※ただし,これを作成している最中に足りなかった機能の追加と不具合の修正を行なって satysfi-base にpull requestを出しており,この amidakuji パッケージの実装はその修正に依存しているため,これを執筆している時点ではそのままでは使用できません.

リポジトリの doc/ にも置いていますが,以下のように記述すると,

@require: stdjareport
@require: amidakuji/amidakuji

document (|
  title  = {`amidakuji` パッケージ};
  author = {Takashi Suwa};
|) '<
  +p{
    \amidakuji@~(@```
      | | | | | |
      |X|-|=|/| |
      | |-|\|-|X|
      |=|X|-|\|=|
      |-|\|-|=|-|
      |X|=|-|\| |
      | | | | | |
    ```);
  }
>

以下のように出力できます:

スクリーンショット 2020-12-20 23 20 01

で,重要なのは異常系です.上記のように出力すること自体はマクロではなく通常のコマンドで実現しても構わないのですが,通常のコマンドで実現すると,DSLの構文解析が組版処理と同じ段階で行なわれるため,例えば500ページある文書の490ページ目にあみだくじを入れたい場合,そこにあみだくじ用DSLコードとして構文エラーのある入力を与えてしまったら,手前の490ページ分の内容が組み上げられるのを待った後にしか構文エラーが報告されないという不都合があります(典型的には490ページ組むには1分程度はかかるはずです).これを解決するためにマクロとして定義しているのです.こうした問題意識と多段階計算ベースのマクロという解決法についての詳細は以下をご覧ください:

さて,上記の例でも試しに入力を少し間違えた場合を与えてみます:

@require: stdjareport
@require: amidakuji/amidakuji

document (|
  title  = {`amidakuji` パッケージ};
  author = {Takashi Suwa};
|) '<
  +p{
    \amidakuji@~(@```
      | | | | | |
      |X|-|=|/|^|
      | |-|\|-|X|
      |=|X|-|\|=|
      |-|\|-|=|-|
      |X|=|-|\| |
      | | | | | |
    ```);
  }
>

対応していない ^ という入力を与えてみました.処理すると以下のように出ます:

$ satysfi foo.saty
(中略)
  evaluating 'stream.satyg' ...
  evaluating 'parser.satyg' ...
  evaluating 'amidakuji0.satyh' ...
  preprocessing 'amidakuji.satyh' ...
  preprocessing 'foo.saty' ...
! [Error during Evaluation] syntax error of 'amidakuji' at line 11, column 15 in 'foo.saty': expected an element (-|, ␣|, X|, /|, \|, or =|)

たしかに11行目の15文字目に ^ を書いていたためにエラーになったという旨がパッケージによって報告されています.また,これは小さい文書ですが,実際に500ページくらいの大きな文書の中の末尾で使っても0.1秒オーダー程度の早さで報告されるはずです.

Clone this wiki locally