Question

Je veux tokeniser une expression mathématique donnée dans un arbre d'analyse comme ceci:

((3 + 4 - 1) * 5 + 6 * -7) / 2

                          '/'
                        /     \
                       +        2
                    /     \
                  *         *
                /   \     /   \
               -     5   6     -7
             /   \
            +     1
          /   \
         3     4

Y a-t-il une pure façon de faire de Python de le faire? Comme passer comme une chaîne à Python, puis récupérer comme un arbre comme mentionné ci-dessus.

Merci.

Était-ce utile?

La solution

Oui, le Python ast Le module fournit des installations pour ce faire. Vous devrez rechercher l'interface exacte de votre version de Python, puisque la ast Le module semble changer régulièrement.

En particulier, le ast.parse() La méthode sera utile pour votre application:

>>> import ast
>>> ast.parse("(1+2)*3", "", "eval")
<_ast.Expression object at 0x88950>
>>> ast.dump(_)
'Expression(body=BinOp(left=BinOp(left=Num(n=1), op=Add(), right=Num(n=2)), op=Mult(), right=Num(n=3)))'

Autres conseils

Plusieurs cadres d'analyseurs existent pour Python; Certains communs sont PLI et pypars. Ned Batchelder a un Liste assez complète.

Il existe de nombreux bons algorithmes établis pour analyser les expressions mathématiques comme celle-ci. Un particulièrement bon est Dijkstra algorithme de charité, qui peut être utilisé pour produire un tel arbre. Je ne connais pas une implémentation particulière dans Python, mais l'algorithme n'est pas particulièrement complexe et il ne devrait pas prendre trop de temps pour en faire un.

Soit dit en passant, le terme le plus précis pour l'arbre que vous construisez est un analyse d'analyse ou Syntaxe abstrait.

Vous pouvez le faire avec le module Python AST.

https://docs.python.org/3.6/library/ast.html

La théorie est notre opération mathématique que nous voulons évaluer, nous utilisons l'isinstance afin de connaître le type qu'il est, si c'est un nombre, si c'est un opérateur binaire (+, *, ..). Vous pouvez lire à https://greentreesnakes.readthedocs.io/en/latest/tofrom.html , comment fonctionne l'AST

Et afin de faire fonctionner la méthode que nous devrions utiliser: évaluer (ast.parse (theoperation, mode = 'eval'). Corps)

def evaluate(theoperation): 
    if (isinstance(theoperation, ast.Num)):
        return theoperation.n
    if (isinstance(theoperation, ast.BinOp)):
        leftope= evaluate(theoperation.left)
        rightope=evaluate(theoperation.right)   
        if (isinstance(theoperation.op, ast.Add)):
            return left+right
        elif (isinstance(theoperation.op, ast.Sub)):
            return left-right
        elif (isinstance(theoperation.op, ast.Mult)):
            return left*right
        elif (isinstance(theoperation.op, ast.Div)):
            return left/right
        elif (isinstance(theoperation.op, ast.Pow)):
            return left**right

Je ne connais pas une façon "pure python" de le faire, qui est déjà implémentée pour vous. Cependant, vous devriez consulter antlr (http://www.antlr.org/), c'est un analyseur open source un lexer et il a une API pour un certain nombre de langues, y compris Python. De plus, ce site Web propose d'excellents didacticiels vidéo qui vous montreront comment faire exactement ce que vous demandez. C'est un outil très utile pour savoir comment utiliser en général.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top