pyparsing - 解析函数调用以获取函数名称和参数列表

时间:2018-06-07 04:58:25

标签: function parsing arguments pyparsing

我有一些复杂的函数调用,我想解析它来获取函数名和参数列表。函数调用的示例如下:

1)扩展(lambda x:'xxxx',如果t ='xx',则t.replace('a','')。replace('b',''),['col_name1'],'col_name ','string')

2)限制(lambda x:x!= 0,['col'])

我试图使用正则表达式解析它,但到目前为止它无法正确解析参数列表。我是pyparsing的新手,所以感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

这些函数中有一些非常复杂的参数列表。因此,如果您尝试解析他们,这将是一项非常重要的工作。

但是,如果您只想要函数名称和传入的参数字符串,那么使用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'

如果你想删除开始和结束(),并解析分界逗号,这是读者/ OP留下的练习。 (如果是这种情况,您可能需要返回到第一个版本,并使用arg列表的已解析位而不是全一字符串版本。)

相关问题