Que signifie fragment dans ANTLR?
J'ai vu les deux règles:
fragment DIGIT : '0'..'9';
et
DIGIT : '0'..'9';
Quelle est la différence?
Un fragment s'apparente un peu à une fonction en ligne: il rend la grammaire plus lisible et plus facile à maintenir.
Un fragment ne sera jamais compté comme un jeton, il ne sert qu'à simplifier une grammaire.
Considérer:
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')+;
Dans cet exemple, la correspondance avec un NUMBER renverra toujours un NUMBER au lexer, qu'il corresponde à «1234», «0xab12» ou «0777».
fragment
signifie ANTLR. Mais l'exemple que vous donnez est médiocre: vous ne voulez pas qu'un lexeur produise unNUMBER
jeton qui peut être un nombre hexadécimal, décimal ou octal. Cela signifierait que vous auriez besoin d'inspecter leNUMBER
jeton dans une production (règle d'analyseur). Vous pouvez mieux laisser le produire lexerINT
,OCT
etHEX
jetons et créer une règle de production:number : INT | OCT | HEX;
. Dans un tel exemple, aDIGIT
pourrait être un fragment qui serait utilisé par les jetonsINT
etHEX
.Selon le livre de références Definitive Antlr4:
en fait, ils amélioreront la lisibilité de vos grammaires.
regardez cet exemple:
STRING est un lexer utilisant une règle de fragment comme ESC. Unicode est utilisé dans la règle Esc et Hex est utilisé dans la règle de fragment Unicode. Les règles ESC et UNICODE et HEX ne peuvent pas être utilisées explicitement.
la source
La référence définitive ANTLR 4 (Page 106) :
Concepts abstraits:
Cas1: (si j'ai besoin rule1, règle2, Règle3 entités ou informations groupe)
Cas 2: (si je m'en fiche RULE1, RULE2, RULE3, je me concentre juste sur RULE0)
Case3: (équivaut à Case2, ce qui le rend plus lisible que Case2)
Différences entre le cas 1 et le cas 2/3?
Voyons un exemple concret.
Objectif: identifier
[ABC]+
,[DEF]+
,[GHI]+
jetonsinput.txt
Main.py
Cas 1 et résultats:
Alphabet.g4 (Cas 1)
Résultat:
Cas 2/3 et résultats:
Alphabet.g4 (Cas 2)
Alphabet.g4 (Cas 3)
Résultat:
Avez-vous vu des parties «groupes de capture » et «groupes sans capture» ?
Voyons l'exemple concret2.
Objectif: identifier les nombres octaux / décimaux / hexadécimaux
input.txt
Numéro.g4
Main.py
Résultat:
Si vous ajoutez le modificateur « fragment » à
DECIMAL_NUMBER
,OCTAL_NUMBER
,HEXADECIMAL_NUMBER
, vous ne serez pas en mesure de saisir les entités numériques (car ils ne sont pas plus des jetons). Et le résultat sera:la source
Cet article de blog a un exemple très clair où
fragment
fait une différence significative:La grammaire reconnaîtra «42» mais pas «7». Vous pouvez le corriger en faisant de digit un fragment (ou en déplaçant DIGIT après INT).
la source
fragment
, mais l'ordre des règles du lexer.DIGIT
tant que fragment deINT
résout le problème simplement parce que les fragments ne définissent pas de jetons, créant ainsiINT
la première règle lexicale. Je suis d'accord avec vous pour dire que c'est un exemple significatif mais (imo) uniquement pour qui sait déjà ce quefragment
signifie le mot - clé. Je trouve cela quelque peu trompeur pour quelqu'un qui essaie de comprendre pour la première fois l'utilisation correcte des fragments.