2015-04-21 11 views
14

Zaczynam korzystać z ANTLR i zauważyłem, że jest dość zmienny z jego regułami dla lexerów. Niezwykle frustrujące przykładem jest następujący:ANTLR 4.5 - Niedopasowane wejście "x" oczekiwanie "x"

grammar output; 

test: FILEPATH NEWLINE TITLE ; 

FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ; 
NEWLINE: '\r'? '\n' ; 
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ; 

Ta gramatyka nie pasuje coś takiego:

c: \ test.txt
x

dziwne jeśli zmienię TITLE być TITLE: 'x' ; nadal tym razem nie powiedzie się komunikat o błędzie "niedopasowane wejście" x "oczekiwanie" x "", co jest bardzo mylące. Jeszcze dziwniej, jeśli zastąpię użycie TITLE w test z FILEPATH cała sprawa działa (chociaż FILEPATH będzie pasować więcej niż szukam, aby dopasować, więc ogólnie nie jest to poprawne rozwiązanie dla mnie).

Jestem bardzo zdezorientowany, dlaczego ANTLR popełnia tak ekstremalnie dziwne błędy, a następnie nagle działa bez wyraźnego powodu, gdy tasuje różne rzeczy.

Odpowiedz

31

To wydaje się być powszechne niezrozumienie antlr:

przetwarzania języka w antlr:

Processing Język odbywa się w dwóch ściśle oddzielonych faz:

  • Lexing, czyli partycjonowanie tekst na tokenach
  • Parsowanie, czyli budowanie drzewa parsowania z tokenów

Ponieważ lexing musi poprzedzać przetwarzanie, istnieje konsekwencja: Lexer jest niezależny od analizatora składni, analizator składni nie może wpływać na leksowanie.

Lexing

Lexing w antlr działa w następujący sposób:

  • wszystkie reguły z wielką pierwszego znaku są lexer rządzi
  • lexer rozpoczyna się na początku i stara się znaleźć przepis, który pasuje najlepiej do bieżącego wejścia
  • najlepszym dopasowaniem jest mecz o maksymalnej długości, tj.token, który wynika z dołączania następnego wprowadzania znaków do maksymalnej długości meczu nie idzie w parze z jakiejkolwiek reguły Lexer
  • tokeny są generowane z meczów:
    • jeśli jedna zasada odpowiada Maksymalna długość mecz analogicznym Token jest wpychana do tokenu strumienia
    • jeśli wiele reguł dopasować maksymalne dopasowanie długości pierwszy zdefiniowane żeton w gramatyce jest popychane do tokenu strumienia

Przykład: Co jest nie tak z gramatyki

gramatykę ma dwie zasady, które są krytyczne:

FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ; 
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ; 

każdego meczu, który jest dopasowane tytuł zostanie również dopasowane ŚCIEŻKA PLIKU. I FILEPATH jest zdefiniowany przed TITLE: Więc każdy token, który spodziewałbyś się tytułu, byłby FILEPATH.

Istnieją dwie wskazówki na to:

  • utrzymać lexer rządzi dysjunktywnej (bez tokena należy dopasować rozszerzeniem innego)
  • jeśli tokeny celowo dopasować te same struny, niż umieścić je w odpowiednia kolejność (w twoim przypadku będzie to wystarczające).
  • jeśli trzeba parser napędzany lexer trzeba zmienić na inny generator parsera: PEG-Parsery lub GLR-Parsery zrobi to (ale oczywiście może produkować inne problemy)
+3

To sprawia, że ​​wiele sensu teraz, dzięki za odpowiedź! Byłoby miło mieć bardziej przydatny komunikat o błędzie, ale wiem, że może to być trudne lub nieuzasadnione. –

+0

W czasie wykonywania analizator składni musi zakładać, że użytkownik jest świadomy swojego działania. Mimo to zgadzam się, że ostrzeżenie byłoby w porządku, gdyby dwie zasady leksykalne nakładały się w taki sposób. – CoronA

+1

Świetne podsumowanie z referencji ANTLR! – Cody