コンテンツにスキップ

アーキテクチャ

このドキュメントでは、 Biome の内部機能の一部と、それらがプロジェクト内でどのように利用されているかについて説明します。

パーサーのアーキテクチャは rowan の内部フォークによって更新されています。 これは Green and Red tree パターンを実装したライブラリです。

CST (Concrete Syntax Tree) は、 トリビアを含むプログラム内のすべての情報を追跡する AST (Abstract Syntax Tree) によく似たデータ構造です。

トリビア は、プログラムを実行するために不可欠な情報を含んでいます:

  • スペース
  • タブ
  • コメント

トリビアは各ノードに関連付けられ、それぞれのノードは前方トリビアと後方トリビアを持ちます。 コードを左から右へ読む場合、前方トリビアはキーワード前に、後方トリビアはキーワード後に現れるものです。

前方トリビアと後方トリビアは、それぞれ以下のように分類されます:

  • 前方トリビア: トークン/キーワードまでのすべてのトリビア(改行を含む)
  • 後方トリビア: 次の改行までのすべてのトリビア(その改行自体は含まない)

次の JavaScript のスニペットでは、// comment 1 はトークン ; に対する後方トリビアで、// comment 2 はキーワード const に対する前方トリビアです。 下部は、Biome によって表現された CST の簡略版です:

const a = "foo"; // comment 1
// comment 2
const b = "bar";
0: JS_MODULE@0..55
...
1: SEMICOLON@15..27 ";" [] [Whitespace(" "), Comments("// comment 1")]
1: JS_VARIABLE_STATEMENT@27..55
...
1: CONST_KW@27..45 "const" [Newline("\n"), Comments("// comment 2"), Newline("\n")] [Whitespace(" ")]
3: EOF@55..55 "" [] []

設計上、CST は直接アクセスできないようになっていますが、言語の文法から自動生成されたAPIによって、開発者は Red tree からその情報を取得できます。

頑健かつ回復可能なパーサー

Section titled 頑健かつ回復可能なパーサー

CST を構築するためには、パーサーはエラーに対して頑健かつ回復可能である必要があります:

  • 頑健性: 言語の構文エラーに遭遇した後でも解析を再開できるパーサー
  • 回復可能性: エラーが発生した箇所を理解でき、正しい情報を生成することで解析を再開できるパーサー

パーサーの回復可能性は科学的なルールに基づかず、厳格なルールは存在しません。 これは、解析対象やエラー発生箇所によって予測された方法で、パーサーが自己回復できる可能性があることを示します。

パーサーは誤った構文を処理することからコンシューマーを保護するため、 Bogus ノードも使用します。 このノードは、構文エラーに起因する破損したコードを装飾するのに利用されます。

以下の例では、 while の括弧が抜けていますが、パーサーは上手く回復し、適切な CST でコードを表現できています。 ループの条件や括弧が欠落しているとしてマークされ、そしてコードブロックは正しく解析されます:

while {}
JsModule {
interpreter_token: missing (optional),
directives: JsDirectiveList [],
items: JsModuleItemList [
JsWhileStatement {
while_token: WHILE_KW@0..6 "while" [] [Whitespace(" ")],
l_paren_token: missing (required),
test: missing (required),
r_paren_token: missing (required),
body: JsBlockStatement {
l_curly_token: L_CURLY@6..7 "{" [] [],
statements: JsStatementList [],
r_curly_token: R_CURLY@7..8 "}" [] [],
},
},
],
eof_token: EOF@8..8 "" [] [],
}

これは、解析中に発生したエラーです:

main.tsx:1:7 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✖ expected `(` but instead found `{`
> 1 │ while {}
│ ^
ℹ Remove {

次のスニペットは同様ではありません。 パーサーは回復フェーズ中に構文を適切に理解することができず、Bogus ノードに頼って一部の構文をエラーとしてマークする必要があります。 JsBogusStatement に注目してください:

function}
JsModule {
interpreter_token: missing (optional),
directives: JsDirectiveList [],
items: JsModuleItemList [
TsDeclareFunctionDeclaration {
async_token: missing (optional),
function_token: FUNCTION_KW@0..8 "function" [] [],
id: missing (required),
type_parameters: missing (optional),
parameters: missing (required),
return_type_annotation: missing (optional),
semicolon_token: missing (optional),
},
JsBogusStatement {
items: [
R_CURLY@8..9 "}" [] [],
],
},
],
eof_token: EOF@9..9 "" [] [],
}

これは、解析フェーズ中に発生したエラーです:

main.tsx:1:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✖ expected a name for the function in a function declaration, but found none
> 1 │ function}
│ ^

Biome は、タスク実行のためにサーバークライアントアーキテクチャを使用しています。

daemon は、エディターや CLI からのリクエストを処理するために Biome をバッググラウンドで起動し、長時間実行されるサーバーです。