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 Typ IDENTIFIER

    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 ist IDENTIFIER Regel.

  • bar ist vom Typ BAR

    Dieser Text stimmt mit der BAR Regel überein, die vor der IDENTIFIER Regel definiert wurde, und hat daher Vorrang.

  • baz ist vom Typ IDENTIFIER

    Dieser Text entspricht der BAZ Regel, aber auch der IDENTIFIER Regel. Letzteres wird so gewählt, wie es vor BAR definiert wurde.

    Angesichts der Grammatik wird BAZ niemals in der Lage sein, Übereinstimmungen zu finden, da die IDENTIFIER Regel bereits alles abdeckt, was BAZ kann.

  • barz ist vom Typ IDENTIFIER

    Die BAR Regel kann mit den ersten 3 Zeichen dieser Zeichenfolge ( bar ) übereinstimmen, aber die IDENTIFIER Regel entspricht 4 Zeichen. Da IDENTIFIER mit einem längeren Teilstring übereinstimmt, wird dieser über BAR .

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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow