Question

Tout ce dont j'ai besoin est de vérifier, en utilisant python, si une chaîne est une expression mathématique valide ou non.

Pour simplifier, disons que j'ai juste besoin d'opérateurs + - * / (+ - aussi unaire) avec des nombres et des parenthèses imbriquées.J'ajoute également des noms de variables simples par souci d'exhaustivité.

Je peux donc tester de cette façon:

test("-3 * (2 + 1)") #valid
test("-3 * ")        #NOT valid

test("v1 + v2")      #valid
test("v2 - 2v")      #NOT valid ("2v" not a valid variable name)

J'ai essayé pyparsing , mais j'ai simplement essayé l'exemple: " analyseur d'expressions algébriques simple, qui effectue des opérations arithmétiques +,-,*,/ et ^ " Je reçois un code invalide et j'essaye également de le réparer Je me trompe toujourssyntaxes analysées sans lever d'exceptions

essayez simplement :

>>>test('9', 9)
9 qwerty = 9.0 ['9'] => ['9']
>>>test('9 qwerty', 9)
9 qwerty = 9.0 ['9'] => ['9']

les deux tests réussissent ... o_O

Un conseil?

Était-ce utile?

La solution

C'est parce que le code de pyparsing autorise les fonctions. (Et au fait, il fait beaucoup plus que ce dont vous avez besoin, c'est-à-dire créer une pile et l'évaluer.)

Pour commencer, vous pouvez supprimer pi et ident (et peut-être quelque chose d'autre qui me manque actuellement) du code pour interdire les caractères.

La raison est différente: les analyseurs PyParsing n'essaieront pas de consommer toute l'entrée par défaut.Vous devez ajouter + StringEnd() (et l'importer, bien sûr) à la fin de expr pour le faire échouer s'il ne peut pas analyser toute l'entrée.Dans ce cas, pyparsing.ParseException sera déclenché.(Source: http://pyparsing-public.wikispaces.com/FAQs )

Si vous voulez apprendre un peu d’analyse, ce dont vous avez besoin peut probablement être construit en moins de trente lignes avec n’importe quelle bibliothèque d’analyse décente (j'aime LEPL ).

Autres conseils

Vous pouvez essayer de construire vous-même un analyseur simple pour tokeniser la chaîne de l'expression arithmétique, puis construire un arbre d'expression, si l'arbre est valide (les feuilles sont toutes des opérandes et les nœuds internes sont tous des opérateurs) alors vous pouvez dire quel'expression est valide.

Le concept de base est de créer quelques fonctions d'aide pour créer votre analyseur.

def extract() obtiendra le caractère suivant de l'expression
def peek() similaire à extract mais utilisé s'il n'y a pas d'espace pour vérifier le caractère suivant
get_expression()
get_next_token()

Alternativement, si vous pouvez garantir des espaces entre les caractères, vous pouvez utiliser split() pour faire tout le tokenizing.

Ensuite, vous construisez votre arbre et évaluez s'il est correctement structuré

Essayez ceci pour plus d'informations: http://effbot.org/zone/simple-top-down-parsing.htm

Pourquoi ne pas simplement l'évaluer et détecter l'erreur de syntaxe?

from math import *

def validateSyntax(expression):
  functions = {'__builtins__': None}
  variables = {'__builtins__': None}

  functions = {'acos': acos,
               'asin': asin,
               'atan': atan,
               'atan2': atan2,
               'ceil': ceil,
               'cos': cos,
               'cosh': cosh,
               'degrees': degrees,
               'exp': exp,
               'fabs':fabs,
               'floor': floor,
               'fmod': fmod,
               'frexp': frexp,
               'hypot': hypot,
               'ldexp': ldexp,
               'log': log,
               'log10': log10,
               'modf': modf,
               'pow': pow,
               'radians': radians,
               'sin': sin,
               'sinh': sinh,
               'sqrt': sqrt,
               'tan': tan,
               'tanh': tanh}

  variables = {'e': e, 'pi': pi}

  try:
    eval(expression, variables, functions)
  except (SyntaxError, NameError, ZeroDivisionError):
    return False
  else:
    return True

Voici quelques exemples:

> print validSyntax('a+b-1') # a, b are undefined, so a NameError arises.
> False

> print validSyntax('1 + 2')
> True

> print validSyntax('1 - 2')
> True

> print validSyntax('1 / 2')
> True

> print validSyntax('1 * 2')
> True

> print validSyntax('1 +/ 2')
> False

> print validSyntax('1 + (2')
> False

> print validSyntax('import os')
> False

> print validSyntax('print "asd"')
> False

> print validSyntax('import os; os.delete("~\test.txt")')
> False # And the file was not removed

Il est limité aux seules opérations mathématiques, donc il devrait fonctionner un peu mieux qu'un générique générique.

L'ajout de parseAll=True à l'appel à parseString convertira cet analyseur en un validateur.

Si vous souhaitez modifier un moteur d'évaluateur mathématique personnalisé écrit en Python pour qu'il devienne un validateur à la place, vous pouvez commencer par Evaluator 2.0 (Python 3.x) et Math_Evaluator (Python 2.X).Ce ne sont pas des solutions toutes faites mais vous permettraient de personnaliser entièrement tout ce que vous essayez de faire exactement en utilisant (espérons-le) du code Python facile à lire.Notez que "et" & "ou" sont traités comme des opérateurs.

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