Bonjour.
Nouveau dans le monde Python (je viens du C), je m'essaye à traduire un fichier .pdn (description d'une partie de dames) avec ply.lex et ply.yacc. Je sais bien que je ne commence pas avec le plus facile. La programmation en générale ne me pose pas de problème mais écrire un descriptif pour lex est une autre paire de manches.
Passons directement à ce qui m'amène. Tout d'abord voici un exemple de fichier pdn que je tente de travailler :
J'ai déclaré les lexèmes suivants :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 [Event "Championnat de France Open de logiciels 2009"] [Site "Arleux, FRA"] [Date "2009.05.17"] [Round "1"] [White "Dam 2.2"] [Black "Tornado"] [Result "1/2-1/2"] 1. 31-27 19-23 2. 33-28 17-21 3. 28x19 14x23 4. 39-33 11-17 5. 37-31 7-11 6. 34-29 23x34 7. 40x29 21-26 8. 32-28 26x37 9. 41x32 10-14 10. 46-41 17-22 11. 28x17 11x31 12. 36x27 6-11 13. 44-39 11-17 14. 50-44 2-7 15. 41-36 17-21 16. 33-28 14-19 17. 39-33 19-23 18. 28x19 13x24 19. 44-39 9-13 20. 42-37 4-9 21. 47-42 5-10 22. 49-44 1-6 23. 44-40 9-14 24. 37-31 7-11 25. 39-34 21-26 26. 32-28 26x37 27. 42x31 11-17 28. 38-32 14-19 29. 43-38 20-25 30. 29x20 25x14 31. 34-29 14-20 32. 27-22 18x27 33. 31x11 6x17 34. 29-24 19x30 35. 35x24 20x29 36. 33x24 10-14 37. 40-34 17-22 38. 28x17 12x21 39. 32-28 8-12 40. 28-23 21-27 41. 48-42 16-21 42. 42-37 21-26 43. 34-29 13-18 44. 45-40 14-20 45. 24-19 3-8 46. 40-35 20-25 47. 37-32 15-20 48. 32x21 26x17 49. 36-31 18-22 50. 29-24 20x18 51. 19-14 17-21 52. 14-10 21-27 53. 31-26 22-28 54. 10-5 18-23 55. 38-33 28x39 56. 5x44 25-30 57. 35x24 27-32 58. 24-20 12-18 59. 44-33 18-22 60. 33x3 32-38 61. 26-21 38-43 62. 21-16 43-49 1/2-1/2
Puis vient la déclaration pour le lexème DESCRIPTION qui fonctionne très bien ici :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 import sys import ply.lex as lex import ply.yacc as yacc # définir les types de lexèmes tokens = ('NUMBER', 'POINT', 'MINUS', 'PRISE', 'DESCRIPTION') t_POINT='.' t_MINUS='-' t_PRISE='x' t_ignore= '/ \t' # pour ignorer les espaces, les slashs et les tabulations
Pour finir le reste des déclarations nécessaires pour la gestion de ply.lex :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 # Declaration de l'état states = (('description', 'exclusive'),) # Recherche du premier "[". def t_description(t): r'\[' t.lexer.code_start = t.lexer.lexpos # Sauvegarde de la position de départ t.lexer.level = 1 # Initialisation du niveau pour ce crochet t.lexer.begin('description') # Initialisation du lexème # Règle pour la description de l'état def t_description_lcrochet(t): r'\[' t.lexer.level +=1 def t_description_rcrochet(t): r'\]' t.lexer.level -=1 # Si c'est un crochet de fermeture, retourne la description if t.lexer.level == 0: t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos-1] t.type = "DESCRIPTION" t.lexer.lineno += t.value.count('\n') t.lexer.begin('INITIAL') return t # Charactères ignorés (slash, espace, tabulation, retour chariot) t_description_ignore = "/ \t\n" # Pour la gestion des erreurs, ne renvoie rien def t_description_error(t): t.lexer.skip(1)
Lorsque j'exécute l'application en l'état, les littéraux "-" et "x" ne sont pas pris en compte. Ils sont remplacés par le lexème POINT. Extrait :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 def t_NUMBER(t): r'\d+' t.value = t.value return t # Garder la trace du numéro de ligne où interviennent nos lexèmes # (pour le diagnostic derreur) def t_newline(t): r'\n+' t.lexer.lineno += len(t.value) # Gérer les erreurs en cas de caractère imprévu def t_error(t): print ("Illegal character % s " % t.value[0]) t.lexer.skip(1) # Construction de l'analyseur lex.lex(debug=False) # teste de l'analyseur # Chargement du fichier source f = open(sys.argv[1], "r") prog = f.read() f.close() #Lancement de l'analyseur lexical sur le fichier source lex.input(prog) while 1: tok = lex.token() if not tok: break print (tok)
Je me suis dit que le "." avait besoin d'un caractère d'échappement. J'ai donc modifié ma déclaration ainsi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 python3 PyGenDb.py save_pdn_game/arleux2009.pdn2 LexToken(DESCRIPTION,'Event "Championnat de France Open de logiciels 2009"',2,54) LexToken(DESCRIPTION,'Site "Arleux, FRA"',3,75) LexToken(DESCRIPTION,'Date "2009.05.17"',4,95) LexToken(DESCRIPTION,'Round "1"',5,107) LexToken(DESCRIPTION,'White "Dam 2.2"',6,125) LexToken(DESCRIPTION,'Black "Tornado"',7,143) LexToken(DESCRIPTION,'Result "1/2-1/2"',8,162) LexToken(NUMBER,'1',10,165) LexToken(POINT,'.',10,166) LexToken(NUMBER,'31',10,168) LexToken(POINT,'-',10,170) LexToken(NUMBER,'27',10,171) LexToken(NUMBER,'19',10,174) LexToken(POINT,'-',10,176) LexToken(NUMBER,'23',10,177) LexToken(NUMBER,'2',10,180) LexToken(POINT,'.',10,181) LexToken(NUMBER,'33',10,183) LexToken(POINT,'-',10,185) LexToken(NUMBER,'28',10,186) LexToken(NUMBER,'17',10,189) LexToken(POINT,'-',10,191) LexToken(NUMBER,'21',10,192) LexToken(NUMBER,'3',10,195) LexToken(POINT,'.',10,196) LexToken(NUMBER,'28',10,198) LexToken(POINT,'x',10,200) ...
ply.lex cette fois-ci m'indique une erreur de déclaration mais le fichier est correctement traduit ! Cependant, lorsque lex.yacc est lancé le lexème POINT n'est pas reconnu.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2t_POINT='.'t_POINT='\.'
Extrait de lex.yacc :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 python3 PyGenDb.py save_pdn_game/arleux2009.pdn2 /home/gerald/Projects/python/PyGenDb/PyGenDb.py:32: SyntaxWarning: invalid escape sequence '\.' t_POINT='\.' LexToken(DESCRIPTION,'Event "Championnat de France Open de logiciels 2009"',2,54) LexToken(DESCRIPTION,'Site "Arleux, FRA"',3,75) LexToken(DESCRIPTION,'Date "2009.05.17"',4,95) LexToken(DESCRIPTION,'Round "1"',5,107) LexToken(DESCRIPTION,'White "Dam 2.2"',6,125) LexToken(DESCRIPTION,'Black "Tornado"',7,143) LexToken(DESCRIPTION,'Result "1/2-1/2"',8,162) LexToken(NUMBER,'1',10,165) LexToken(POINT,'.',10,166) LexToken(NUMBER,'31',10,168) LexToken(MINUS,'-',10,170) LexToken(NUMBER,'27',10,171) LexToken(NUMBER,'19',10,174) LexToken(MINUS,'-',10,176) LexToken(NUMBER,'23',10,177) LexToken(NUMBER,'2',10,180) LexToken(POINT,'.',10,181) LexToken(NUMBER,'33',10,183) LexToken(MINUS,'-',10,185) LexToken(NUMBER,'28',10,186) LexToken(NUMBER,'17',10,189) LexToken(MINUS,'-',10,191) LexToken(NUMBER,'21',10,192) LexToken(NUMBER,'3',10,195) LexToken(POINT,'.',10,196) LexToken(NUMBER,'28',10,198) LexToken(PRISE,'x',10,200) ...
Est-ce qu'une âme charitable saurait m'indiquer l'erreur, sûrement de débutant, que j'ai commise ici ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 DESCRIPTION : Event "Championnat de France Open de logiciels 2009" Syntax error in input! DESCRIPTION : Date "2009.05.17" DESCRIPTION : White "Dam 2.2" DESCRIPTION : Result "1/2-1/2" Déplacement : ('31', '-', '27') Syntax error in input! Déplacement : ('33', '-', '28') ...
Partager