2017-04-13 1 views
0

Pourquoi JavaCC donne-t-il toujours une erreur sur le terminal avec lookahead? Comme sur cet exemple,JavaCC a obtenu une erreur lexicale lorsque le lookahead rencontre la fin du fichier

options{ 
    LOOKAHEAD = 2; 
} 

PARSER_BEGIN(GS) 
    public class GS{ 
     public static void main(String args[]) throws ParseException { 
      GS parser = new GS(System.in); 
      parser.q0(); 
     } 
    } 
PARSER_END(GS) 

void q0(): 
{} 
{ 
    "a" q1() | 
    "c" 
} 

void q1(): 
{} 
{ 
    "b" q0() 
    | "b" 
} 

Sur q1() il y a 2 options sommes, on est à lire "b" et passer à q0, ou lire "b" et mettre fin à la lecture. Mais si je donne une entrée "ab" cela donnera une erreur même si elle a l'option lookahead. Mais si je donne "(ab) * c", JavaCC l'accepte très bien.

Exception in thread "main" TokenMgrError: Lexical error at line 1, column 3. Encountered: "\r" (13), after : "" 

Cette même erreur se produit toujours lorsque la règle de production est

{ 
    "terminal_x" non-terminal() 
    | "terminal_x" 
} 

Est-il possible de faire ce genre de règle de production sans donner une erreur? J'utilise JavaCC version. 6.0_1.

merci.

modifier:

Apparemment, si la règle de production est sous la forme

{ 
    "terminal_x" 
    | "terminal_x" non-terminal() 
} 

L'erreur wont est arrivé. Mais encore, quelle est la cause de cette erreur?

Répondre

0

Le problème est que votre chaîne d'entrée contient un caractère de retour que le lexeur n'attend pas. Cela n'a rien à voir avec lookhahead; lookahead a à voir avec l'analyse, pas lexing. Je suggérerais de mettre quelque chose comme ça dans une règle.

SKIP : { " " | "\t" | "\r" | "\n" } 
+0

Je vois, ma mauvaise. Merci cela fonctionne pour moi. Bien que si je donne l'entrée directement à partir de l'invite de commande, il continue d'attendre la saisie. Y at-il une méthode pour dire que la lecture est terminée? – tettra

+0

Sous UNIX ou Mac, utilisez cntl-d. Sous DOS ou Windows, utilisez cntl-z. Ce sera lexé comme un jeton EOF. –

0

La règle d'exemple, vous avez suggéré:

{ 
     "terminal_x" 
     | "terminal_x" non-terminal() 
    } 

est effectivement dire « il doit y avoir "terminal_x" suivi par zéro ou un non-terminal() ». Cela serait fait plus facile à l'aide de l'opérateur ? (zéro ou un) comme ci-dessous:

{ 
     "terminal_x" (non-terminal())? 
    } 

De cette façon, la préanalyse n'est pas nécessaire car il cherchera toujours "terminal_x" et permettre à zéro ou un "non-terminal()", ce qui élimine le problème complètement.

+0

oui, cette forme est plus simple, mais l'erreur persiste. – tettra