Buscar..


Reglas simples

Las reglas de Lexer definen tipos de token. Su nombre debe comenzar con una letra mayúscula para distinguirlos de las reglas del analizador.

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

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

Sintaxis básica:

Sintaxis Sentido
A Coincidir con la regla de lexer o fragmento llamado A
AB Match A seguido de B
(A|B) Coincidir con A o B
'text' Emparejar literal "texto"
A? Match A cero o una vez
A* Match A cero o más veces
A+ Match A una o más veces
[A-Z0-9] Haga coincidir un carácter en los rangos definidos (en este ejemplo entre AZ o 0-9)
'a'..'z' Sintaxis alternativa para un rango de caracteres
~[AZ] Negación de un rango - coincide con cualquier carácter individual que no esté en el rango
. Coincidir con cualquier carácter individual

Fragmentos

Los fragmentos son partes reutilizables de las reglas de lexer que no pueden coincidir por sí solas: deben ser referenciados desde una regla de lexer.

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

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

Reglas lexer implícitas

Cuando se usan tokens como '{' en una regla de analizador , se creará una regla implícita de lexer para ellos a menos que exista una regla explícita.

En otras palabras, si tiene una regla lexer:

OPEN_BRACE: '{';

Entonces estas dos reglas del analizador son equivalentes:

parserRule: '{';
parserRule: OPEN_BRACE;

Pero si la regla OPEN_BRACE no está definida, se creará una regla anónima implícita. En ese caso, la regla implícita se definirá como si se definiera antes que las otras reglas: tendrá una prioridad más alta que otras reglas.

Reglas de prioridad

Varias reglas lexer pueden coincidir con el mismo texto de entrada. En ese caso, el tipo de token se elegirá de la siguiente manera:

  • Primero, seleccione la regla lexer que coincida con la entrada más larga
  • Si el texto coincide con un token definido implícitamente (como '{' ), use la regla implícita
  • Si varias reglas lexer coinciden con la misma longitud de entrada, elija la primera , según el orden de definición

La siguiente gramática combinada:

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;

Dada la siguiente entrada:

aaa foo bar baz barz

Producirá la siguiente secuencia de token desde el lexer:

IDENTIFIER 'foo' BAR IDENTIFIER IDENTIFIER
  • aaa es de tipo IDENTIFIER

    Solo la regla IDENTIFIER puede coincidir con este token, no hay ambigüedad.

  • foo es de tipo 'foo'

    La regla del analizador randomParserRule introduce el tipo de token 'foo' implícito, que es prioritario sobre la regla IDENTIFIER .

  • bar es de tipo BAR

    Este texto coincide con la regla BAR , que se define antes que la regla IDENTIFIER , y por lo tanto tiene prioridad.

  • baz es de tipo IDENTIFIER

    Este texto coincide con la regla BAZ , pero también coincide con la regla IDENTIFIER . Este último es elegido como se define antes de BAR .

    Dada la gramática, BAZ nunca podrá coincidir, ya que la regla IDENTIFIER ya cubre todo lo que BAZ puede igualar.

  • barz es de tipo IDENTIFIER

    La regla BAR puede coincidir con los primeros 3 caracteres de esta cadena ( bar ), pero la regla IDENTIFIER coincidirá con 4 caracteres. Como IDENTIFIER coincide con una subcadena más larga, se elige sobre BAR .

Como regla general, las reglas específicas deben definirse antes que las reglas más genéricas. Si una regla solo puede coincidir con una entrada que ya está cubierta por una regla definida previamente, nunca se utilizará.

Las reglas definidas implícitamente, como 'foo' actúan como si estuvieran definidas antes que todas las demás reglas del lexer.

Comandos de Lexer

Una regla lexer puede tener comandos asociados:

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

Los comandos se definen después de un -> al final de la regla.

  • skip : skip el texto coincidente, no se emitirá ningún token
  • channel(n) : emite el token en un canal diferente
  • type(n) : cambia el tipo de token emitido
  • mode(n) , pushMode(n) , popMode , more : controla los modos del lexer

Acciones y predicados semánticos.

Una acción lexer es un bloque de código arbitrario en el idioma de destino rodeado por { ... } , que se ejecuta durante la coincidencia:

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

Un predicado semántico es un bloque de código arbitrario en el idioma de destino rodeado por { ... }? , que se evalúa a un valor booleano. Si el valor devuelto es falso, se omite la regla de lexer.

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

Los predicados semánticos deben definirse al final de la regla siempre que sea posible por razones de rendimiento.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow