0Pricing
TypeScript Academy · Lekcja

Koncepcje kombinatorów parserów

Komponuj małe parsery w większe

Koncepcje kombinatorów parserów to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 4 lekcji w sumie.

Czym jest parser

Parser odczytuje dane wejściowe (zwykle ciąg znaków) i tworzy uporządkowany wynik albo kończy działanie niepowodzeniem. Najpierw zaczniemy od poziomu wartości, aby zbudować intuicję, a następnie przeniesiemy te same idee do systemu typów.

type Parser<T> = (input: string) => { value: T; rest: string } | null;
// Consumes part of the input, returns a value and the leftover

Mały parser

Najprostszy parser dopasowuje dosłowny prefiks. Jeśli dane wejściowe zaczynają się od oczekiwanego tekstu, parser kończy się powodzeniem i zwraca pozostały ciąg; w przeciwnym razie zwraca 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"));

Kombinatory

Kombinator przyjmuje małe parsery i buduje z nich większe. Ten kompozycyjny styl jest powodem, dla którego podejście nazywa się kombinatorami parserów: złożone parsery składa się z prostych, wielokrotnego użytku elementów.

// Small parsers: digit, letter, literal
// Combinators: sequence, choice, many
// Compose them into: number, identifier, expression

Sekwencjonowanie

Kombinator sekwencji uruchamia jeden parser, a następnie kolejny na pozostałych danych, łącząc ich wyniki w parę. Oba parsery muszą zakończyć się powodzeniem, aby sekwencja zakończyła się powodzeniem.

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 };
  };
}

Używanie sekwencji

Połącz dwa literały, aby przeanalizować je w określonej kolejności. Wynik zawiera oba dopasowane fragmenty oraz pozostałe dane wejściowe.

const ab = seq(literal("a"), literal("b"));
const r = ab("abc");
console.log(r); // { value: ["a","b"], rest: "c" }

Wybór

Kombinator wyboru najpierw próbuje użyć pierwszego parsera; jeśli ten zawiedzie, próbuje drugiego. Pozwala to wyrażać alternatywy, takie jak „cyfra albo litera”.

function alt<T>(p1: Parser<T>, p2: Parser<T>): Parser<T> {
  return input => p1(input) ?? p2(input);
}

Powtarzanie

Kombinator many wielokrotnie stosuje parser, aż do jego niepowodzenia, zbierając wszystkie wyniki. Umożliwia to parsowanie list, ciągów cyfr lub białych znaków.

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 };
  };
}

Mapowanie wyników

Kombinator map przekształca wynik parsera bez zmiany tego, co parser konsumuje, na przykład zamienia dopasowane znaki cyfr w liczbę.

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;
  };
}

Rozbudowa

Na podstawie tych kilku kombinatorów (literal, seq, alt, many, map) można parsować rzeczywiste gramatyki: liczby, identyfikatory, a nawet małe języki wyrażeń. Każda warstwa buduje na warstwie znajdującej się niżej.

const digit = alt(literal("0"), literal("1")); // toy digit
const digits = many(digit);
console.log(digits("0110x"));

Od wartości do typów

Kluczowa obserwacja jest taka, że ta sama struktura kompozycyjna działa również na poziomie typów. Na tym poziomie „danymi wejściowymi” są typy literałów tekstowych, a parserami — typy warunkowe wykorzystujące wnioskowanie z literałów szablonowych. Następnie przejdziemy do tego poziomu.

// Value level: (input: string) => { value, rest } | null
// Type level:  conditional types over string literal types

Dlaczego parsowanie na poziomie typów

Parsery na poziomie typów pozwalają kompilatorowi rozumieć strukturę literałów tekstowych: ścieżki routingu, ciągi formatujące czy klucze zapytań. Zbudowana tutaj intuicja dotycząca kombinatorów bezpośrednio przekłada się na techniki pracy na poziomie typów przedstawione w dalszej części kursu.

// Goal: parse "users/:id" into { id: string } at compile time

Szybki test

Proszę sprawdzić swoją wiedzę na temat kombinatorów parserów.

Podsumowanie

Zbudowano podstawową intuicję dotyczącą parserów na poziomie wartości.

  • Parser konsumuje dane wejściowe i zwraca wartość wraz z pozostałymi danymi albo kończy działanie niepowodzeniem.
  • Kombinatory (seq, alt, many, map) łączą małe parsery w większe.
  • Ta sama struktura ma zastosowanie na poziomie typów.

Następnie: dzielenie ciągów znaków w systemie typów.

Często zadawane pytania

Czy lekcja „Koncepcje kombinatorów parserów” jest bezpłatna?

Tak — pełny tekst „Koncepcje kombinatorów parserów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Koncepcje kombinatorów parserów”?

Komponuj małe parsery w większe Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?

Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Koncepcje kombinatorów parserów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?

Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Koncepcje kombinatorów parserów
  2. Dzielenie stringów na poziomie typów
  3. Parsowanie za pomocą literałów szablonowych
  4. Mini parser ścieżek routingu na poziomie typów
← Powrót do TypeScript Academy