ANTLR
Reglas Lexer en v4
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 tipoIDENTIFIER
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 reglaIDENTIFIER
.
bar
es de tipoBAR
Este texto coincide con la regla
BAR
, que se define antes que la reglaIDENTIFIER
, y por lo tanto tiene prioridad.
baz
es de tipoIDENTIFIER
Este texto coincide con la regla
BAZ
, pero también coincide con la reglaIDENTIFIER
. Este último es elegido como se define antes deBAR
.Dada la gramática,
BAZ
nunca podrá coincidir, ya que la reglaIDENTIFIER
ya cubre todo lo queBAZ
puede igualar.
barz
es de tipoIDENTIFIER
La regla
BAR
puede coincidir con los primeros 3 caracteres de esta cadena (bar
), pero la reglaIDENTIFIER
coincidirá con 4 caracteres. ComoIDENTIFIER
coincide con una subcadena más larga, se elige sobreBAR
.
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.