Как я могу использовать пипарс для анализа вложенных выражений, которые имеют несколько типов открытия/ближе?
Вопрос
Я хотел бы использовать пипарс, чтобы разобрать выражение формы: expr = '(gimme [some {nested [lists]}])'
, и верните список питонов формы: [[['gimme', ['some', ['nested', ['lists']]]]]]
. Анкет Прямо сейчас моя грамматика выглядит так:
instedParens = indestExpr ('(', ')')
indestBrackets = indestExpr ('[', ']')
indestCurlies = indestExpr ('{', '}')
Прилагается = indestParens | InstedBrackets | вложенные
На данный момент, enclosed.searchString(expr)
Возвращает список формы: [[['gimme', ['some', '{nested', '[lists]}']]]]
. Анкет Это не то, что я хочу, потому что это не распознавание квадратных или кудрявых кронштейнов, но я не знаю почему.
Решение
Вот решение для пипарса, которое использует самомодифицирующую грамматику для динамического соответствия правильного символа закрывающегося скоба.
from pyparsing import *
data = '(gimme [some {nested, nested [lists]}])'
opening = oneOf("( { [")
nonBracePrintables = ''.join(c for c in printables if c not in '(){}[]')
closingFor = dict(zip("({[",")}]"))
closing = Forward()
# initialize closing with an expression
closing << NoMatch()
closingStack = []
def pushClosing(t):
closingStack.append(closing.expr)
closing << Literal( closingFor[t[0]] )
def popClosing():
closing << closingStack.pop()
opening.setParseAction(pushClosing)
closing.setParseAction(popClosing)
matchedNesting = nestedExpr( opening, closing, Word(alphas) | Word(nonBracePrintables) )
print matchedNesting.parseString(data).asList()
Отпечатки:
[['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]]
Обновлено: Я опубликовал приведенное выше решение, потому что на самом деле написал его более года назад в качестве эксперимента. Я просто поближе посмотрел на ваш оригинальный пост, и это заставило меня задуматься о определении рекурсивного типа, созданном operatorPrecedence
Метод, и поэтому я переехал это решение, используя ваш оригинальный подход - намного проще следовать! (может быть проблема левой рекурсии с правильными входными данными, не тщательно проверено):
from pyparsing import *
enclosed = Forward()
nestedParens = nestedExpr('(', ')', content=enclosed)
nestedBrackets = nestedExpr('[', ']', content=enclosed)
nestedCurlies = nestedExpr('{', '}', content=enclosed)
enclosed << (Word(alphas) | ',' | nestedParens | nestedBrackets | nestedCurlies)
data = '(gimme [some {nested, nested [lists]}])'
print enclosed.parseString(data).asList()
Дает:
[['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]]
Другие советы
Это должно помочь вам. Я проверил это на вашем примере:
import re
import ast
def parse(s):
s = re.sub("[\{\(\[]", '[', s)
s = re.sub("[\}\)\]]", ']', s)
answer = ''
for i,char in enumerate(s):
if char == '[':
answer += char + "'"
elif char == '[':
answer += "'" + char + "'"
elif char == ']':
answer += char
else:
answer += char
if s[i+1] in '[]':
answer += "', "
ast.literal_eval("s=%s" %answer)
return s
Комментарий, если вам нужно больше