Recherche…


Règles simples

Les règles Lexer définissent les types de jeton. Leur nom doit commencer par une lettre majuscule pour les distinguer des règles d’analyseur.

INTEGER: [0-9]+;
IDENTIFIER: [a-zA-Z_] [a-zA-Z_0-9]*;

OPEN_PAREN: '(';
CLOSE_PAREN: ')';

Syntaxe de base:

Syntaxe Sens
A Faire correspondre la règle ou le fragment lexer nommé A
AB Match A suivi de B
(A|B) Match soit A ou B
'text' Match littéral "texte"
A? Match A zéro ou une fois
A* Match A zéro ou plusieurs fois
A+ Match A une ou plusieurs fois
[A-Z0-9] Faire correspondre un caractère dans les plages définies (dans cet exemple, entre AZ et 0-9)
'a'..'z' Syntaxe alternative pour une plage de caractères
~[AZ] Négation d'une plage - correspond à n'importe quel caractère unique qui n'est pas dans la plage
. Correspond à n'importe quel caractère

Fragments

Les fragments sont des parties réutilisables des règles de lexer qui ne peuvent pas correspondre seules. Elles doivent être référencées à partir d'une règle de lexer.

INTEGER: DIGIT+
       | '0' [Xx] HEX_DIGIT+
       ;

fragment DIGIT: [0-9];
fragment HEX_DIGIT: [0-9A-Fa-f];

Règles implicites de lexer

Lorsque des jetons comme '{' sont utilisés dans une règle d' analyse , une règle lexer implicite sera créée à moins qu'une règle explicite n'existe.

En d'autres termes, si vous avez une règle de lexer:

OPEN_BRACE: '{';

Ensuite, ces deux règles d'analyse sont équivalentes:

parserRule: '{';
parserRule: OPEN_BRACE;

Mais si la règle OPEN_BRACE OPEN_BRACE n'est pas définie, une règle anonyme implicite sera créée. Dans ce cas, la règle implicite sera définie comme si elle était définie avant les autres règles: elle aura une priorité plus élevée que les autres règles.

Règles de priorité

Plusieurs règles de lexer peuvent correspondre au même texte d'entrée. Dans ce cas, le type de jeton sera choisi comme suit:

  • Tout d'abord, sélectionnez la règle lexer qui correspond à l'entrée la plus longue
  • Si le texte correspond à un jeton défini implicitement (comme '{' ), utilisez la règle implicite
  • Si plusieurs règles de lexer correspondent à la même longueur d'entrée, choisissez la première en fonction de l'ordre de définition.

La grammaire combinée suivante:

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;

Compte tenu de l'entrée suivante:

aaa foo bar baz barz

Produira la séquence de jetons suivante à partir du lexer:

IDENTIFIER 'foo' BAR IDENTIFIER IDENTIFIER
  • aaa est de type IDENTIFIER

    Seule la règle IDENTIFIER peut correspondre à ce jeton, il n'y a pas d'ambiguïté.

  • foo est de type 'foo'

    La règle d'analyse syntaxique randomParserRule introduit le type de jeton implicite 'foo' , qui est prioritaire sur la règle IDENTIFIER .

  • bar est du type BAR

    Ce texte correspond à la règle BAR définie avant la règle IDENTIFIER et a donc la priorité.

  • baz est de type IDENTIFIER

    Ce texte correspond à la règle BAZ , mais il correspond également à la règle IDENTIFIER . Ce dernier est choisi tel qu'il est défini avant BAR .

    Compte tenu de la grammaire, BAZ ne sera jamais en mesure de correspondre, car la règle IDENTIFIER couvre déjà tout ce que BAZ peut égaler.

  • barz est du type IDENTIFIER

    La règle BAR peut correspondre aux 3 premiers caractères de cette chaîne ( bar ), mais la règle IDENTIFIER correspond à 4 caractères. Comme IDENTIFIER correspond à une sous-chaîne plus longue, il est choisi sur BAR .

En règle générale, les règles spécifiques doivent être définies avant des règles plus génériques. Si une règle ne peut correspondre qu'à une entrée déjà couverte par une règle précédemment définie, elle ne sera jamais utilisée.

Les règles implicitement définies telles que 'foo' agissent comme si elles étaient définies avant toutes les autres règles lexer.

Commandes Lexer

Une règle lexer peut avoir des commandes associées:

WHITESPACE: [ \r\n] -> skip;

Les commandes sont définies après un -> à la fin de la règle.

  • skip : ignore le texte correspondant, aucun jeton ne sera émis
  • channel(n) : émet le jeton sur un canal différent
  • type(n) : change le type de jeton émis
  • mode(n) , pushMode(n) , popMode , more : contrôle les modes lexer

Actions et prédicats sémantiques

Une action lexer est un bloc de code arbitraire dans le langage cible entouré de { ... } , qui est exécuté lors de la correspondance:

IDENTIFIER: [A-Z]+ { log("matched rule"); };

Un prédicat sémantique est un bloc de code arbitraire dans le langage cible entouré de { ... }? , qui évalue une valeur booléenne. Si la valeur renvoyée est false, la règle lexer est ignorée.

IDENTIFIER: [A-Z]+ { identifierIsValid() }?;

Les prédicats sémantiques doivent être définis à la fin de la règle chaque fois que cela est possible pour des raisons de performances.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow