9
votes

Checker syntaxe mathématique écrit en python

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

Pour simplicité, disons que je n'ai pas besoin de + - * / opérateurs ( + - aussi unaire) avec des chiffres et des parenthèses imbriquées. J'ajouterai également des noms de variables simples pour la complétude.

afin que je puisse tester de cette façon: xxx

J'ai essayé PYPARSING mais juste essayer l'exemple: " Un analyseur d'expression algébrique simple, qui effectue +, -, *, / et ^ opérations arithmétiques " je reçois le code non invalide et essayez également de réparer J'obtiens toujours des syntaxes erronées à analyser sans élever des exceptions

essayez simplement : xxx

"O_OO

Des conseils?


0 commentaires

5 Réponses :


3
votes

Ceci est parce que le code pymparsing permet des fonctions. (et par la manière dont vous avez beaucoup plus que ce dont vous avez besoin, c'est-à-dire une pile et évaluez cela.)

pour commencer, vous pouvez supprimer pi et Ident (et éventuellement autre chose qui me manque maintenant) du code pour interdire les personnages.

La raison est différente: les analyseurs pygarines ne vont pas essayer de consommer l'entrée entière par défaut. Vous devez ajouter + stringend () (et importez-le, bien sûr) à la fin de Expr pour l'échouer s'il ne peut pas analyser l'entrée entière. Dans ce cas, pygarsing.parsexception sera soulevé. (Source: http://pyparsing-public.wikispaces.com/faqs )

Si vous souhaitez apprendre un peu d'analyse, ce dont vous avez besoin peut être construite de manière proprablement dans une trentaine de lignes avec une bibliothèque de parsing décente (j'aime LEPL ).


5 commentaires

non true depuis pi ... est pi et non Qitiy et l'identifiant vient uniquement suivi d'une parenthèse ... bien sûr si je pouvais obtenir du pyparsing Pour travailler comme un vérificateur de syntaxe valide, je l'aimerais. Je vais donner une chance leulée aussi.


@neuriono: Ensuite, soit le code source est trompeur et la grammaire est en réalité différente, ou pyparsing est cassée (éditer: une explication que je peux penser, ce qui serait dans la catégorie "PyparSing est cassé": il ne consomme pas le tout String mais plutôt sort et retourne ce qu'il a analysé jusqu'à présent si l'entrée restante ne parvient pas à analyser).


Eh bien, c'est assez évident, mais si vous regardez la partie du code qui construit l'analyseur (def Bnf ()) est assez simple et même enlever des choses comme exponentiation la pièce rendant encore plus simple que cela échoue encore Je suppose que le pyparsing n'est pas bon pour vérifier la syntaxe.


@neuriono: Je suppose que ça avait raison. Ajout de cause et correction de la réponse.


ou ajoutez parseall = true ... Merci d'avoir souligné cela, je verrai si je peux vraiment l'obtenir pour vérifier ma syntaxe et vous donner la meilleure réponse



2
votes

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

> 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


15 commentaires

Cela est bien pire que la première réponse (maintenant supprimée), qui au moins vérifiée si la réponse est composée de numéros et d'opérateurs. Le vôtre permet un code abrégé :(


Literal_eval n'est pas la réponse, comme vous souhaitez autoriser les opérateurs de mathématiques et les parens.


Une mise à jour supplémentaire: j'ai changé la source de littéral_eval afin que cela n'accepte que des opérations binaires et unaires (espérons-le que c'est propre maintenant).


Tant de travail et de code ... jamais pensé à simplement aller à la manière d'un autre type (vérification des chiffres + ops) ou de le faire correctement et de construire un analyseur?


Votre premier échantillon est toujours faux pour mes besoins ... L'expression est une syntaxe valide, si les variables ne sont pas définies, c'est une NameError, pas une SyntaxError ...


Sept lignes et -20 de la source? C'est rien ! Et qui sait, peut-être que ma solution fonctionnera mieux à long terme si vous envisagez d'ajouter une vérification plus complexe de syntaxe mathématique.


Je travaille dessus, Sheesh. Vous agissez comme si je fais un travail faux. Soyez heureux que vous obteniez même de l'aide.


@Blender: Même si les exigences se développent, une solution utilisant une bibliothèque d'analyse sera facilement ajustée. Pas besoin de maintenir la solution.


@Blender: Je suis heureux de l'aide de tout le monde, mais je le donne comme une hypothèse qui donnant une syntaxe à un Evaluator est la mauvaise et éventuellement faible. Merci de vos efforts de toute façon.


Ok, Cette mise à jour devrait fonctionner. Corrigez-moi si je me trompe, mais je pense qu'il est assez sûr d'utiliser un eval () dans ce cas.


Peut-être en sécurité, mais toujours beaucoup trop de code. Même discutable si nous allions évaluer l'expression, mais nous excédez absolument (et aussi toujours sale) si le problème est la vérification de la syntaxe.


Je peux le formater un peu mieux, mais pourquoi est-ce sale? Trouvez-moi un trou et je serai heureux.


Vous savez essayer EVAL ("1000 1000 1000") suspendra votre python longtemps? J'espère que ce code ne fonctionne pas sur un serveur Web ...


Je vois ce que tu veux dire ... laissez-moi voir ce que je peux faire.


Je pense que cela serait vulnérable aux conditions de course si multithreaded.



1
votes

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

Le concept de base consiste à faire fonctionner quelques fonctions d'assistance pour créer votre analyseur.

def extrait () obtiendra le caractère suivant de l'expression de
DEF PEEK () Semblable à l'extrait mais utilisé s'il n'y a pas de blancheur pour vérifier le caractère suivant de
get_expression ()
get_next_Token ()

Alternativement si vous pouvez garantir des espaces blancheurs entre les caractères, vous pouvez utiliser divisé () pour faire tout la jeton.

Ensuite, vous construisez votre arbre et évaluez si sa structure correctement

Essayez ceci pour plus d'informations: http://effbot.org/zone/ Simple-Top-Down-Parsing.htm


7 commentaires

Construire tout cela vous-même est si le siècle dernier ... De nos jours, vous utilisez une bibliothèque d'analyse qui prend soin de toute la bureaucratie méchante.


@delnan j'ai ajouté le fait que s'il y a une espace blanche, vous pouvez simplement utiliser Split (), également s'il n'y a pas de cette bibliothèque de ce type qui répond à vos besoins (fonctionnel mais pas trop grand, etc.), qu'est-ce que?


@YOEL: Ensuite, vous n'avez pas de chance et avez-vous des normes trop élevées.


@delnan, je ne comprends pas que quelqu'un devait écrire la bibliothèque LEPL que vous avez dit avoir aimé utiliser. Je suppose que cela m'appelle à l'ancienne pour vouloir faire des choses qui sont "sooo du siècle dernier";)


@Yoel: Je suppose que vous avez déjà analysé quelque chose de non-trivial (CSV est à la limite entre trivial et simple) à la main? Je cautions une fois, mais à mi-chemin, je me suis rendu compte que j'écris des fonctions d'assistant, des services publics, etc. que l'analyse des bibliothèques fournissait déjà (sans oublier que mon code était toujours buggy pendant que le leur travaille parfaitement).


@Delnan: +1 pour ne pas laisser cette chaîne de commentaires devenir agressifs. Je comprends où votre venant de et oui en utilisant des bibliothèques jugées et vraies est très utile. Je viens de ressentir pour cette application spécifique que @Neurino avait besoin, il pourrait être logique de faire la route personnalisée. Je suppose que je sautais à des conclusions sur les contraintes existantes sur l'espace et les dépendances


@Yoel: Eh bien, puisque OP a présenté une solution pymparsing, il souhaitait travailler, les dépendances semblent bien. Mais ne jamais relâcher.



1
votes

Ajout parseall = true à l'appel à parsestring convertira cet analgésique en validateur.


1 commentaires

Eh bien, un peu tard ... (voir mon dernier commentaire à la réponse sélectionnée), merci quand même.



0
votes

Si vous souhaitez modifier un moteur d'évaluateur de mathématiques personnalisé écrit dans Python de sorte qu'il s'agisse d'un validateur, vous pouvez commencer avec Evaluator 2.0 (Python 3.x) et math_evaluator (python 2. X). Ce ne sont pas des solutions prêtes à l'emploi mais vous permettraient de personnaliser pleinement tout ce que vous essayez de faire exactement utiliser (espérons-le) le code Python facile à lire. Notez que "et" & "ou" sont traités comme des opérateurs.


0 commentaires