4

優れた pyparsing パッケージを使用して、Python 関数呼び出しを最も一般的な形式で解析したいと考えています。ここで多少役立つが、まだ十分に一般的ではない 1 つの投稿を読みました。

次の式を解析したいと思います。

f(arg1,arg2,arg3,...,kw1=var1,kw2=var2,kw3=var3,...)

どこ

  1. arg1,arg2,arg3 ... 任意の種類の有効な Python オブジェクト (整数、実数、リスト、dict、関数、変数名 ...)
  2. kw1、kw2、kw3 ... は有効な python キーワード名です
  3. var1、var2、var3 は有効な Python オブジェクトです

このような一般的なテンプレートに文法を定義できないかと思っていました。私はおそらくあまりにも多くを求めています...あなたは何か分かりますか?

ご助力ありがとうございます

エリック

4

1 に答える 1

8

それだけですか?このための単純な非公式 BNF から始めましょう。

func_call ::= identifier '(' func_arg [',' func_arg]... ')'
func_arg ::= named_arg | arg_expr
named_arg ::= identifier '=' arg_expr
arg_expr ::= identifier | real | integer | dict_literal | list_literal | tuple_literal | func_call
identifier ::= (alpha|'_') (alpha|num|'_')*
alpha ::= some letter 'a'..'z' 'A'..'Z'
num ::= some digit '0'..'9'

pyparsing に変換し、ボトムアップで作業します。

identifier = Word(alphas+'_', alphanums+'_')

# definitions of real, integer, dict_literal, list_literal, tuple_literal go here
# see further text below

# define a placeholder for func_call - we don't have it yet, but we need it now
func_call = Forward()

string = pp.quotedString | pp.unicodeString

arg_expr = identifier | real | integer | string | dict_literal | list_literal | tuple_literal | func_call

named_arg = identifier + '=' + arg_expr

# to define func_arg, must first see if it is a named_arg
# why do you think this is?
func_arg = named_arg | arg_expr

# now define func_call using '<<' instead of '=', to "inject" the definition 
# into the previously declared Forward
#
# Group each arg to keep its set of tokens separate, otherwise you just get one
# continuous list of parsed strings, which is almost as worthless the original
# string
func_call << identifier + '(' + delimitedList(Group(func_arg)) + ')'

これらarg_exprの要素は処理に時間がかかる可能性がありますが、幸いなことに、pyparsing wiki のサンプル ページから取得できます: http://pyparsing.wikispaces.com/file/view/parsePythonValue.py

from parsePythonValue import (integer, real, dictStr as dict_literal, 
                              listStr as list_literal, tupleStr as tuple_literal)

*list_of_argsまたは**dict_of_named_args表記を使用して引数が渡される場合があります。arg_exprこれらをサポートするために展開します。

deref_list = '*' + (identifier | list_literal | tuple_literal)
deref_dict = '**' + (identifier | dict_literal)

arg_expr = identifier | real | integer | dict_literal | list_literal | tuple_literal | func_call | deref_list | deref_dict

今すぐ自分でいくつかのテスト ケースを作成してください。

sin(30)
sin(a)
hypot(a,b)
len([1,2,3])
max(*list_of_vals)

追加する必要がある追加の引数タイプarg_expr(OP のさらなる演習として残します):

  • インデックス付き引数:dictval['a'] divmod(10,3)[0] range(10)[::2]

  • オブジェクト属性参照:a.b.c

  • 算術式 : sin(30),sin(a+2*b)

  • 比較式 :sin(a+2*b) > 0.5 10 < a < 20

  • ブール式 :a or b and not (d or c and b)

  • ラムダ式:lambda x : sin(x+math.pi/2)

  • リスト内包表記

  • ジェネレータ式

于 2013-01-24T09:50:24.380 に答える