2012-04-19 10 views
6

Si tengo:¿Utiliza la expresión regular para manejar los paréntesis anidados en la ecuación matemática?

statement = "(2*(3+1))*2" 

Quiero ser capaz de manejar múltiples paréntesis dentro de paréntesis, para un lector de matemáticas que estoy escribiendo. Tal vez estoy haciendo esto de la manera incorrecta, pero mi objetivo era recursivamente profundizar en el paréntesis hasta que no hubiera ninguno, y luego realizar las operaciones matemáticas. Por lo tanto, me gustaría en primer lugar que desee centrarse en

"(2*(3+1))" 

continuación se centran en

"(3+1)" 

esperaba hacerlo asignando el valor de enfoque para el índice de inicio de la expresión regular y el índice final de la expresión regular . Todavía tengo que encontrar la manera de encontrar el índice final, pero estoy más interesado en la adecuación de la expresión regular primera

r"\(.+\)" 

no pudieron igualar. Quería que se lea como "uno o más caracteres contenidos dentro de un paréntesis". ¿Podría alguien explicar por qué la expresión anterior no coincidirá con la declaración anterior en python?

+0

analizador? .......... –

+0

['r" \ (. + \) "' No coincide.] (Http://ideone.com/oJQjV) – Amber

Respuesta

12

Me encanta expresiones regulares. Los utilizo todo el tiempo.

No utilizar expresiones regulares para esto.

¿Quieres un analizador real que realmente va a analizar sus expresiones matemáticas. Es posible que desee leer esto:

http://effbot.org/zone/simple-top-down-parsing.htm

Una vez que realmente han analizado la expresión, es trivial para recorrer el árbol de análisis sintáctico y calcular el resultado.

EDIT: @Lattyware sugirió pyparsing, que también debe ser un buen camino a seguir, y podría ser más fácil que la solución EFFBot publicado anteriormente.

http://pyparsing.wikispaces.com

Aquí hay un enlace directo al código de ejemplo pyparsing para una de cuatro funciones evaluador de expresiones algebraicas:

http://pyparsing.wikispaces.com/file/view/fourFn.py

+0

También podría valer la pena mencionar ['' pyparsing''] (http://pyparsing.wikispaces.com/) - aunque si esto es todo lo que se quiere, sería excesivo. –

+0

@Lattyware Entonces, ¿recomendaría usar pyparsing si quisiera usar mi programa python para analizar un archivo e interpretar su contenido como si fuera código en otro idioma? – purpleladydragons

+1

@purpleladydragons, pyparsing es un kit para compilar cualquier analizador que necesites. El código de muestra para pyparsing incluye un "analizador de notación algebraica de cuatro funciones", por lo que le daría un punto de partida: http://pyparsing.wikispaces.com/file/view/fourFn.py – steveha

1

probablemente estoy de acuerdo con steveha, y no recomiendo expresiones regulares para este , pero para responder a su pregunta específicamente, necesita parches no guardados para extraer grupos de resultados (su patrón solo ha escapado de los parientes):

>>> re.match(r"\((.+)\)", "(2*(3+1))*2").group(1) 
'2*(3+1)' 

Si va por esa ruta, puede repetir los resultados del partido hasta que se agoten las coincidencias y luego invierta la lista de resultados para que funcione al revés.

2

para lo que vale, aquí hay un poco más de contexto:

expresiones regulares se llaman paréntesis "normales" porque están asociados con las gramáticas regulares y gramáticas regulares no pueden describir (un número ilimitado de) anidados (que puede describir un montón de paréntesis aleatorios, pero no puede hacer que coincidan en parejas ordenadas).

Una forma de entender esto es entender que las expresiones regulares pueden (algunos detalles que explicaré al final) convertir a autómatas finitos deterministas. lo cual suena intimidante, pero realmente solo significa que se pueden convertir en listas de "reglas", donde las reglas dependen de lo que coincida, y describir lo que puede coincidir.

por ejemplo, la expresión regular ab*c se puede convertir en:

  1. al principio, sólo se puede igualar a. y luego ir a 2.

  2. ahora, puede hacer coincidir b y volver a 2, o el partido c e ir a 3

  3. ya está! ¡el partido fue un éxito!

y que es un "autómata determinista finito".

de todos modos, la parte interesante de esto es que si te sientas y tratas de hacer algo así para unir pares de paréntesis, ¡no puedes! intentalo. puede hacer coincidir un número finito haciendo más y más reglas, pero no puede escribir un conjunto general de reglas que coincida con un número ilimitado de paréntesis (debería agregar que las reglas tienen que ser de la forma "si coincide X vaya"). a Y ").

Ahora, obviamente, puede modificar eso de varias maneras. podría permitir reglas más complejas (como extenderlas para permitirle contar los paréntesis), y luego podría obtener algo que funcionara como esperaba. pero no sería una gramática regular.

dado que las expresiones regulares son limitadas de esta manera, ¿por qué se utilizan en lugar de algo más complejo? resulta que son algo así como un punto dulce: pueden hacer mucho, sin dejar de ser bastante simples y eficientes. las gramáticas más complejas (tipos de reglas) pueden ser más poderosas, pero también son más difíciles de implementar y tienen más problemas con la eficiencia.

descargo de responsabilidad y detalles adicionales prometidos: en la práctica, muchas expresiones regulares actualmente en realidad son más potentes que esto (y no deberían llamarse realmente "expresiones regulares"). pero lo anterior sigue siendo la explicación básica de por qué no deberías usar una expresión regular para esto.

ps La solución sugerida de jesse lo soluciona mediante el uso de una expresión regular varias veces; el argumento aquí es para un uso único de la expresión regular.

+0

El resumen breve de lo anterior: "las expresiones regulares no pueden contar".Tomará mucho trabajo, aplicando repetidamente expresiones regulares, para hacer que manejen expresiones con paréntesis. – steveha

Cuestiones relacionadas