J'ai commencé à utiliser ANTLR et j'ai remarqué qu'il est assez inconstant avec ses règles de lexer. Un exemple extrêmement frustrant est le suivant:
grammar output;
test: FILEPATH NEWLINE TITLE ;
FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ;
NEWLINE: '\r'? '\n' ;
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ;
Cette grammaire ne correspondra pas à quelque chose comme:
c:\test.txt
X
Curieusement, si je change TITLE
en TITLE: 'x' ;
il échoue toujours cette fois, donnant un message d'erreur disant "entrée non concordante" x "attend" x "", ce qui est très déroutant. Encore plus bizarrement si je remplace l'utilisation de TITLE
dans test
par FILEPATH
tout fonctionne (bien que FILEPATH
correspondra plus que je ne cherche à faire correspondre) donc en général ce n'est pas une solution valable pour moi).
Je suis très confus quant à la raison pour laquelle ANTLR donne des erreurs si étranges et travaille soudainement sans raison apparente lors du brassage des choses.
Cela semble être un malentendu courant de ANTLR
:
Traitement linguistique dans ANTLR:
Le traitement du langage se fait en deux phases strictement séparées:
Puisque le lexing doit précéder l'analyse, il y a une conséquence: le lexer est indépendant de l'analyseur, l'analyseur ne peut pas influencer lexing.
Lexing
Lexing dans ANTLR fonctionne comme suit:
Exemple: qu'est-ce qui ne va pas avec votre grammaire
Votre grammaire a deux règles essentielles:
FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ;
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ;
Chaque correspondance, qui est mise en correspondance par TITLE, sera également mise en correspondance par FILEPATH. Et FILEPATH est défini avant TITLE: Donc, chaque jeton que vous attendez à être un titre serait un FILEPATH.
Il y a deux indices à cela:
Ce n'était pas directement le problème d'OP, mais pour ceux qui ont le même message d'erreur, voici quelque chose que vous pouvez vérifier.
J'ai eu le même Mismatched Input 'x' expecting 'x'
vague message d'erreur lorsque j'ai introduit un nouveau mot clé. La raison pour moi était que j'avais placé la nouvelle clé Word après ma règle de lexer VARNAME
, qui l'a assignée comme nom de variable plutôt que comme nouveau mot-clé. Je l'ai corrigé en plaçant les mots clés avant la règle VARNAME
.
J'ai la même erreur, mais je ne peux pas imaginer quelle règle du lexer pourrait être impliquée.
J'essaie d'analyser certains fichiers CDE de Cobol - je pense que c'est tout à fait spécifique à HP Nonstop.
Quoi qu'il en soit, ce que je veux analyser est quelque chose comme
* SCHEMA PRODUCED DATE - TIME : 1/29/2019 - 15:17:01
?SECTION MYREQUEST,NONSTOP
* Definition MYREQUEST created on 05/11/2016 at 11:05
01 MYREQUEST.
...
et l'analyseur échoue avec
mismatched input '?SECTION foo' expecting '?'
Ma grammaire est la suivante:
grammar CdeFile;
cdeFile : line+ ;
line : sectionLine ;
sectionLine : QUESTIONMARK SECTION sectionName '\r'? '\n' ;
sectionName : TEXTLIST ;
QUESTIONMARK : '?' ;
SECTION: S E C T I O N ;
TEXTLIST : TEXT (',' TEXT)* ;
TEXT : ~[,\n\r"]+ ;
WS : ( ' ' | '\t' | '\f' )+ -> skip;
LINE_COMMENT
: '*' {Column == 1}? '*'* ~('\n'|'\r')* '\r'? '\n' ->skip
;
// case insensitive chars
fragment A:('a'|'A');
fragment B:('b'|'B');
fragment C:('c'|'C');
fragment D:('d'|'D');
fragment E:('e'|'E');
fragment F:('f'|'F');
fragment G:('g'|'G');
fragment H:('h'|'H');
fragment I:('i'|'I');
fragment J:('j'|'J');
fragment K:('k'|'K');
fragment L:('l'|'L');
fragment M:('m'|'M');
fragment N:('n'|'N');
fragment O:('o'|'O');
fragment P:('p'|'P');
fragment Q:('q'|'Q');
fragment R:('r'|'R');
fragment S:('s'|'S');
fragment T:('t'|'T');
fragment U:('u'|'U');
fragment V:('v'|'V');
fragment W:('w'|'W');
fragment X:('x'|'X');
fragment Y:('y'|'Y');
fragment Z:('z'|'Z');
Les valeurs QUESTIONMARK sont synchronisées, tout est reconstruit - toujours ce message étrange.