Generátory parserů

Třetí a poslední kategorií konstruktorů jsou generátory parserů. Typicky jsou to predikáty vyššího řádu umožňující automatizované vytváření parserů, jenž na rozdíl od dvou předchozích kategorií v rámci své práce neprovádějí aplikování parserů, nýbrž používají parsery a jejich konstruktory pouze jako stavební materiál. Generátory v této práci se od generátorů používaných v různých nástrojích pro vytváření parserů liší v tom, že jednak využívají při své práci širší spektrum kombinátorů a dále má jejich použití zpravidla online charakter -- vygenerovaný parser obvykle není po svém zkonstruování ukládán pro pozdější použití, ale je okamžitě aplikován.

Prvním zástupcem této kategorie, kterého si ukážeme je velmi jednoduchý generátor, jenž vytváří nové parsery řetězením pomocí daného konstruktoru s pravou asociativitou. Je parametrizován jednak kombinátorem, který má být pro řetězení použit, dále pak seznamem samotných parserů. Definujeme jej ve dvou variantách -- první bez terminátoru:

% convoy(+Binder, +ListOfParsers, -Convoy)
convoy(_,[P],P).
convoy(B,[H|T],Convoy):-
        Convoy=..[B,H,TConvoy],
        convoy(B,T,TConvoy).
convoy(_,[],terminate).
a druhé s ním:
% convoy(+Binder, +Terminator, +ListOfParsers, -Convoy)
convoy(B,T,Ps,C):-
        foldR(convoy_(B),T,Ps,C).
Vstupním parametrem obou generátorů je jednak výše zmíněný kombinátor $Binder$ a dále seznam parserů $ListOfParsers$. Parametr $Terminator$ ve druhé variantě je parser, který se má stát článkem uzavírajícím vytvářený řetězec. Výsledkem volání predikátu je vygenerovaný parser $Convoy$. Využijeme nyní convoy k definici dvou speciálnějších generátorů.

Prvním z nich je sequence vytvářející z množiny parserů jejich sekvenční kompozici:

% sequence(+ListOfParsers, -Convoy)
sequence(Ps,C):-
        convoy(<&>,Ps,C).

% sequence(+ListOfParsers, +Terminator, -Convoy)
sequence(Ps,T,C):-
        convoy(<&>,T,Ps,C).
Opět je zaveden ve dvou variantách lišících se použitím terminátoru. Jeho parametry mají stejný význam jako v případě generátoru convoy.

Slibovanou druhou aplikací generátoru convoy je choice vytvářející alternativní kompozici daných parserů:

% choice(+ListOfParsers, -Convoy)
choice(Ps,C):-
        convoy(<:>,Ps,C).

% choice(+ListOfParsers, +Terminator, -Convoy)
choice(Ps,T,C):-
        convoy(<:>,T,Ps,C).
Specializované generátory sequencechoice jsme zavedli, protože kombinátory <&><:> patří mezi nejpoužívanější. Co se týče ostatních kombinátorů, convoy lze zpravidla použít bez problémů, neboť všechny kombinátory definované jako operátory jsou pravě asociativní.

Použití těchto generátorů si můžeme představit v situacích, kdy nejdříve přichází definice dat, jež obsahuje například specifikaci klíčových slov, povolených separátorů a podobně, a za ní teprve následuje samotný text určený ke zpracování. Analýzou části definující příchozí data se získají parametry pro generátory, s jejichž pomocí se online vytvoří parser pro tyto struktury, který lze vzápětí použít.



Subsections
dvorka 2013-12-31