ANTLR
Zasady Lexera w wersji 4
Szukaj…
Proste zasady
Reguły Lexera definiują typy tokenów. Ich nazwa musi zaczynać się wielką literą, aby odróżnić je od reguł parsera.
INTEGER: [0-9]+;
IDENTIFIER: [a-zA-Z_] [a-zA-Z_0-9]*;
OPEN_PAREN: '(';
CLOSE_PAREN: ')';
Podstawowa składnia:
| Składnia | Znaczenie |
|---|---|
A | Dopasuj regułę leksykalną lub fragment o nazwie A |
AB | Dopasuj A a następnie B |
(A|B) | Dopasuj A lub B |
'text' | Dopasuj dosłowny „tekst” |
A? | Mecz zero lub jeden raz A |
A* | Mecz zero lub więcej razy A |
A+ | Mecz jeden lub więcej razy A |
[A-Z0-9] | Dopasuj jeden znak w zdefiniowanych zakresach (w tym przykładzie między AZ lub 0-9) |
'a'..'z' | Alternatywna składnia dla zakresu znaków |
~[AZ] | Negacja zakresu - dopasuj dowolny pojedynczy znak spoza zakresu |
. | Dopasuj dowolny pojedynczy znak |
Paprochy
Fragmenty są częściami wielokrotnego użytku reguł leksykalnych, które same nie mogą się dopasować - należy się do nich odwoływać z reguły leksykalnej.
INTEGER: DIGIT+
| '0' [Xx] HEX_DIGIT+
;
fragment DIGIT: [0-9];
fragment HEX_DIGIT: [0-9A-Fa-f];
Niejawne reguły leksykalne
Gdy tokeny takie jak '{' są używane w regule parsera , zostanie utworzona dla nich niejawna reguła leksykalna, chyba że istnieje reguła jawna.
Innymi słowy, jeśli masz regułę leksykalną:
OPEN_BRACE: '{';
Zatem obie reguły parsera są równoważne:
parserRule: '{';
parserRule: OPEN_BRACE;
Ale jeśli nie zdefiniowano reguły OPEN_BRACE , zostanie utworzona domniemana anonimowa reguła. W takim przypadku reguła niejawna zostanie zdefiniowana tak, jakby była zdefiniowana przed innymi regułami: będzie miała wyższy priorytet niż inne reguły.
Zasady pierwszeństwa
Kilka reguł leksykalnych może pasować do tego samego tekstu wejściowego. W takim przypadku typ tokena zostanie wybrany w następujący sposób:
- Najpierw wybierz regułę leksykalną, która pasuje do najdłuższego wejścia
- Jeśli tekst pasuje do domyślnie zdefiniowanego tokena (np.
'{'), Użyj reguły niejawnej - Jeśli kilka reguł leksykalnych odpowiada tej samej długości wejściowej, wybierz pierwszą , na podstawie kolejności definicji
Następująca połączona gramatyka:
grammar LexerPriorityRulesExample;
// Parser rules
randomParserRule: 'foo'; // Implicitly declared token type
// Lexer rules
BAR: 'bar';
IDENTIFIER: [A-Za-z]+;
BAZ: 'baz';
WS: [ \t\r\n]+ -> skip;
Biorąc pod uwagę następujące dane wejściowe:
aaa foo bar baz barz
Wyodrębni następującą sekwencję żetonów z leksera:
IDENTIFIER 'foo' BAR IDENTIFIER IDENTIFIER
aaajest typuIDENTIFIERTylko reguła
IDENTIFIERmoże dopasować ten token, nie ma dwuznaczności.
foojest typu'foo'Reguła parsera
randomParserRulewprowadza domyślny typ tokena'foo', który ma pierwszeństwo przed regułąIDENTIFIER.
barjest typuBARTen tekst jest zgodny z regułą
BARzdefiniowaną przed regułąIDENTIFIER, a zatem ma pierwszeństwo.
bazjest typuIDENTIFIERTen tekst jest zgodny z regułą
BAZ, ale pasuje również do regułyIDENTIFIER. Ten ostatni jest wybierany zgodnie z definicją przedBAR.Biorąc pod uwagę gramatykę,
BAZnigdy nie będzie w stanie dopasować, ponieważ regułaIDENTIFIERobejmuje już wszystko, coBAZmoże dopasować.
barzjest typuIDENTIFIERReguła
BARmoże pasować do pierwszych 3 znaków tego ciągu (bar), ale regułaIDENTIFIERbędzie pasować do 4 znaków. PonieważIDENTIFIERpasuje do dłuższego podłańcucha, jest wybieranyBAR.
Zasadniczo szczegółowe reguły powinny zostać zdefiniowane przed bardziej ogólnymi regułami. Jeśli reguła może pasować tylko do danych wejściowych, które są już objęte wcześniej zdefiniowaną regułą, nigdy nie zostanie użyta.
Niejawnie zdefiniowane reguły, takie jak 'foo' działają tak, jakby były zdefiniowane przed wszystkimi innymi regułami leksykalnymi.
Polecenia Lexera
Reguła leksykalna może mieć powiązane polecenia :
WHITESPACE: [ \r\n] -> skip;
Polecenia są definiowane po -> na końcu reguły.
-
skip:skipdopasowany tekst, żaden token nie będzie emitowany -
channel(n): Emituje token na innym kanale -
type(n): Zmienia typ emitowanego tokena -
mode(n),pushMode(n),popMode,more: Kontroluje trybypopMode
Działania i predykaty semantyczne
Lexer to blok dowolnego kodu w języku docelowym otoczony { ... } , który jest wykonywany podczas dopasowywania:
IDENTIFIER: [A-Z]+ { log("matched rule"); };
Predykat semantyczny to blok arbitralnego kodu w języku docelowym otoczony { ... }? , który daje wartość logiczną. Jeśli zwrócona wartość to false, reguła leksykalna jest pomijana.
IDENTIFIER: [A-Z]+ { identifierIsValid() }?;
O ile to możliwe, ze względów wydajnościowych predykaty semantyczne należy określać na końcu reguły.