2012-04-15 5 views
6

Supongamos que tengo una cadena como la siguiente:Expresión regular para que coincida con el nombre y la función de todos los argumentos en Python

"func(arg1, arg2, arg3, arg4, ..., argn)" 

EDIT: Esta función no está en un idioma en particular. Simplemente tiene este formato. Si lo hace más fácil, no lo piense como una llamada a función, solo una cadena.

Quiero escribir una expresión regular para que coincida con la función y cada de los argumentos. Estoy escribiendo esto en Python. La salida deseada de esto es:

{"function" : "func", "arg" : ["arg1", "arg2", ... , "argn"]} 

EDIT: Si bien los argumentos podrían ser llamadas a funciones, puedo tratar fácilmente de forma recursiva para que coincida con la misma expresión regular una vez que creo que funciona. Con esto quiero decir que puedo recurrir en la función con cada uno de los argumentos. Pero esto no es realmente relevante. Estoy no tratando de crear un intérprete, solo algo para reconocer los argumentos.

Aquí está mi intento de esto:

import re 
s = "func(arg1, arg2, arg3, arg4, argn)" 
m = re.match(r"(?P<function>\w+)\s?\((?P<args>(?P<arg>\w+(,\s?)?)+)\)", s) 
print m.groupdict() 

Y aquí está la salida:

{'function': 'func', 'args': 'arg1, arg2, arg3, arg4, argn', 'arg': 'argn'} 

La función coincide muy bien, y lo mismo ocurre con el conjunto argumento. Sin embargo, parece que no puedo unir los argumentos individuales. ¿Esto es un problema con mi expresión regular, o una limitación de la coincidencia de expresiones regulares de Python?

Edit2: Soy consciente de que ahora puedo dividir los argumentos usando el siguiente código:

d["arg"] = d["args"].split(", ") 

Pero me preguntaba si podía hacer todo el trabajo con expresiones regulares. En particular, me pregunto por qué "arg" se corresponde con el último argumento.

EDIT3: Supongo que estoy (1) esperando descubrir por qué Python solo coincide con el último argumento cada vez, y (2) si puedo hacer una coincidencia de patrones al estilo de Scheme en Python. O si hay algo tan intuitivo en Python como la coincidencia de patrones estilo Scheme. Miré el módulo ast y su sintaxis es prohibitivamente compleja.

+1

¿Está llamada a esta función en algún idioma en particular? No debe usar una expresión regular para analizar un idioma para el que ya existe un analizador correcto/completo ... – Borealid

+0

No puede hacer esto con expresiones regulares (suponiendo que desea hacer coincidir los argumentos individuales, que a su vez podrían ser llamadas a funciones)) Necesitas un analizador real. Si insiste en escribir el suyo, lea esto: http://effbot.org/zone/simple-iterator-parser.htm – Wes

+0

Es posible que desee verificar [pyparsing] (http://pyparsing.wikispaces.com/) si estás planeando hacer algo más complejo. –

Respuesta

4

Parece que eres el 90% no, ¿por qué no intercambiar los argargs y agrupaciones y hacer:

import re 

fn_match = re.match(r"(?P<function>\w+)\s?\((?P<arg>(?P<args>\w+(,\s?)?)+)\)", s) 
fn_dict = fn_match.groupdict() 
del fn_dict['args'] 
fn_dict['arg'] = [arg.strip() for arg in fn_dict['arg'].split(',')] 
+0

Estoy intentando capturar todo como una expresión regular. ¿No es eso posible? – BlackSheep

+0

No obtener la lista resultante de argumentos que desea. ¿Por qué usar solo una navaja suiza cuando tienes toda una caja de herramientas? – mVChr

7

Las expresiones regulares no pueden analizar los lenguajes de programación complejos.

Si solo está tratando de analizar Python, sugiero echar un vistazo al módulo ast, que lo analizará por usted.

+0

No estoy tratando de analizar Python, solo capturar una sintaxis muy específica. Por lo poco que leo, parece que el módulo ast es (1) específico de Python, y (2) es bastante complejo para lo que estoy tratando de hacer. – BlackSheep

1

Para responder a la última parte de su pregunta: Nº Python no tiene nada similar a Esquema de "coincidencia", ni tiene coincidencia de patrones como ML/Haskell. Lo más parecido que tiene es la capacidad de desestructurar cosas como esta

>>> (a, [b, c, (d, e)]) = (1, [9, 4, (45, 8)]) 
>>> e 
8 

Y para extraer la cabeza y la cola de una lista (en Python 3.x) así ...

>>> head, *tail = [1,2,3,4,5] 
>>> tail 
[2, 3, 4, 5] 

Hay algunos módulos flotantes en torno a que el patrón real de hacer juego en Python, sin embargo, pero no puedo dar fe de su calidad.

Si tuviera que hacerlo, lo implementaría de manera diferente - tal vez tenga la capacidad de ingresar un tipo y argumentos opcionales (por ejemplo, longitud o contenido exacto) y una función para llamar si coincide, por lo que match ([list, length = 3, check = (3, str), func]) y que coincida (list _ _ somestr) y llame a func con somestr en el alcance, y también podría agregar más patrones.

Cuestiones relacionadas