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 :

analyse syntaxique avec pyparsing : parsing non complet


Sujet :

Python

  1. #1
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut analyse syntaxique avec pyparsing : parsing non complet
    Bonjour,
    j'ai fait un bout de code afin d'analyser une query simple telle que :
    Altitude != 80 or QFU=120

    mon pg est le suivant :
    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
    """
    Describe the parser of a query 
    """
    from pyparsing import Literal, CaselessLiteral, Word, Upcase, delimitedList, Optional, \
        Combine, Group, alphas, nums, alphanums, ParseException, Forward, oneOf, quotedString, \
        ZeroOrMore, restOfLine, Keyword
     
    def test(ch ):
        	print ch,"->"
        	try:
            	tokens = selectStmt.parseString( ch )
            	print "tokens = ",        tokens
        	except ParseException, err:
            	print " "*err.loc + "^\n" + err.msg
            	print err
        	print
     
     
    colname = ['Airport name', 'Altitude', 'Located on point', 'Pilot map', 'Full name', 'Transition altitude', 'QFU'] 
    # define tokens
    selectStmt = Forward()
     
    columnName = oneOf(colname)
    columnValue = Word(nums)
    binop = oneOf("= != < > >= <=")
    and_ = Keyword("and", caseless=True)
    or_ = Keyword("or", caseless=True)
     
    Expression = columnName + binop + columnValue 
    selectStmt << Expression + ZeroOrMore( ( and_ | or_ ) + Expression ) 
     
    test("Altitude != 80 or QFU=120")
    test("Altitude != 80 xor QFU=120")
    Mon parser décode bien ma phrase, par contre il ne détecte pas certaines erreurs telle que l'opérateur xor qui n'est pas déclaré comme token.
    L'output donne le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >linux awalter 31>: python ./parsenedi.py
    Altitude != 80 or QFU=120 ->
    tokens =  ['Altitude', '!=', '80', 'or', 'QFU', '=', '120']
     
    Altitude != 80 xor QFU=120 ->
    tokens =  ['Altitude', '!=', '80']
     
    >linux awalter 32>:
    Le parser s'arrête en rencontrant l'erreur : xor. Est ce normal ?
    Merci

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Le parser s'arrête en rencontrant l'erreur : xor. Est ce normal?
    Hélas oui ;-)
    La sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Altitude != 80 xor QFU=120 ->
    tokens =  ['Altitude', '!=', '80']
    indique que le début de la chaîne est "correct" jusqu'au "xor".

    A vous de vous débrouillez pour gérer la fin à cause du "ZeroOrMore".
    Ajoutez "+ StringEnd()" pour indiquer que toute la chaîne doit être "conforme".

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

  3. #3
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    Merci beaucoup, c'est exactement StringEnd() qu'il fallait.

    Sans vouloir abuser, j'ai une question supplémentaire : le parser renvoie les valeurs des tokens détectés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tokens =  ['Altitude', '!=', '80', 'or', 'QFU', '=', '120']
    Comment peut t'on savoir à quels tokens ces valeurs se rapportent t'elles ? Je souhaiterais récupérer une liste telle que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [columnName,binop,columnValue,or_,columnName,binop,columnValue]
    J'ai essayé d'utiliser la méthode .setResultsName() : voir ligne 31
    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
    35
    """
    Describe the parser of a query 
    """
    from pyparsing import Literal, CaselessLiteral, Word, Upcase, delimitedList, Optional, \
        Combine, Group, alphas, nums, alphanums, ParseException, Forward, oneOf, quotedString, \
        ZeroOrMore, restOfLine, Keyword, StringEnd
     
    def test(ch ):
            print ch,"->"
            try:
                    tokens = selectStmt.parseString( ch )
                    print "tokens = ",        tokens
                    print "tokens.columnName=",tokens.columnName
                    print "tokens.columnValue=",tokens.columnValue
            except ParseException, err:
                    print " "*err.loc + "^\n" + err.msg
                    print err
            print
     
     
    colname = ['Airport name', 'Altitude', 'Located on point', 'Pilot map', 'Full name', 'Transition altitude', 'QFU'] 
    # define tokens
    selectStmt = Forward()
     
    columnName = oneOf(colname).setName("columnName")
    columnValue = Word(nums)
    binop = oneOf("= != < > >= <=")
    and_ = Keyword("and", caseless=True)
    or_ = Keyword("or", caseless=True)
     
    Expression = columnName.setResultsName( "columnName" ) + binop + columnValue.setResultsName( "columnValue" ) 
    selectStmt << Expression + ZeroOrMore( ( and_ | or_ ) + Expression ) + StringEnd()
     
    test("Altitude != 80 or QFU=120")
    test("Altitude != 80 xor QFU=120")
    Mais je n'obtient que les token de la dernière expression parsée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >linux awalter 93>: python parsenedi.py
    Altitude != 80 or QFU=120 ->
    tokens =  ['Altitude', '!=', '80', 'or', 'QFU', '=', '120']
    tokens.columnName= QFU
    tokens.columnValue= 120
    Cela vous parle t'il ?
    Merci beaucoup

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    C'est d'abord un analyseur lexical.
    Cela analyse (parse) la chaîne de caractères en entrée pour valider qu'elle est "conforme" à la grammaire définie.
    Pendant l'opération, il va falloir construire l'Absract Syntax Tree (AST) qui va représenter l'entrée (ou ce que vous voulez en extraire).
    Et pour çà associer les "actions" adhoc au "parseur".

    Lorsque vous écrivez:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    selectStmt << Expression + ZeroOrMore( ( and_ | or_ ) + Expression ) + StringEnd()
    vous pourrez avoir plusieurs "matchs" d'Expressions.
    Récupérer columnName et columnValue devra être une action associée à l'allumage d'Expression lorsqu'elle a été rencontrée dans l'entrée.

    Ce qui (dans ce cas) se fait avec .ParseAction genre ajout après la définition d'Expression de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def show(s):
        print (s)
    Expression.setParseAction(
        lambda src, line, tokens:
               show('key: %s, value: %s' % (tokens.columnName, tokens.columnValue))
        )
    - W
    PS: Les "parseurs" sont des outils sophistiqués. Pour comprendre comment çà fonctionne, quelques connaissances sur les techniques des compilateurs et en théorie des langages sont nécessaires.
    Les documentations des logiciels de ces domaines paraissent "succinctes" aux non-initiés car les pré-requis doivent avoir été acquis "ailleurs".
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti Avatar de awalter1
    Inscrit en
    Août 2004
    Messages
    994
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 994
    Points : 407
    Points
    407
    Par défaut
    oui vous avez raison. A l'université, j'ai fait une uv sur les langages naturels, les compilateurs ... je suis sensé maitriser ces concepts, mais ça remonte à 30 ans. Je dois revenir aux bases.
    J'ai une version du livre d'O'reilly sur pyparsing, je vais l'étudier en détails.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    A l'université, j'ai fait une uv sur les langages naturels, les compilateurs ... je suis sensé maitriser ces concepts, mais ça remonte à 30 ans. Je dois revenir aux bases.
    Aho et Ullman ont commis leur premier "Principles of Compiler Design" en 1977.
    Le bouquin a été ré-actualisé et ré-édité plusieurs fois.

    Citation Envoyé par awalter1 Voir le message
    J'ai une version du livre d'O'reilly sur pyparsing, je vais l'étudier en détails.
    Ce bouquin documente les exemples donnés sur le site et ce qui est dans les sources. Il aborde assez peu les bases.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

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

Discussions similaires

  1. Erreur d'analyse syntaxique avec moc (std)
    Par Abstrus dans le forum Débuter
    Réponses: 4
    Dernier message: 25/04/2012, 17h15
  2. Algorithme génétique et probleme de voyageur de commerce avec graphe non complet
    Par marmarnassouf dans le forum Intelligence artificielle
    Réponses: 2
    Dernier message: 30/04/2009, 16h51
  3. analyse lexicale et syntaxique avec java
    Par hasnaouiwafa dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 08/03/2007, 14h16
  4. Réponses: 3
    Dernier message: 05/09/2006, 00h47
  5. Une fonction avec des attributs non obligatoires
    Par YanK dans le forum Langage
    Réponses: 5
    Dernier message: 15/11/2002, 13h39

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