pyparsing以最常见的形式解析python函数调用

Eur*_*ice 3 python pyparsing

我想使用优秀的pyparsing包以最常见的形式解析python函数调用.我读了一篇在这里有点用处但仍然不够通用的帖子.

我想解析以下表达式:

f(arg1,arg2,arg3,...,kw1=var1,kw2=var2,kw3=var3,...)
Run Code Online (Sandbox Code Playgroud)

哪里

  1. arg1,arg2,arg3 ...是任何类型的有效python对象(整数,实数,列表,字典,函数,变量名......)
  2. kw1,kw2,kw3 ...是有效的python关键字名称
  3. var1,var2,var3是有效的python对象

我想知道是否可以为这样的通用模板定义语法.我或许要求太多了......你有什么想法吗?

非常感谢您的帮助

埃里克

Pau*_*McG 5

这就是全部?让我们从一个简单的非正式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'
Run Code Online (Sandbox Code Playgroud)

翻译为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()

arg_expr = identifier | real | integer | 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)) + ')'
Run Code Online (Sandbox Code Playgroud)

这些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)
Run Code Online (Sandbox Code Playgroud)

您仍然可以使用*list_of_args**dict_of_named_args表示法传递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
Run Code Online (Sandbox Code Playgroud)

现在给自己写一些测试用例 - 从简单开始,逐步复杂化:

sin(30)
sin(a)
hypot(a,b)
len([1,2,3])
max(*list_of_vals)
Run Code Online (Sandbox Code Playgroud)

需要添加的其他参数类型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表达式: lambda x : sin(x+math.pi/2)

  • 列表理解

  • 发电机表达