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

Function pyparsing-解析函数调用以获取函数名和参数列表,function,parsing,arguments,pyparsing,Function,Parsing,Arguments,Pyparsing,我有一些复杂的函数调用,我想解析它们以获得函数名和参数列表。函数调用的示例如下: 1) 扩展(lambda x:'xxxx'如果t='xx'否则t.replace('a','')。replace('b',''),['col\u name1','col\u name','string') 2) 限制(λx:x!=0,['col']) 我曾尝试使用regex解析这个,但到目前为止,它无法正确解析参数列表。我是pyparsing新手,非常感谢您的帮助。这些函数中有一些非常复杂的参数列表。因此,如果您试

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

1) 扩展(lambda x:'xxxx'如果t='xx'否则t.replace('a','')。replace('b',''),['col\u name1','col\u name','string')

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


我曾尝试使用regex解析这个,但到目前为止,它无法正确解析参数列表。我是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)

如果我们将参数看作是嵌套在一个或多个括号级别的项的列表,那么我们可以使用PyPrScript的代码> NestStestPrp< /Case>帮助器来捕获它们。

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 = 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列表中解析出的位,而不是全部一个字符串版本。)

嗨,Paul,感谢您回答这个问题。我对解析器的期望是获得函数名(这相当容易)和参数列表。例如,在第一个函数中:extend(lambda x:xxxx'if t='xx'else t.replace('a','').replace('b',''),['col\u name1'],'col\u name','string')预期结果是[extend,['lambda x:'xxxx'if t='xx'else t.replace('a','').replace('b',''),['col name1'],“,['col name1'],'col name','string']。我希望能澄清。正如我所说的,我把它作为一个练习留给你来完成。哈哈,好的,我不知道你指的是它。感谢你对一个后续问题的及时回答。函数限制(lambda x:x!=0,[col]),如果第一个参数和第二个参数之间没有空格,则解析似乎无法按预期进行。我们如何忽略空格?这是因为
nestedExpr
只不过是嵌套开始和结束字符串的检测器,在本例中,'('和')“。带有paren的内容没有真正解析,只是在空格处分解。要检测参数,您需要使用
originalTextFor
返回原始字符串。此时,您应该能够使用
ast.literal\u eval
,但这似乎只适用于不包含a
lambda
。如果您确信文本源是安全的,您可以
eval()
使用
originalTextFor
发出的字符串。