Kolony

Až dosud jsme v případech složitějších transformací výsledků parserů volili cestu definování jednoúčelového predikátu a jeho následné použití v mutátoru aplikace sémantické operace.

V této části si představíme dva predikáty vyššího řádu, které umožní zapisovat některé složitější operace na výsledcích přímo v parametru mutátoru <@.

První z nich pokrývá potřebu následné aplikace několika operací. Pomocí predikátu =>, jenž je definován rovněž jako operátor, lze řetězit sémantické operace nad syntaktickými stromy:

$Parser$ <@ $Goal_1$ => $Goal_2$
Na syntaktický strom vydaný parserem je aplikována operace $Goal_1$ a její výsledná hodnota se stává vstupním argumentem operace $Goal_2$. Nakonec je výsledek $Goal_2$ uložen do seznamu úspěšných rozkladů.

Obecně lze samozřejmě řetězit libovolný počet operací:

$Parser$ <@ $Goal_1$ => ...=> $Goal_n$
Syntaktický strom potom prochází celou kolonou predikátů $Goal_i$. V každém kroku je příchozí hodnota transformována a předána na vstup následující operace.

Nově definovaný predikát => umožňuje efektivnější provedení této konstrukce. Bez něj bychom museli výše uvedený případ transformace v několika krocích implementovat výhradně s pomocí mutátoru aplikace sémantické operace:

$Parser$ <@ $Goal_1$ <@ ...<@ $Goal_n$
Takové zpracování obnáší $n$ průchodů seznamu úspěšných rozkladů. Zatímco s rostoucí délkou struktury LOS se toto řešení stává nepoužitelným, při použití predikátu => jsou aplikovány všechny operace v jednom kroku -- vždy tedy postačuje jediný průchod.

V úvodu zmíněný druhý predikát vyššího řádu je určený pro specifikaci argumentů následujících za výsledkem pocházejícím ze seznamu úspěšných rozkladů. Doposud bylo možné používat v parametru mutátoru <@ pouze operace s rozhraním:

$fun(A_1, \dots, A_n, LosItem, Result)$
Kdy se za přímo specifikované argumenty $A_i$ připojil buď mutátor aplikace sémantické operace nebo operátor => výstup parseru $LosItem$ a parametr $Result$ v němž je také výsledek operace vydán. Aby bylo možné specifikovat také další parametry následující za položkou struktury LOS tj. abychom mohli aplikovat operace tvaru:
$fun(A_1, \dots, A_n, LosItem, B_1, \dots, B_m, Result)$
zavedeme predikát ->>, který po jednom přidává parametry $B_i$. Až teprve v okamžiku, kdy je připojen poslední parametr, je cíl doplněn o $Result$ a zavolán. Právě zde lze využít mechanismu curryfikace, cíle jsou totiž volány prostřednictvím predikátů :-@/1 zavedeného v kapitole [*]. Výsledky procházející kolonou -- nemusí tedy být přímo vyhodnocovány, ale může dojít pouze k částečné aplikaci, kterou lze uskutečnit i ve více krocích.

Predikát ->> je zaveden jako infixní operátor. Má nižší precedenci tj. vyšší prioritu než =>:

$Parser$ <@ $A$ ->> $B$ ->> $C$ => $D$ ->> $E$ ->> $F$
$\Leftrightarrow$
$Parser$ <@ ($A$->>$B$->>$C$) => ($D$->>$E$->>$F$)
Jeho použití je přínosné zejména při jeho vícenásobné zřetězené aplikaci -- jak je vidět na následujícím příkladu:
$Parser$ <@ $fun(A_1, \dots, A_n)$ ->> $B_1$ ->> ...->> $B_m$
kde aplikovaná sémantická operace odpovídá:
:-@ $[A_1, \dots, A_n,+LOS,B_1, \dots, B_m, -Result]$
Oba nové operátory lze samozřejmě libovolně kombinovat. Tak například zpracování výsledku:
$Parser$ <@ $fun_1$ => $fun_2(a,b)$ ->> $c$ ->> $d$->> $e$ => $fun_3(g)$
odpovídá následující transformaci hodnoty $LosItem$ na $Result$:
$fun_1(+LosItem,-F_1),$ $fun_2(a,b,+F_1,c,d,e,-F_2),$ $fun_3(g,+F_2,-Result)$

Kolony zčitelňují kód parserů a činí jej srozumitelnějším. Bohužel nejsou zpravidla tak efektivní, jako je použití explicitně definovaného jednoúčelového predikátu.

Hlavní uplatnění nacházejí v parserech generovaných online, kde hrají nezastupitelnou roli při transformacích syntaktického stromu.

Jsou přínosné i při přímém vytváření parserů na příkazové řádce interpretu, kde můžeme snadno, ať už pro ladící účely či z jiného důvodu, upravovat výstupní hodnoty parserů bez nutnosti přidávání nového predikátu do databáze.

Zvážení všech hledisek při použití kolon -- tedy zejména rozhodnutí mezi mírou elegance a efektivity, záleží pouze na programátorovi.

dvorka 2013-12-31