pyparsing - 解析函数调用以获取函数名称和参数列表
pyparsing - Parsing a function call to get function name and argument list
我有一些复杂的函数调用,我想对其进行解析以获取函数名称和参数列表。函数调用示例如下:
1) extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b', ''), ['col_name1'], 'col_name', 'string')
2) 限制(lambda x:x !=0, ['col'])
我曾尝试使用正则表达式对其进行解析,但到目前为止它未能正确解析参数列表。我是 pyparsing 的新手,所以感谢您的帮助。
这些函数中有一些非常复杂的参数列表。因此,如果您尝试解析 它们,这将是一项艰巨的工作。
但是,如果您只需要函数名称和传入的参数字符串,那么使用 pyparsing,您可以使用一些简单的快捷方式。
如果你的计划非常高级,你可以将 BNF 写成:
function_call ::= identifier '(' arguments ')'
idenntifier ::= word starting with alpha or '_', followed by zero or more alphanums or '_'
arguments ::= (let's not worry about this for the moment)
如果我们只是将参数视为可以嵌套在一层或多层括号中的项目列表,那么我们可以使用 pyparsing 的 nestedExpr
帮助程序来捕获它们。
import pyparsing as pp
identifier = pp.Word('_' + pp.alphas, '_' + pp.alphanums)
arg_list = pp.nestedExpr() # nesting delimiters default to '(' and ')'
function_call = identifier("name") + arg_list("args")
tests = """\
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
restrict(lambda x:x !=0, ['col'])"""
function_call.runTests(tests)
打印:
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
['extend', ['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]]
- args: [['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]]
[0]:
['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]
[0]:
lambda
[1]:
x:
[2]:
'xxxx'
... every word in the args broken out separately
[16]:
,
[17]:
'string'
- name: 'extend'
restrict(lambda x:x !=0, ['col'])
['restrict', ['lambda', 'x:x', '!=0,', '[', "'col'", ']']]
- args: [['lambda', 'x:x', '!=0,', '[', "'col'", ']']]
[0]:
['lambda', 'x:x', '!=0,', '[', "'col'", ']']
- name: 'restrict'
如果你只想将 args 列表作为一个字符串,那么你可以用 pyparsing 的 originalTextFor
包装起来。将 arg_list
更改为:
arg_list = pp.originalTextFor(pp.nestedExpr())
现在重新运行测试得到:
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
['extend', "(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')"]
- args: "(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')"
- name: 'extend'
restrict(lambda x:x !=0, ['col'])
['restrict', "(lambda x:x !=0, ['col'])"]
- args: "(lambda x:x !=0, ['col'])"
- name: 'restrict'
如果您想删除开头和结尾 (),并解析分隔逗号,那是留给 reader/OP 的练习。 (如果是这种情况,您可能想回到第一个版本,并使用 arg 列表的解析位而不是全单字符串版本。)
我有一些复杂的函数调用,我想对其进行解析以获取函数名称和参数列表。函数调用示例如下:
1) extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b', ''), ['col_name1'], 'col_name', 'string')
2) 限制(lambda x:x !=0, ['col'])
我曾尝试使用正则表达式对其进行解析,但到目前为止它未能正确解析参数列表。我是 pyparsing 的新手,所以感谢您的帮助。
这些函数中有一些非常复杂的参数列表。因此,如果您尝试解析 它们,这将是一项艰巨的工作。
但是,如果您只需要函数名称和传入的参数字符串,那么使用 pyparsing,您可以使用一些简单的快捷方式。
如果你的计划非常高级,你可以将 BNF 写成:
function_call ::= identifier '(' arguments ')'
idenntifier ::= word starting with alpha or '_', followed by zero or more alphanums or '_'
arguments ::= (let's not worry about this for the moment)
如果我们只是将参数视为可以嵌套在一层或多层括号中的项目列表,那么我们可以使用 pyparsing 的 nestedExpr
帮助程序来捕获它们。
import pyparsing as pp
identifier = pp.Word('_' + pp.alphas, '_' + pp.alphanums)
arg_list = pp.nestedExpr() # nesting delimiters default to '(' and ')'
function_call = identifier("name") + arg_list("args")
tests = """\
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
restrict(lambda x:x !=0, ['col'])"""
function_call.runTests(tests)
打印:
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
['extend', ['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]]
- args: [['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]]
[0]:
['lambda', 'x:', "'xxxx'", 'if', 't=', "'xx'", 'else', 't.replace', ["'a'", ',', "''"], '.replace', ["'b'", ',', "''"], ',', '[', "'col_name1'", '],', "'col_name'", ',', "'string'"]
[0]:
lambda
[1]:
x:
[2]:
'xxxx'
... every word in the args broken out separately
[16]:
,
[17]:
'string'
- name: 'extend'
restrict(lambda x:x !=0, ['col'])
['restrict', ['lambda', 'x:x', '!=0,', '[', "'col'", ']']]
- args: [['lambda', 'x:x', '!=0,', '[', "'col'", ']']]
[0]:
['lambda', 'x:x', '!=0,', '[', "'col'", ']']
- name: 'restrict'
如果你只想将 args 列表作为一个字符串,那么你可以用 pyparsing 的 originalTextFor
包装起来。将 arg_list
更改为:
arg_list = pp.originalTextFor(pp.nestedExpr())
现在重新运行测试得到:
extend(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')
['extend', "(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')"]
- args: "(lambda x: 'xxxx' if t='xx' else t.replace('a','').replace('b',''), ['col_name1'], 'col_name', 'string')"
- name: 'extend'
restrict(lambda x:x !=0, ['col'])
['restrict', "(lambda x:x !=0, ['col'])"]
- args: "(lambda x:x !=0, ['col'])"
- name: 'restrict'
如果您想删除开头和结尾 (),并解析分隔逗号,那是留给 reader/OP 的练习。 (如果是这种情况,您可能想回到第一个版本,并使用 arg 列表的解析位而不是全单字符串版本。)