¿Qué significa fragmento en ANTLR?
He visto ambas reglas:
fragment DIGIT : '0'..'9';
y
DIGIT : '0'..'9';
¿Cuál es la diferencia?
Un fragmento es algo parecido a una función en línea: hace que la gramática sea más legible y más fácil de mantener.
Un fragmento nunca se contará como un token, solo sirve para simplificar una gramática.
Considerar:
NUMBER: DIGITS | OCTAL_DIGITS | HEX_DIGITS;
fragment DIGITS: '1'..'9' '0'..'9'*;
fragment OCTAL_DIGITS: '0' '0'..'7'+;
fragment HEX_DIGITS: '0x' ('0'..'9' | 'a'..'f' | 'A'..'F')+;
En este ejemplo, hacer coincidir un NÚMERO siempre devolverá un NÚMERO al lexer, independientemente de si coincidió con "1234", "0xab12" o "0777".
fragment
significa en ANTLR. Pero el ejemplo que da es pobre: no quiere que un lexer produzca unNUMBER
token que puede ser un número hexadecimal, decimal u octal. Eso significaría que necesitaría inspeccionar elNUMBER
token en una producción (regla del analizador). Usted puede dejar que la producen mejor léxicoINT
,OCT
yHEX
las fichas y crear una regla de producción:number : INT | OCT | HEX;
. En tal ejemplo, aDIGIT
podría ser un fragmento que sería utilizado por los tokensINT
yHEX
.Según el libro de referencias Definitive Antlr4:
de hecho, mejorarán la legibilidad de sus gramáticas.
mira este ejemplo:
STRING es un lexer que usa una regla de fragmento como ESC. Unicode se usa en la regla Esc y Hex se usa en la regla de fragmento Unicode. Las reglas ESC, UNICODE y HEX no se pueden usar explícitamente.
fuente
La referencia definitiva de ANTLR 4 (página 106):
Conceptos abstractos:
Caso 1: (si necesito el RULE1, RULE2, RULE3 entidades o información de grupo)
Caso2: (si no me importa REGLA1, REGLA2, REGLA3, solo me concentro en REGLA0)
Case3: (es equivalente a Case2, lo que lo hace más legible que Case2)
¿Diferencias entre Case1 y Case2 / 3?
Veamos un ejemplo concreto.
Objetivo: identificar
[ABC]+
,[DEF]+
,[GHI]+
fichasinput.txt
Main.py
Caso1 y resultados:
Alphabet.g4 (Caso1)
Resultado:
Caso2 / 3 y resultados:
Alphabet.g4 (Caso2)
Alphabet.g4 (Caso3)
Resultado:
¿ Viste las partes "grupos de captura " y "grupos que no capturan" ?
Veamos el ejemplo concreto2.
Objetivo: identificar números octales / decimales / hexadecimales
input.txt
Número.g4
Main.py
Resultado:
Si se agrega el modificador 'fragmento' a
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, usted no será capaz de capturar las entidades numéricas (ya que no son fichas más). Y el resultado será:fuente
Esta publicación de blog tiene un ejemplo muy claro donde
fragment
marca una diferencia significativa:La gramática reconocerá '42' pero no '7'. Puede arreglarlo haciendo de dígito un fragmento (o moviendo DIGIT después de INT).
fuente
fragment
, sino el orden de las reglas del lexer.DIGIT
como un fragmento deINT
resuelve el problema solo porque los fragmentos no definen tokens, por lo que se creaINT
la primera regla léxica. Estoy de acuerdo con usted en que este es un ejemplo significativo, pero (en mi opinión) solo para quienes ya saben lo quefragment
significa la palabra clave. Lo encuentro algo engañoso para alguien que está tratando de averiguar el uso correcto de los fragmentos por primera vez.