O que significa fragmento em ANTLR?
Eu vi as duas regras:
fragment DIGIT : '0'..'9';
e
DIGIT : '0'..'9';
Qual é a diferença?
Um fragmento é algo semelhante a uma função embutida: torna a gramática mais legível e mais fácil de manter.
Um fragmento nunca será contado como um token, ele serve apenas para simplificar uma 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')+;
Neste exemplo, combinar um NUMBER sempre retornará um NUMBER para o lexer, independentemente de corresponder a "1234", "0xab12" ou "0777".
fragment
significa no ANTLR. Mas o exemplo que você dá é pobre: você não quer que um lexer produza umNUMBER
token que pode ser um número hexadecimal, decimal ou octal. Isso significa que você precisa inspecionar oNUMBER
token em uma produção (regra do analisador). Você poderia melhor deixar o lexer produzirINT
,OCT
eHEX
os tokens e criar uma regra de produção:number : INT | OCT | HEX;
. Nesse exemplo, aDIGIT
poderia ser um fragmento que seria usado pelos tokensINT
eHEX
.De acordo com o livro de referências Definitive Antlr4:
na verdade, eles vão melhorar a legibilidade de suas gramáticas.
veja este exemplo:
STRING é um lexer que usa a regra de fragmento como ESC .Unicode é usado na regra Esc e Hex é usado na regra de fragmento Unicode. As regras ESC, UNICODE e HEX não podem ser usadas explicitamente.
fonte
A Referência ANTLR 4 Definitiva (Página 106):
Conceitos abstratos:
Case1: (se preciso o RULE1, RULE2, Regra3 entidades ou grupo info)
Caso 2: (se eu não me importo com RULE1, RULE2, RULE3, eu apenas me concentro em RULE0)
Caso 3: (é equivalente ao Caso 2, tornando-o mais legível do que o Caso 2)
Diferenças entre Case1 e Case2 / 3?
Vamos ver um exemplo concreto.
Objetivo: identificar
[ABC]+
,[DEF]+
,[GHI]+
fichasinput.txt
Main.py
Caso 1 e resultados:
Alphabet.g4 (Case1)
Resultado:
Caso 2/3 e resultados:
Alphabet.g4 (Case2)
Alphabet.g4 (Case3)
Resultado:
Você viu partes de "grupos de captura " e "grupos de não captura" ?
Vamos ver o exemplo concreto2.
Objetivo: identificar números octais / decimais / hexadecimais
input.txt
Number.g4
Main.py
Resultado:
Se você adicionar o modificador 'fragmento' para
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, você não será capaz de capturar as entidades numéricas (uma vez que eles não são fichas mais). E o resultado será:fonte
Esta postagem do blog tem um exemplo muito claro em que
fragment
faz uma diferença significativa:A gramática reconhecerá '42', mas não '7'. Você pode consertá-lo criando um fragmento de dígito (ou movendo DIGIT após INT).
fonte
fragment
, mas a ordem das regras do lexer.DIGIT
como um fragmento deINT
resolve o problema simplesmente porque os fragmentos não definem tokens, constituindo assimINT
a primeira regra lexical. Concordo com você que este é um exemplo significativo, mas (imo) apenas para quem já sabe o que afragment
palavra - chave significa. Acho um tanto enganoso para alguém que está tentando descobrir o uso correto de fragmentos pela primeira vez.