web-dev-qa-db-fra.com

ANTLR 4.5 - Entrée non concordante 'x' attend 'x'

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.

30
Chiune Sugihara

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:

  • Lexing, c'est-à-dire partitionner le texte en jetons
  • Analyse, c'est-à-dire construction d'un arbre d'analyse à partir des jetons

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:

  • toutes les règles avec le premier caractère majuscule sont des règles de lexer
  • le lexer commence au début et essaie de trouver une règle qui correspond le mieux à l'entrée courante
  • une meilleure correspondance est une correspondance qui a une longueur maximale, c'est-à-dire que le jeton qui résulte de l'ajout du caractère d'entrée suivant à la correspondance de longueur maximale ne correspond à aucune règle de lexer
  • les jetons sont générés à partir des correspondances:
    • si ne règle correspond à correspondance de longueur maximale le jeton correspondant est poussé dans le flux de jetons
    • si règles multiples correspond à correspondance de longueur maximale le premier jeton défini dans la grammaire est poussé vers le flux de jetons

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:

  • gardez vos règles de lexer disjointes (aucun jeton ne doit correspondre à un surensemble d'un autre).
  • si vos jetons correspondent intentionnellement aux mêmes chaînes, mettez-les dans le bon ordre (dans votre cas, cela suffira).
  • si vous avez besoin d'un lexer piloté par l'analyseur, vous devez passer à un autre générateur d'analyseur: les analyseurs PEG ou GLR feront cela (mais bien sûr, cela peut entraîner d'autres problèmes).
55
CoronA

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.

1
Blubber

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.

0
Slesa