pyparsing - парсинг вызова функции для получения имени функции и списка аргументов - PullRequest
0 голосов
/ 07 июня 2018

У меня есть несколько сложных вызовов функций, которые я хочу проанализировать, чтобы получить имя функции и список аргументов.Ниже приведены примеры вызовов функций:

1) extends (лямбда-x: 'xxxx', если t = 'xx', иначе t.replace ('a', ''). replace ('b', ''), [' col_name1 '],' col_name ',' string ')

2) restrict (лямбда-x: x! = 0, [' col '])

Я пыталсячтобы проанализировать это с помощью регулярного выражения, но пока он не может правильно проанализировать список аргументов.я новичок в pyparsing, поэтому любая помощь приветствуется.

1 Ответ

0 голосов
/ 07 июня 2018

Это довольно сложные списки аргументов в этих функциях.Так что, если вы пытаетесь разобрать их , это будет довольно большая работа.

Однако, если вы просто хотите, чтобы имя функции и строка аргументов были переданы, то с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'

Есливы просто хотите, чтобы список аргументов был в виде строки, тогда вы можете заключить в 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'

Если вы хотите удалить открытия и закрытия () и проанализировать запятые с разделителями, это упражнение, оставленное для читателя / ОП.(Если это так, вы можете вернуться к первой версии и работать с разобранными битами списка аргументов, а не с версией из одной строки.)

...