青空文庫記法を解析する Rust パーサ aozora

Share

aozora は青空文庫記法のパーサ。CommonMark や Markdown は扱わず、青空文庫が配布している .txt ファイルに現れる注釈記法だけを対象にする。実装は Rust で、CLI バイナリ・Rust ライブラリ・WASM・C ABI・Python バインディングの 5 種類で配布する。

use aozora::Document;

let source = "|青梅《おうめ》".to_owned();
let doc = Document::new(source);
let tree = doc.parse();

let html: String = tree.to_html();
let canonical: String = tree.serialize();
let diagnostics = tree.diagnostics();

assert_eq!(canonical, "|青梅《おうめ》");

青空文庫記法とは何か

青空文庫 はパブリックドメインの日本文学を電子化して公開しているボランティアの電子図書館で、1997 年から続いている。各作品は Shift_JIS でエンコードされた .txt ファイルに、本文と独自の注釈記法が混在した形で配布される。

注釈記法には次のような種類がある。

  • ルビ: |青梅《おうめ》 で「青梅」に「おうめ」と振り仮名を付ける
  • 傍点: [#「ここに傍点」に傍点] で強調用の点を打つ
  • 縦中横: [#「23」は縦中横] で縦書き中の数字を横向きに組む
  • 外字: ※[#「魚+師」、第3水準1-94-37] で JIS X 0213 や Unicode 不在字を参照
  • 訓点・返り点: 漢文の読み下し用記号
  • 字下げコンテナ: [#ここから2字下げ]… [#ここで字下げ終わり] の範囲指定
  • 改ページ・改段: 章区切りを示す

aozora はこれらを全て認識し、構造化された AST と診断情報に変換する。

インストールと使い方

ビルド済みの CLI バイナリは GitHub Releases に Linux x86_64 / macOS arm64 / Windows x86_64 の 3 種類が aozora-vX.Y.Z-<target>.{tar.gz,zip} 形式で置いてある (SHA256SUMS 同梱)。

ソースから入れるなら cargo install:

cargo install --git <https://github.com/P4suta/aozora> --locked aozora-cli

CLI のサブコマンドはこの 4 つを覚えればだいたい用が足りる。

aozora check FILE.txt           # 字句解析と診断
aozora fmt --check FILE.txt     # parse → serialize の往復チェック
aozora render FILE.txt          # HTML を標準出力へ
aozora check -E sjis FILE.txt   # 青空文庫が配布する Shift_JIS をそのまま読む

すべて - (またはパス省略) で標準入力から読める。

Rust ライブラリとしての使い方は冒頭のコード例の通り。Documentbumpalo アリーナを所有し、tree がそこから borrow するライフタイム設計になっている。WASM / C ABI / Python から呼ぶ場合は handbook の Bindings 章にそれぞれの最小例がある。

実装の独自な部分

設計判断として目立つのは 3 点。詳細は handbook の Architecture 章にそれぞれ独立した節がある。

Markdown を扱わない。青空文庫記法は CommonMark とも GFM とも違う独自の文法体系で、aozora は青空文庫記法だけに責務を絞っている。Markdown と組み合わせて使いたい場合は別プロジェクトの afm を使う (afm は aozora を内部に取り込んだ Markdown 方言)。

SIMD マルチパターンスキャナ。青空文庫の本文は UTF-8 で 1 文字 3 バイトが大半を占め、トリガーバイト (|《》※[] および全角空白) の出現密度は 1KB あたり 1 個程度しかない。この希薄な探索を回すために Intel Hyperscan 由来の Teddy アルゴリズムを採用している。AVX2 環境のコーパス計測で 12 GB/s。AVX2 が無い環境では Hoehrmann 系 DFA に runtime dispatch でフォールバックする (3.5 GB/s)。wasm32 ターゲットは memchr 多重スキャンで 1.2 GB/s。

借用アリーナ AST。1 ドキュメントは数万ノードに展開されるため、Box<Node> を素直に並べると malloc がボトルネックになる。aozora は bumpalo 単一アリーナに全ノードを置き、ドキュメント drop 時に 1 回の Bump::reset で全解放する。青空文庫全作品を回すコーパスベンチで Box<Node> 版比 6.4 倍速、ピーク RSS は 30% 減を測っている。

さらに知りたい場合

  • handbook: https://p4suta.github.io/aozora/ — 記法の網羅リファレンス、内部設計 (借用アリーナ、SIMD スキャナ、外字解決)、性能チューニング (PGO、samply、コーパススイープ) まで一通り入っている
  • API リファレンス: https://p4suta.github.io/aozora/api/aozora/ — rustdoc を自動デプロイ
  • 関連プロジェクト
    • P4suta/afm — CommonMark + GFM + 青空文庫記法を統合した Markdown 方言
    • P4suta/aozora-tools — フォーマッタ、LSP サーバ、tree-sitter 文法、VS Code 拡張

crates.io への公開は v1.0 API 確定後の予定。それまでは tagged commit に依存する形で利用する。

Read more

青空文庫のParser

青空文庫のParser

青空文庫のParserを作ってます。 GitHub - P4suta/aozora: Pure-functional Rust parser for 青空文庫記法 (Aozora Bunko notation): ルビ, 傍点, 縦中横, 外字, 返り点, indent containers, page breaks.Pure-functional Rust parser for 青空文庫記法 (Aozora Bunko notation): ルビ, 傍点, 縦中横, 外字, 返り点, indent containers, page breaks. - P4suta/aozoraGitHubP4suta Rustで作ってますが、配布物はcargoのほかにnpm/pypiでも入手できます Documentation * Playground — try it in

By Sakashita Yasunobu

イケイケなWinスクショアプリを作りました

パソコンのスクショってなんというか、地味というか、撮ってそのままだと何とものっぺりしていますよね。 特にWindowsだとMacっぽい丸っこい感じとかもなく、無骨だなあと。 ということで、それっぽくおしゃれな背景や角丸を付けておしゃれに撮影をしてくれるスクショアプリを作りました。 GitHubで公開しています。 GitHub - P4suta/Snaply: Snaply — a modern, clean-architecture Windows screenshot tool (WinUI 3 / .NET 10)Snaply — a modern, clean-architecture Windows screenshot tool (WinUI 3 / .NET 10) - P4suta/SnaplyGitHubP4suta ウィンドウ・領域選択・スクリーンのキャプチャができます。 タッチスクリーンなどにも対応しているはずです。 撮影をすると、クリップボードにコピーされ、フォルダーへの保存もされます。

By Sakashita Yasunobu
Find My Files

Find My Files

Windowsにおける爆速ファイル検索アプリの定番といえば、Everythingです。 voidtoolswebhost2 その高速さの理由は、NTFSの仕組みをうまく活用していることにあります。Windowsで一般的に使われているNTFSには、ファイル情報を管理するマスターファイルテーブル(MFT)と、ファイルシステムの変更履歴を記録するUSN Journalがあります。Everythingはこれらを利用することで、初回に高速にファイル一覧を構築し、その後はUSN Journalを監視してリアルタイムにインデックスを更新しています。そのため、数百万ファイル規模の環境でも非常に高速な検索を実現しています。 もちろん、単純にファイル名やパスを保持するだけでは、大量のメモリを消費してしまいます。また、数百万件ものファイルから一瞬で目的のものを見つけるためには、メモリ効率の高いデータ構造や高速な検索アルゴリズムなど、さまざまな工夫が必要になります。 このように、Everythingは見た目こそシンプルですが、中身はかなり高度なことをやっているソフトウェアです。 なお、Everyth

By Sakashita Yasunobu