2010-07-19 13 views
4

J'utilise Lemon comme générateur de parseur, sa gestion des erreurs est la même que celle de yacc et de bison si vous ne connaissez pas Lemon.Récupérer des jetons d'erreur dans l'analyse (Lemon)

Lemon a une option pour définir le jeton d'erreur dans un ensemble de règles afin d'intercepter les erreurs d'analyse. Le comportement par défaut de l'analyseur généré est de détruire le jeton provoquant l'erreur; est-il possible de contourner ce comportement afin que je puisse garder le jeton?

Voici un exemple pour montrer ce qui se passe: au fond, je suis annexant les jetons pour chaque règle ensemble pour réformer la chaîne d'entrée, voici une grammaire exemple:

input ::= string(A) { printf("%s", A); } // Print the result 
string(A) ::= string(B) part(C). { A = append(B, C); } 
string(A) ::= part(B). { A = B; } 
part(A) ::= NUMBER(B) NAME(C). { A = append(C, B); } // Rearrange the number and name 
part(A) ::= error(B). { A = B; } // On error keep the token anyways 

En entrée:

"Username 1234Joseph" 

Je reçois la sortie:

"Joseph1234" 

Parce que le texte « Nom d'utilisateur » est mis au rebut par la analyseur dans la partie (A) :: = règle d'erreur (B), mais je veux vraiment:

"Username Joseph1234" 

comme sortie.

Si vous ne pouvez résoudre ce problème dans le bison ou un autre générateur d'analyseur j'accepter que comme une réponse :)

Répondre

2

Avec yacc/bison, une erreur d'analyse fait tomber l'outil en mode de récupération d'erreur, si possible. Il tentera de rejeter les jetons sur son chemin vers un état "propre".

Je suis incapable de trouver une référence pour le citron, donc je ne peux pas montrer un code de citron pour résoudre ce problème, mais avec yacc/bison, on utiliserait les règles here.

A savoir, vous devez ajuster votre règle d'erreur pour indiquer que l'analyseur est correct avec yyerrok pour l'empêcher de supprimer des jetons. Ensuite, il tentera de relire le "mauvais" jeton, vous devrez donc l'effacer avec yyclearin. Enfin, puisque la règle attachée à votre code d'erreur contient le contenu de votre jeton, vous devrez configurer une fonction qui ajuste votre pile d'entrée, en prenant le contenu du jeton actuel et en créant un nouveau jeton (correct) avec le même contenu.

À titre d'exemple, si une grammaire définie comme MyOther MyOther a vu MyTok MyOther:

stack 
MyTok: "the text" 
MyOther: "new text" 

stack 
MyOther: "the text" 
MyOther: "new text" 

Pour cela, regarder dans yybackup. Je suis incapable de trouver une méthode alternative, bien que yybackup soit mal vu.

+0

Au cas où quelqu'un serait intéressé, j'ai fini par passer à RE2C [[link] (http://re2c.org/)]. Il était beaucoup plus facile d'obtenir le comportement avec les macros RE2C. J'ai écrit les macros de sorte que toutes les sous-chaînes non appariées soient simplement sorties alors que les sous-chaînes correspondantes sont modifiées par RE2C. –

2

Il est un ancien, mais pourquoi pas ...

La grammaire doit inclure des espaces. Pour le moment, la grammaire n'autorise qu'une séquence de NUMBER NAME (sans espace entre les tokens).

+1

Il existe des badges (Nécromancien et Revival) pour répondre aux anciennes questions et obtenir des votes, il y a donc toutes les raisons de répondre aux questions plus anciennes sans réponse (ou sans bonne réponse). –

+0

L'analyseur lexical traite vraisemblablement des espaces entre les jetons, etc. C'est une division standard du travail - l'analyseur lexical gère les commentaires, les blancs et les cordes; la grammaire traite des jetons trouvés par l'analyseur lexical qui ne sont pas mangés par lui. –

+0

@Jonathan Leffler, je ne pouvais pas faire cette hypothèse basée sur la question.La séquence de jetons NUMBER NAME est supposée capturer 1234Joseph, mais ce n'est généralement pas le cas (1234Joseph ne serait pas un jeton légal). J'espère que vous voyez ce que je veux dire par rapport aux espaces. –

Questions connexes