パーサーコンビネーターの概念
小さなパーサーを組み合わせて、より大きなパーサーを構築します。
「パーサーコンビネーターの概念」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。
パーサーとは
パーサーは入力(通常は文字列)を読み取り、構造化された出力を生成するか、失敗します。まずは値のレベルから始めて直感を養い、その後で同じ考え方を型システムに移します。
type Parser<T> = (input: string) => { value: T; rest: string } | null;
// Consumes part of the input, returns a value and the leftover小さなパーサー
最も単純なパーサーは、リテラルのプレフィックスに一致するかを調べます。入力が期待するテキストで始まっていれば成功し、残りの文字列を返します。そうでなければnullを返します。
function literal(prefix: string): Parser<string> {
return input =>
input.startsWith(prefix)
? { value: prefix, rest: input.slice(prefix.length) }
: null;
}
console.log(literal("ab")("abc"));コンビネーター
コンビネーターは小さなパーサーを受け取り、より大きなパーサーを構築します。このように組み合わせていくスタイルが、単純で再利用可能な部品から複雑なパーサーを組み立てる手法をパーサーコンビネーターと呼ぶ理由です。
// Small parsers: digit, letter, literal
// Combinators: sequence, choice, many
// Compose them into: number, identifier, expression逐次実行
シーケンスコンビネーターは、まず1つ目のパーサーを実行し、残りの入力に対して次のパーサーを実行して、結果を組にします。シーケンスが成功するには、両方が成功しなければなりません。
function seq<A, B>(pa: Parser<A>, pb: Parser<B>): Parser<[A, B]> {
return input => {
const ra = pa(input);
if (!ra) return null;
const rb = pb(ra.rest);
if (!rb) return null;
return { value: [ra.value, rb.value], rest: rb.rest };
};
}順序の使用
2つのリテラルを組み合わせて、順番に解析します。結果には、一致した両方の部分と残りの入力が含まれます。
const ab = seq(literal("a"), literal("b"));
const r = ab("abc");
console.log(r); // { value: ["a","b"], rest: "c" }選択
選択コンビネータは最初のパーサーを試し、失敗した場合は2番目のパーサーを試します。これは「数字または文字」のような選択肢を表します。
function alt<T>(p1: Parser<T>, p2: Parser<T>): Parser<T> {
return input => p1(input) ?? p2(input);
}繰り返し
many コンビネータは、失敗するまでパーサーを繰り返し適用し、すべての結果を収集します。これにより、リストや数字の連続、空白を解析できます。
function many<T>(p: Parser<T>): Parser<T[]> {
return input => {
const out: T[] = [];
let rest = input;
let r = p(rest);
while (r) { out.push(r.value); rest = r.rest; r = p(rest); }
return { value: out, rest };
};
}結果の変換
map コンビネータは、消費する入力を変えずにパーサーの結果を変換します。たとえば、一致した数字文字を数値に変換できます。
function map<A, B>(p: Parser<A>, f: (a: A) => B): Parser<B> {
return input => {
const r = p(input);
return r ? { value: f(r.value), rest: r.rest } : null;
};
}組み立てる
これらの少数のコンビネータ(literal、seq、alt、many、map)から、数値や識別子、さらには小規模な式言語まで、実際の文法を解析できます。各層は、その下の層を組み合わせて構成されます。
const digit = alt(literal("0"), literal("1")); // toy digit
const digits = many(digit);
console.log(digits("0110x"));値から型へ
重要な洞察は、同じ合成構造が型レベルでも機能することです。型レベルでは、「入力」は文字列リテラル型であり、パーサーはテンプレートリテラル推論を使う条件型です。次は型レベルへ進みます。
// Value level: (input: string) => { value, rest } | null
// Type level: conditional types over string literal typesなぜ型レベルで解析するのか
型レベルのパーサーを使うと、コンパイラーは文字列リテラルの構造を理解できます。対象には、ルートパス、フォーマット文字列、クエリキーなどがあります。ここで身に付けたコンビネータの直感は、このコースの後半で扱う型レベルのテクニックにそのまま対応します。
// Goal: parse "users/:id" into { id: string } at compile time理解度チェック
パーサーコンビネータについての理解度を確認します。
まとめ
値レベルでパーサーの基本的な考え方を身に付けました。
- パーサーは入力を消費し、残りの入力と値を返すか、失敗します。
- コンビネータ(seq、alt、many、map)は、小さなパーサーを組み合わせて大きなパーサーを作ります。
- 同じ構造を型レベルにも適用できます。
次は、型システムで文字列を分割します。
よくある質問
「パーサーコンビネーターの概念」レッスンは無料ですか?
はい。「パーサーコンビネーターの概念」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。
「パーサーコンビネーターの概念」で何を学びますか?
小さなパーサーを組み合わせて、より大きなパーサーを構築します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「パーサーコンビネーターの概念」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- パーサーコンビネーターの概念
- 型レベルの文字列分割
- テンプレートリテラルによる解析
- 型レベルのミニルートパーサー