Pythonで書かれた数学構文チェッカー
-
28-10-2019 - |
質問
文字列が有効な数学式であるかどうかを確認する必要があるのは、Pythonを使用することだけです。
簡単にするために、私がただ必要だとしましょう + - * /
オペレーター(+ -
数字とネストされた括弧付きの単位も)。完全性のためにシンプルな変数名も追加します。
だから私はこの方法でテストすることができます:
test("-3 * (2 + 1)") #valid
test("-3 * ") #NOT valid
test("v1 + v2") #valid
test("v2 - 2v") #NOT valid ("2v" not a valid variable name)
私は試した パイピング しかし、例を試してみるだけです: 「パフォーマンスを発揮する単純な代数表現パーサー +,-,*,/
と ^
算術操作」 私は無効なコードに合格し、それを修正しようとしています私は常に例外を提起することなく解析される構文を常に間違えます
ちょうど試して:
>>>test('9', 9)
9 qwerty = 9.0 ['9'] => ['9']
>>>test('9 qwerty', 9)
9 qwerty = 9.0 ['9'] => ['9']
両方のテストパス... O_O
何かアドバイス?
解決
これは、パピングコードが機能を許可するためです。 (そして、ちなみに、それはあなたが必要とするものよりもはるかに多くのことをします。つまり、スタックを作成してそれを評価します。)
手始めに、削除できます pi
と ident
文字を禁止するためにコードから(そして今私が今見ている何か他の何か)。
その理由は異なります:PyParsingパーサーは、デフォルトで入力全体を消費しようとはしません。追加する必要があります + StringEnd()
(そしてもちろんそれをインポートします)の終わりまで expr
入力全体を解析できない場合に失敗させる。その場合、 pyparsing.ParseException
上げられます。 (ソース: http://pyparsing-public.wikispaces.com/faqs)
少しの解析を学びたい場合、必要なものは、まともな解析ライブラリを使用して30回未満のライン未満でおそらく構築できます(私は好きです Lepl).
他のヒント
シンプルなパーサーを構築して、算術式の文字列をトークン化してから式ツリーを構築してみてください。ツリーが有効な場合(葉はすべてオペランドであり、内部ノードはすべて演算子です)、式は式があると言うことができます。有効。
基本的な概念は、いくつかのヘルパー機能を作成してパーサーを作成することです。
def extract()
式から次のキャラクターを取得します
def peek()
抽出に似ていますが、次の文字を確認するために空白がない場合に使用されます
get_expression()
get_next_token()
または、文字間でホワイトスペースを保証できる場合は、使用できます split()
すべてのトークン化を行う。
次に、ツリーを構築し、その構造が正しく構成されているかどうかを評価します
詳細については、これをお試しください: http://effbot.org/zone/simple-top-down-parsing.htm
それを評価して構文エラーをキャッチしてみませんか?
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
ここにいくつかのサンプルがあります:
> 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
数学的な操作のみに制限されているので、 したほうがいい 粗野よりも少しうまく機能します eval
.
追加 parseAll=True
電話に parseString
このパーサーをバリデーターに変換します。
Pythonで書かれたカスタム数学評価エンジンを変更して、代わりにバリデーターになるように興味がある場合は、から始めることができます 評価者2.0 (Python 3.x)および Math_Evaluator (Python 2.x)。それらは既製のソリューションではありませんが、(できれば)Pythonコードを正確に使用しようとしていることを完全にカスタマイズすることができます。 「&」または「または」はオペレーターとして扱われることに注意してください。