ANTLR
Lexer regelt in v4
Suche…
Einfache Regeln
Lexer-Regeln definieren Token-Typen. Ihr Name muss mit einem Großbuchstaben beginnen, um sie von den Parserregeln zu unterscheiden.
INTEGER: [0-9]+;
IDENTIFIER: [a-zA-Z_] [a-zA-Z_0-9]*;
OPEN_PAREN: '(';
CLOSE_PAREN: ')';
Grundlegende Syntax:
Syntax | Bedeutung |
---|---|
A | Passen Sie die Lexer-Regel oder das Fragment mit dem Namen A |
AB | Spiel A gefolgt von B |
(A|B) | Passen Sie entweder A oder B |
'text' | Wörtliches "Text" abgleichen |
A? | Match A null oder einmal |
A* | Spiel A null oder mehrmals |
A+ | Spiel A ein- oder mehrmals |
[A-Z0-9] | Stimmen Sie ein Zeichen in den definierten Bereichen ab (in diesem Beispiel zwischen AZ oder 0-9). |
'a'..'z' | Alternative Syntax für einen Zeichenbereich |
~[AZ] | Negation eines Bereichs - Entspricht einem beliebigen Zeichen, das nicht im Bereich liegt |
. | Stimmen Sie jedes einzelne Zeichen ab |
Fragmente
Fragmente sind wiederverwendbare Teile von Lexer-Regeln, die nicht für sich alleine passen können. Sie müssen aus einer Lexer-Regel referenziert werden.
INTEGER: DIGIT+
| '0' [Xx] HEX_DIGIT+
;
fragment DIGIT: [0-9];
fragment HEX_DIGIT: [0-9A-Fa-f];
Implizite Lexer-Regeln
Wenn Token wie '{'
in einer Parser- Regel verwendet werden, wird eine implizite Lexer-Regel erstellt, sofern keine explizite Regel vorhanden ist.
Mit anderen Worten, wenn Sie eine Lexer-Regel haben:
OPEN_BRACE: '{';
Dann sind diese beiden Parserregeln gleichwertig:
parserRule: '{';
parserRule: OPEN_BRACE;
Wenn die Lexer-Regel OPEN_BRACE
nicht definiert ist, wird eine implizite anonyme Regel erstellt. In diesem Fall wird die implizite Regel so definiert, als wäre sie vor den anderen Regeln definiert worden : Sie hat eine höhere Priorität als andere Regeln.
Prioritätsregeln
Mehrere Lexer-Regeln können mit demselben Eingabetext übereinstimmen. In diesem Fall wird der Token-Typ wie folgt ausgewählt:
- Wählen Sie zuerst die Lexer-Regel aus, die der längsten Eingabe entspricht
- Wenn der Text mit einem implizit definierten Token übereinstimmt (wie
'{'
), verwenden Sie die implizite Regel - Wenn mehrere Lexer-Regeln der gleichen Eingabelänge entsprechen, wählen Sie die erste Regel basierend auf der Definitionsreihenfolge aus
Die folgende kombinierte Grammatik:
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;
Gegeben die folgende Eingabe:
aaa foo bar baz barz
Erzeugt die folgende Token-Sequenz aus dem Lexer:
IDENTIFIER 'foo' BAR IDENTIFIER IDENTIFIER
aaa
ist vom TypIDENTIFIER
Nur die
IDENTIFIER
Regel kann diesem Token entsprechen, es gibt keine Mehrdeutigkeit.
foo
ist vom Typ'foo'
Der Parser Regel
randomParserRule
führt den impliziten'foo'
Token - Typen, die über die prioritäre istIDENTIFIER
Regel.
bar
ist vom TypBAR
Dieser Text stimmt mit der
BAR
Regel überein, die vor derIDENTIFIER
Regel definiert wurde, und hat daher Vorrang.
baz
ist vom TypIDENTIFIER
Dieser Text entspricht der
BAZ
Regel, aber auch derIDENTIFIER
Regel. Letzteres wird so gewählt, wie es vorBAR
definiert wurde.Angesichts der Grammatik wird
BAZ
niemals in der Lage sein, Übereinstimmungen zu finden, da dieIDENTIFIER
Regel bereits alles abdeckt, wasBAZ
kann.
barz
ist vom TypIDENTIFIER
Die
BAR
Regel kann mit den ersten 3 Zeichen dieser Zeichenfolge (bar
) übereinstimmen, aber dieIDENTIFIER
Regel entspricht 4 Zeichen. DaIDENTIFIER
mit einem längeren Teilstring übereinstimmt, wird dieser überBAR
.
Als Faustregel sollten bestimmte Regeln vor allgemeineren Regeln definiert werden. Wenn eine Regel nur mit einer Eingabe übereinstimmen kann, die bereits von einer zuvor definierten Regel abgedeckt ist, wird sie niemals verwendet.
Implizit definierte Regeln wie 'foo'
als wären sie vor allen anderen lexer-Regeln definiert worden .
Lexer-Befehle
Eine Lexer-Regel kann Befehle enthalten :
WHITESPACE: [ \r\n] -> skip;
Befehle werden nach einem ->
am Ende der Regel definiert.
-
skip
:skip
den übereinstimmenden Text, es wird kein Token ausgegeben -
channel(n)
: Der Token wird auf einem anderen Kanal ausgegeben -
type(n)
: Ändert den Typ des ausgegebenen Tokens -
mode(n)
,pushMode(n)
,popMode
,more
:popMode
Lexer-Modi
Aktionen und semantische Prädikate
Eine Lexer-Aktion ist ein Block mit beliebigem Code in der Zielsprache, umgeben von {
... }
, der während des Abgleichs ausgeführt wird:
IDENTIFIER: [A-Z]+ { log("matched rule"); };
Ein semantisches Prädikat ist ein Block beliebigen Codes in der Zielsprache, umgeben von {
... }?
, der einen booleschen Wert ergibt. Wenn der zurückgegebene Wert false ist, wird die Lexer-Regel übersprungen.
IDENTIFIER: [A-Z]+ { identifierIsValid() }?;
Semantische Prädikate sollten aus Leistungsgründen möglichst am Ende der Regel definiert werden.