9

必要なのは、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

何かアドバイス?

4

5 に答える 5

3

これは、pyparsing コードで関数が許可されているためです。(ちなみに、これは必要以上のことを行います。つまり、スタックを作成してそれを評価します。)

手始めに、コードからpiand ident(そしておそらく私が今見逃している何か) を削除して、文字を禁止することができます。

理由は異なります。PyParsing パーサーは、デフォルトでは入力全体を消費しようとしません。入力全体を解析できない場合に失敗させるには、 の最後に追加+ StringEnd()(そしてもちろんインポート) する必要があります。exprその場合はpyparsing.ParseException値上げします。(出典: http://pyparsing-public.wikispaces.com/FAQs )

少し構文解析を学びたい場合、適切な構文解析ライブラリ (私はLEPLが好きです) を使用すると、必要なものを 30 行以内で構築できる可能性があります。

于 2011-02-03T15:09:18.513 に答える
2

なぜそれを評価して構文エラーをキャッチしないのですか?

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です。

于 2011-02-03T15:14:50.037 に答える
1

単純なパーサーを自分で構築して算術式の文字列をトークン化し、式ツリーを構築してみることができます。ツリーが有効な場合 (葉はすべてオペランドで、内部ノードはすべて演算子です)、式は有効。

基本的な概念は、いくつかのヘルパー関数を作成してパーサーを作成することです。

def extract()
def peek()extract に似た式から次の文字を取得しますが、次の文字をチェックする空白がない場合に使用されます
get_expression()
get_next_token()

または、文字間の空白を保証できる場合split()は、すべてのトークン化を行うために使用できます。

次に、ツリーを構築し、正しく構造化されているかどうかを評価します

詳細については、これを試してください: http://effbot.org/zone/simple-top-down-parsing.htm

于 2011-02-03T15:21:58.857 に答える
1

parseAll=Trueへの呼び出しに追加するparseStringと、このパーサーがバリデーターに変換されます。

于 2011-02-03T23:14:08.397 に答える
0

Python で記述されたカスタム数学エバリュエーター エンジンをバリデーターに変更することに興味がある場合は、Evaluator 2.0 (Python 3.x) とMath_Evaluator (Python 2.x) から始めることができます。それらは既製のソリューションではありませんが、(できれば) 読みやすい Python コードを使用して、実行しようとしているものを完全にカスタマイズできます。「and」と「or」は演算子として扱われることに注意してください。

于 2011-02-04T02:31:34.997 に答える