2008-09-20 13 views
3

J'écris un analyseur C en utilisant PLY, et j'ai récemment rencontré un problème. Ce code:PLY: problème de décalage de jeton dans l'analyseur C

typedef int my_type; 
my_type x; 

est bon code C, parce que my_type est défini comme un type précédemment utilisé en tant que tel. Je le manipule en remplissant une table de symboles de type dans l'analyseur qui est utilisé par le lexeur pour différencier les types et identifiants simples. Cependant, alors que la règle de déclaration de type se termine par SEMI (le jeton ';'), PLY décale le jeton my_type de la deuxième ligne avant de décider que c'est fait avec le premier. Pour cette raison, je n'ai aucune chance de passer la mise à jour dans la table des symboles de type à la lexer et voit my_type comme un identifiant et non un type.

Des idées pour une solution?

Le code complet est à: http://code.google.com/p/pycparser/source/browse/trunk/src/c_parser.py Vous ne savez pas comment créer un exemple plus petit à partir de cela.

Edit:

Problème résolu. Voir ma solution ci-dessous.

Répondre

2

Avec some help de Dave Beazley (créateur de PLY), mon problème a été résolu.

L'idée est d'utiliser des sous-règles spéciales et d'y effectuer les actions. Dans mon cas, je partage la règle declaration à:

def p_decl_body(self, p): 
    """ decl_body : declaration_specifiers init_declarator_list_opt 
    """ 
    # <<Handle the declaration here>>   

def p_declaration(self, p): 
    """ declaration : decl_body SEMI 
    """ 
    p[0] = p[1] 

decl_body est toujours réduite avant le jeton après SEMI est déplacé, donc mon action est exécuté au bon moment.

1

Je pense que vous devez déplacer la vérification pour savoir si un ID est un TYPEID de c_lexer.py à c_parser.py.

Comme vous l'avez dit, puisque l'analyseur regarde 1 jeton en avant, vous ne pouvez pas prendre cette décision dans la lexeur. Au lieu de cela, modifiez votre analyseur pour vérifier les ID pour voir s'il s'agit de déclarations TYPEID et, si ce n'est pas le cas, générer une erreur. Comme l'a dit Pax Diablo dans son excellente réponse, le travail de lexer/tokenizer n'est pas de prendre ce genre de décisions sur les jetons. C'est le travail de l'analyseur.

3

Vous ne savez pas pourquoi vous faites ce niveau d'analyse dans votre lexer.

L'analyse lexicale devrait probablement être utilisée pour séparer le flux d'entrée en jetons lexicaux (nombre, changement de ligne, mot-clé, etc.). C'est la phase d'analyse qui devrait faire ce niveau d'analyse, y compris les recherches de table pour typedefs et autres.

C'est comme ça que j'ai toujours séparé les tâches entre lexx et yacc, mes outils de prédilection.

+0

Je suis d'accord. Chaque fois que j'ai eu ce type de problèmes, c'est généralement parce que j'essaie d'avoir trop de lexer. Mais j'utilise maintenant ANTLR au lieu de LEX et YACC (** pas ** trop vieux pour changer). –