¿Cómo puedo usar pyparsing para analizar expresiones anidadas que tienen múltiples tipos de apertura / cierre?

Me gustaría usar pyparsing para analizar una expresión de la forma: expr = '(gimme [some {nested [lists]}])' , y recuperar una lista de python de la forma: [[['gimme', ['some', ['nested', ['lists']]]]]] . En este momento mi gramática se ve así:

nestedParens = nestedExpr (‘(‘, ‘)’)
nestedBrackets = nestedExpr (‘[‘, ‘]’)
nestedCurlies = nestedExpr (‘{‘, ‘}’)
enclosed = nestedParens | nestedsBrackets | nestedsCurlies

Actualmente, enclosed.searchString(expr) devuelve una lista de la forma: [[['gimme', ['some', '{nested', '[lists]}']]]] . Esto no es lo que quiero porque no reconoce los corchetes o los corchetes, pero no sé por qué.

Aquí hay una solución de pyparsing que usa una gramática auto-modificable para hacer coincidir dinámicamente el correcto corchete de cierre.

 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() 

huellas dactilares:

 [['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]] 

Actualizado: publiqué la solución anterior porque la había escrito hace más de un año como un experimento. Acabo de echar un vistazo más de cerca a su publicación original, y me hizo pensar en la definición de tipo recursiva creada por el método de precedencia del operatorPrecedence , por lo que rehicí esta solución, utilizando su enfoque original, ¡mucho más sencillo de seguir! (aunque podría tener un problema de recursión a la izquierda con los datos de entrada correctos, no se ha probado a fondo):

 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() 

Da:

 [['gimme', ['some', ['nested', ',', 'nested', ['lists']]]]] 

Esto debería hacer el truco por ti. Lo probé en tu ejemplo:

 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 

Comenta si necesitas más