IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

ply.lex Prendre en compte le "." lors de l'analyse lexicale [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 309
    Billets dans le blog
    5
    Par défaut ply.lex Prendre en compte le "." lors de l'analyse lexicale
    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 :
    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
    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
    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
    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
    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)
    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
    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 d’erreur)
    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)
    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
    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)
    ...
    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
    t_POINT='.'
    t_POINT='\.'
    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
    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)
    ...
    Extrait de lex.yacc :
    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')
    ...
    Est-ce qu'une âme charitable saurait m'indiquer l'erreur, sûrement de débutant, que j'ai commise ici ?

  2. #2
    Membre Expert
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 923
    Billets dans le blog
    8
    Par défaut
    Bonjour.
    Ce ne pas vraiment une question sur python, cependant:

    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.
    De ce que je lis, je comprends que est une expression régulière, et puisque l'expression '.' peut être n'importe quel caractère il va matcher avec les autres littéraux.
    Utilise une Raw string:
    Tu peux aussi définir la règle dans une fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def t_POINT(t):
        r'\.'
        return t
    ?

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par gerald3d Voir le message
    Est-ce qu'une âme charitable saurait m'indiquer l'erreur, sûrement de débutant, que j'ai commise ici ?
    Par expérience (et sans voir essayé) j'écrirais r'\.'

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 309
    Billets dans le blog
    5
    Par défaut
    Merci pour vous réponses.

    C’est bien ce que j’ai tenté. Cela fonctionne effectivement mais lex émet un warning en console pour ce caractère d’échappement.
    Pour l’instant je me cantonne à lex. J’arrive à extraire toutes les données sans utiliser yacc.

    [Edit]
    Au temps pour moi . Le diable se cache dans les détails. J'ai répondu un peu vite hier soir alors que je n'étais pas devant le PC. Le t_POINT = r'\.' m'avait échappé . L'interpréteur n'hurle plus dorénavant. Je vais maintenant pouvoir passer à l'étape yacc.

    Je vous remercie pour vos réponses rapides et pertinentes .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. requête sans prendre en compte la casse
    Par clems34 dans le forum PostgreSQL
    Réponses: 13
    Dernier message: 13/04/2009, 16h50
  2. Réponses: 5
    Dernier message: 19/10/2005, 14h56
  3. [XHTML] Ne pas prendre en compte les balises XHTML
    Par simnitch dans le forum Balisage (X)HTML et validation W3C
    Réponses: 8
    Dernier message: 18/08/2005, 15h58
  4. Réponses: 2
    Dernier message: 07/07/2004, 17h44
  5. [plugin][tomcat] Comment prendre en compte les jar ?
    Par djodjo dans le forum Eclipse Java
    Réponses: 6
    Dernier message: 08/04/2004, 19h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo