PEG.js: Generátor parserů pro JavaScript
Dnešní webové aplikace jsou stále závislejší na JavaScriptu. Spousta věcí, které se dřív dělaly na serveru, se nyní řeší na straně klienta. Jedním z takových úkolů je i zpracování nejrůznějších formátů dat.
V JavaScriptu není problém zpracovat běžné formáty jako JSON nebo XML, ale s jakýmkoliv složitějším formátem, nebo dokonce jazykem, přijdou potíže. Obvykle je třeba buď najít nějakou chytrou knihovnu, nebo si napsat vlastní parser.
Parsery se dnes běžně píšou pomocí generátorů, které parser vygenerují z gramatiky zpracovávaného jazyka. Když jsem ale před časem potřeboval takový generátor v JavaScriptu použít, narazil jsem – nenašel jsem totiž žádný dostatečně dobrý. Existující generátory jsou vesměs založeny na variacích na téma LR parsing (který nemám rád a navíc má různá omezení), mají ošklivé zápisy gramatik, neumí dobře ošetřovat chyby a mají i jiné další neduhy. A tak se nevyhnutelně stalo, že jsem si napsal generátor vlastní.
Uvítejte PEG.js
PEG.js je generátor parserů pro JavaScript. Je založen na formalismu parsing expression grammar (PEG), což vám asi nic neřekne, ale znamená to několik věcí:
- Zápis gramatiky je příjemný a uživatel má při něm k dispozici poměrně
bohaté vyjadřovací prostředky. Konkrétně jde především o operátory
*
,+
a?
, známé z regulárních výrazů, které je v klasických generátorech obvykle nutné nahrazovat rekurzivními pravidly. - Lexikální a syntaktická analýza splývá. Na zpracování jazyka je tak potřeba jen jeden nástroj.
- Nedochází ke konfliktům při nejednoznačnostech v gramatice jako u parserů založených na LR parsingu. Vše se řeší prioritami pravidel.
- Třída zpracovávaných jazyků je poměrně velká (pro odborníky: nadmnožina LR(k) i LL(k)).
Pro další informace o PEG doporučuji přečíst článek Parsing Expression Grammars: A Recognition-Based Syntactic Foundation (PDF).
K těmto vlastnostem plynoucích z použitého formalismu přidává PEG.js především kvalitní chybová hlášení při parsování – poloha chyby je přesně určena a hlášení je srozumitelné pro člověka.
Jak PEG.js funguje?
PEG.js je klasický generátor, z gramatiky tedy vygeneruje kus kódu, který zpracovává popisovaný jazyk. Zda z jednotlivých prvků jazyka postavíte syntaktický strom, vypíšete je na výstup, nebo nějak zpracujete, je plně na vás – PEG.js umožňuje v libovolném okamžiku zavolat kód v JavaScriptu, kterému je předána část zpracovaného vstupu v podobě javascriptových hodnot. Kód může tyto hodnoty libovolně ztransformovat.
Parser je možné vygenerovat z příkazové řádky (stačí pokud máte nainstalovanou Javu – využíván je interpret JavaScriptu Rhino) a nebo online na stránkách projektu. Druhý způsob se může hodit při ladění a také umožňuje si vygenerovaný parser hned vyzkoušet na různých vstupech přímo v prohlížeči. Jednodušší snad už tvorba parseru ani být nemůže.
Začlenění vygenerovaného parseru např. do webové aplikace je otázka přidání
dvou elementů <script>
(pro parser samotný a pro malý
(2 kB) runtime, který potřebuje k svému běhu).
Zaujalo?
Zaujal vás PEG.js? Pokud ano, budu rád, když si ho vyzkoušíte. Narazíte-li na nějakou chybu či nedostatek, dejte mi vědět (nejlépe napsat do diskuzní skupiny nebo použít issue tracker). V tuto chvíli je projekt v relativně rané fázi vývoje a lecos se ještě může změnit (např. formát gramatiky), rád bych ale generátor postupně vyladil a stabilizoval tak, aby nebyl problém ho nasadit na reálných projektech. Když už kvůli ničemu jinému, tak proto, že ho chci sám používat.