parser-development について
Biome のコントリビューター向けパーサー開発スキルです。文法、エラー回復、字句解析、テストの手順とレビュー項目をまとめています。
主な機能
- 01パーサーの手順とレビュー項目
- 02文法と構文生成のガイド
- 03存在判定とエラー回復の規約
- 04レキサーとトークンソースの実践
- 05フィクスチャとスナップショットのテスト
活用シーン
- 01言語の解析ルールの追加や変更
- 02文法と生成済み構文アーティファクトの更新
- 03後続の有効な入力を保つ解析回復の修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ biomejs/ biome --skill parser-developmentインストール後、Claude Code で/parser-developmentを入力して読み込まれたか確認します。
詳細
パーサー開発
正準的なパーサーガイドとして crates/biome_parser/CONTRIBUTING.md を使用してください。現在の文法、レキサー、パースルール、またはリカバリーのタスクに該当するセクションを読んでください。
ワークフロー
- 言語の文法と、周辺のパースルールを確認します。
- リカバリー動作を変更する前に、対象を絞った
ok/とerror/のフィクスチャを追加または調整します。 - 型付きツリーの形が変わる場合は、文法を更新します。
.ungramを変更した後、構文とファクトリーの成果物を再生成します。- 存在チェックを明示し、範囲を限定したリカバリーを使ってパーサーロジックを実装します。
- 言語パーサーの対象を絞ったテストを実行し、スナップショットを確認します。
文法
xtask/codegen/ 以下の文法ファイルでは、型付き構文ノードとフィールドを定義します。既存の言語命名規則に従ってください。
- ノード名には言語名を接頭辞として付けます。
- 名前のユニオンには
Anyを付けます。 - リカバリー可能な無効な構文には
Bogusノードを使用します。 - リストノード名の末尾には
Listを付けます。 - リストは省略可能なフィールドではなく、存在し、空の場合もあるノードとして表現します。
文法を変更した後、次を実行します。
just gen-grammar <lang>
これにより、生成される構文ノード、構文種別、ファクトリー、マクロ、言語固有のマッピングが更新されます。パーサールールは手書きのままです。
存在契約
パース関数が Absent を返すのは、トークンをまったく消費していない場合に限ります。start、bump、eat、expect、または入力を進める可能性がある別のパーサーを呼び出す前に、最初に構文を識別するトークンを確認してください。
次を使用します。
- 不在の場合に診断を生成すべき必須トークンには
expect。 - 省略可能なトークンには
eat。 - 省略可能なノードには
.ok()。 - 必須ノードには
.or_add_diagnostic(...)。 - CST に保持すべき不正なノードには型付きリカバリー。
範囲を限定した先読みや、より正確な存在チェックで構文を識別できる場合は、バックトラッキングを使用しないでください。
エラーリカバリー
リカバリーでは後続の有効な構文を保持し、その位置の文法で許可されている bogus ノードを生成する必要があります。
通常、リカバリーセットには、最も近い該当する次の要素を含めます。
- リストの区切り文字。
- リストまたはブロックの終端。
- 文の境界。
- 次の有効な構文を開始するトークン。
無関係な文法位置のリカバリーセットをそのままコピーしないでください。パースに失敗した後に呼び出し元がどのトークンを想定しているかを確認してください。
リスト
契約が文法に合致する場合は、ループを独自に記述するのではなく、パーサー基盤のリストトレイトを使用してください。
区切り付きリストでは、次の点を確認してください。
- パーサーが囲む終端を認識すること。
- 区切り文字の処理が末尾の区切り文字に関する文法と一致すること。
- 要素が不正な場合に、処理が進むか停止すること。
- リカバリーで囲む終端を消費しないこと。
- 空のリストでも必要なリストノードが生成されること。
レキサーとトークンソース
現在の Lexer と biome_parser のバッファ付きトークンソーストレイトに従ってください。スキルやイシューにある古いトレイト実装をコピーしないでください。
- レキサー基盤が提供する、チェック付きのバイトおよび文字アクセス関数を使用します。
- 同じバイト列がコンテキストによって異なる意味を持つ場合は、レキシングコンテキストを明示します。
- すべてのレキサーパスが入力を進めるか、EOF を返すようにします。
- 有効なマルチバイト文字と文字境界/インデックスの動作をテストするには、
&strを使ったレキサーテストを使用します。不正なバイト列は、既存のバイト指向 API を通じてのみテストしてください。
テスト
パーサーのクイックテストとスナップショットの仕組みについては、testing-codegen を読み込んでください。
- 開発中に CST を確認するには、クレートの
quick_testを使用します。 - パーサークレートで現在使用されている
ok/およびerror/ディレクトリに、永続的なフィクスチャを追加します。 - パーサーのバグ修正には、変更前に失敗していた最小のフィクスチャが必要です。
- リカバリーの変更では、パースが正しく再開することを確認するため、不正な入力の後に有効な構文を続けます。
レビューチェックリスト
Absentのパスでは入力を消費しません。- 必須ノードとトークンが有用な診断を生成します。
- リカバリーで文法に適合した bogus ノードが生成されます。
- すべてのループが入力を進めるか終了します。
- リストのリカバリーは、囲む境界の手前で停止します。
- CST が、不正な入力を含むすべてのソーステキストを保持します。
- 文法の変更に、生成された構文およびファクトリーの成果物が含まれています。
- 有効なフィクスチャと不正なフィクスチャの両方が、変更したパスを検証します。
References
- Parser guide:
crates/biome_parser/CONTRIBUTING.md - Grammars:
xtask/codegen/*.ungram - Parser infrastructure:
crates/biome_parser/src/ - Language implementations:
crates/biome_*_parser/src/