2017-09-16 6 views
0

J'utilise actuellement antlr4 pour construire un analyseur, mais j'ai rencontré un problème que j'ai essayé de mon mieux mais que je n'ai pas compris. Pouvez-vous m'aider à l'expliquer et à le résoudre?antlr4 deux règles lexer correspondent à la même chaîne

# grammer file : PluginDoc.g4: 

grammer PluginDoc 

pluginDef : pluginName | pluginDesc; 
pluginName : PluginName IDENTIFIER; 
pluginDesc : PluginDesc TEXT; 

PluginName '@pluginName' 
PluginDesc '@pluginDesc' 

IDENTIFIER : [a-zA-Z_]+; 
TEXT : ~(' ' | '\n' | '\t')+; 

input content is: 
@pluginName kafka 
@pluginDesc abc 

Si je mets IDENTIFIER avant le texte, je vais obtenir "entrée ne correspondent pas 'abc' attendre TEXT" Si je mets TEXT avant IDENTIFIER, je vais obtenir "entrée ne correspondent pas 'kafka' attendre IDENTIFIER"

Il semble que IDENTIFIER et TEXT soient identiques, comment puis-je seulement identifier IDENTIFIER dans pluginName et seulement correspondre à TEXT dans pluginDesc?

+0

Il suffit d'utiliser 'TEXT' pour les deux, puis de valider le nom de l'identifiant dans une phase de post-traitement. –

Répondre

2

Tout d'abord, vous avez plusieurs erreurs dans la grammaire que vous avez publié:

L'en-tête du fichier doit spécifier la grammaire , pas Grammer. Vos jetons Lexer PluginName et PluginDesc n'ont pas deux points devant eux et un point-virgule pour les terminer. C'est aussi une règle (non écrite?) D'écrire vos règles d'analyseur comme toutes les minuscules et vos règles lexer comme majuscules.

grammar PluginDoc; 

pluginDef : pluginName | pluginDesc; 
pluginName : PLUGIN_NAME IDENTIFIER; 
pluginDesc : PLUGIN_DESC TEXT; 

PLUGIN_NAME : '@pluginName'; 
PLUGIN_DESC : '@pluginDesc'; 

IDENTIFIER : [a-zA-Z_]+; 
TEXT : ~(' ' | '\n' | '\t')+; 

Certains des problèmes que j'ai rencontrés lors du test de votre grammaire étaient dus aux espaces non gérés. Tout d'abord, vous devez inclure une règle Lexer pour ignorer les espaces à la fin du fichier après toutes les autres règles Lexer.

WS: [ \n\t\r]+ -> skip; 

Ensuite, il y a un problème avec votre TEXT et IDENTIFIER se heurtant les uns avec les autres. Lorsque le flux de caractères est segmenté par le Lexer, kafka et abc peuvent être à la fois le jeton IDENTIFIER et le jeton TEXT. Depuis les lexes de Lexer de façon top-down, ils sont tous les deux tokenized comme la règle de Lexer vient en premier dans votre grammaire. Cela provoque l'erreur que vous rencontrez - tout ce que vous définissez comme la deuxième règle ne peut pas correspondre dans l'analyseur, car il n'a pas été envoyé en tant que jeton.

Comme suggéré par Lucas, vous devriez probablement faire correspondre les deux comme TEXT et vérifier ensuite la validité de l'entrée dans votre Listener/Visitor.

grammar PluginDoc; 

pluginDef : (pluginName | pluginDesc)* EOF; 
pluginName : PLUGIN_NAME TEXT; 
pluginDesc : PLUGIN_DESC TEXT; 

PLUGIN_NAME: '@pluginName'; 
PLUGIN_DESC: '@pluginDesc'; 

TEXT : ~[ \r\n\t]+; 

WS: [ \r\n\t]+ -> skip; 

J'ai aussi changé la règle pluginDef Parser à

pluginDef : (pluginName | pluginDesc)* EOF; 

car il était mon impression que vous voulez saisir à la fois @pluginName X et @pluginDesc Y à la fois et de les identifier. Si ce n'est pas le cas, n'hésitez pas à revenir à ce que vous aviez auparavant.

L'AST résultant produit par la grammaire modifiée ci-dessus onyour entrée échantillon: enter image description here

Vous pouvez également exécuter ce avec un fichier texte en entrée.

+0

Que signifie «EOF»? –

+0

@GaryGauh EOF est l'identificateur de fin de fichier intégré. Cela peut être la fin littérale du fichier si l'entrée est un fichier, ou le terminal CTRL-Z/D en fonction de votre système d'exploitation. Pour votre exemple ici, cela fonctionnerait probablement sans très bien, mais l'expérience m'a appris à le mettre là pour éviter les problèmes plus tard. –