Chcę przeanalizować zdefiniowane przez użytkownika języki specyficzne dla domeny. Te języki są zazwyczaj zbliżone do notacji matematycznych (nie analizuję języka naturalnego). Użytkownicy definiują swoje DSL w notacji BNF, w następujący sposób:
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
Wejście podobne 1 + ( 2 * 3 )
musi zostać zaakceptowane, podczas gdy wejście podobne 1 +
musi zostać odrzucone jako niepoprawne, a wejście podobne 1 + 2 * 3
musi zostać odrzucone jako niejednoznaczne.
Główną trudnością jest tutaj radzenie sobie z niejednoznacznymi gramatykami w sposób przyjazny dla użytkownika. Ograniczanie gramatyki do jednoznaczności nie jest opcją: taki jest język - chodzi o to, że pisarze wolą pomijać nawiasy, gdy nie są konieczne, aby uniknąć dwuznaczności. Dopóki wyrażenie nie jest dwuznaczne, muszę je przeanalizować, a jeśli nie jest, muszę je odrzucić.
Mój parser musi działać na dowolnej gramatyce bezkontekstowej, nawet dwuznacznej, i musi akceptować wszystkie jednoznaczne dane wejściowe. Potrzebuję drzewa parsowania dla wszystkich zaakceptowanych danych wejściowych. W przypadku nieprawidłowych lub niejednoznacznych danych wejściowych idealnie chcę mieć dobre komunikaty o błędach, ale na początek wezmę to, co mogę.
Zazwyczaj wywołuję parser na stosunkowo krótkich wejściach, z okazjonalnie dłuższymi wejściami. Zatem asymptotycznie szybszy algorytm może nie być najlepszym wyborem. Chciałbym zoptymalizować dla dystrybucji około 80% danych wejściowych krótszych niż 20 symboli, 19% od 20 do 50 symboli i 1% rzadkich dłuższych danych wejściowych. Prędkość nieprawidłowych danych wejściowych nie jest poważnym problemem. Ponadto oczekuję modyfikacji DSL co około 1000 do 100000 danych wejściowych; Mogę poświęcić kilka sekund na przygotowanie gramatyki, a nie kilka minut.
Jaki algorytm analizowania powinienem zbadać, biorąc pod uwagę moje typowe rozmiary wejściowe? Czy raportowanie błędów powinno być czynnikiem w moim wyborze, czy też powinienem skoncentrować się na analizie jednoznacznych danych wejściowych i ewentualnie uruchomić całkowicie oddzielny, wolniejszy analizator składni, aby uzyskać informacje zwrotne o błędach?
(W projekcie, w którym tego potrzebowałem (jakiś czas temu), użyłem CYK , który nie był zbyt trudny do wdrożenia i działał odpowiednio dla moich rozmiarów wejściowych, ale nie spowodował bardzo fajnych błędów.)
x+y+z
.
+
, więc x+y+z
jest to rzeczywiście dwuznaczne, a zatem błędne.