En el sentido académico, ¿las expresiones regulares califican como lenguaje de programación?
La motivación para mi curiosidad es una pregunta SO que acabo de mirar y que preguntó "¿puede regex hacer X?" y me hizo preguntarme qué se puede decir en sentido genérico sobre las posibles soluciones que los utilizan.
Básicamente estoy preguntando, "¿son completas las expresiones regulares de Turing"?
programming-languages
regular-expressions
Anodide Aaron
fuente
fuente
Respuestas:
Las expresiones regulares son un tipo particular de gramática formal utilizada para analizar cadenas y otra información textual que se conoce como "lenguas regulares" en la teoría del lenguaje formal. No son un lenguaje de programación como tal. Son más una abreviatura para la codificación que de otro modo sería extremadamente tediosa de implementar e incluso más confusa que la Regex a veces arcana.
Los lenguajes de programación generalmente se definen como lenguajes que están completos en Turing . Dichos lenguajes deben poder procesar cualquier función computable . Regex no encaja en esta categoría.
Si quieres un lenguaje que se parezca a Regex, prueba J.
fuente
Es difícil responder a preguntas del tipo "es X una Y ", si los participantes en el debate del uso de diferentes definiciones de X e Y . Podría ser que para algunas definiciones, la respuesta es "sí", y para algunas definiciones la respuesta es "no". Especialmente si la respuesta depende de detalles técnicos donde las diferentes definiciones difieren. Además, esta discusión contiene información errónea, así que tenga paciencia con una respuesta más larga.
¿Qué queremos decir con " lenguaje de programación "?
Una respuesta simple podría ser "un lenguaje utilizado para crear programas". Claro, pero: ¿qué tipo de programas? ¿Qué pasa con un lenguaje que podría usarse para crear algunos tipos de programas, pero no otros tipos de programas? Aquí hay dos ejemplos específicos para ilustrar los casos extremos:
1) Un lenguaje imaginario llamado M funciona así: si el programa contiene la letra única "m", crea un juego de Buscaminas. Todo lo demás es un error de sintaxis.
Intuitivamente, esto no es lo que queremos decir con "un lenguaje de programación". Pero el departamento de marketing de M podría argumentar que técnicamente cumple con la definición, porque puede usarse para crear un programa. Claro, el compilador hace algunas partes críticas para usted, pero eso es lo que hacen los compiladores, ¿no? Un compilador del lenguaje C también traduce algunas palabras simples en docenas de instrucciones del procesador. El compilador M simplemente va más allá y simplifica aún más su trabajo.
2) Si instala la versión original del famoso Turbo Pascal, puede escribir muchos tipos de programas. Pero no puede escribir un juego que se ejecute en el navegador web, porque la API necesaria simplemente no está allí.
Entonces, ¿qué es exactamente lo que hace de Turbo Pascal un lenguaje de programación, pero M no lo tiene? Simplemente hablando, puedes hacer más en Pascal que en M. Pero imagina que tenemos un M.NET, que crea un juego de Buscaminas que se ejecuta en un navegador web. Así que ahora tenemos algo que Pascal puede hacer y M.NET no, pero también tenemos algo que M.NET puede hacer y Pascal no. ¿Por qué deberíamos considerar importantes las ventajas de Pascal y las ventajas de M.NET irrelevantes?
La respuesta es que puede escribir todo tipo de algoritmos en Pascal, pero no puede escribir algoritmos en M o M.NET. Claro, M compila su comando "m", y C compila su comando "strcmp". Pero puede poner "strcmp" en un contexto más amplio, por ejemplo, comparar dos archivos línea por línea, o leer miles de cadenas y ordenarlas alfabéticamente, o ... bueno, millones de otras cosas. Y es precisamente esta capacidad de usar comandos dados en cualquier algoritmo lo que hace la esencia de un lenguaje de programación.
¿Qué es exactamente un algoritmo y, lo que es más importante, qué es "cualquier algoritmo"? En informática utilizamos las palabras Turing-complete . La idea es que hay un conjunto de lenguajes de computadora, donde cada uno de ellos puede simularlos a todos. Uno de esos idiomas es la máquina de Turing, por eso se les llama así. Pascal está allí, C está allí, Java está allí, Python está allí, Lisp está allí, Smalltalk está allí, incluso XSLT está allí. Nuestros hipotéticos M y M.NET no están allí. Puedes aprender más sobre esto en cualquier universidad que ofrezca un curso de computación decente, pero la idea es que un lenguaje completo de Turing pueda hacer cualquier cosaque otro lenguaje completo de Turing puede hacer, si les das la API mínima necesaria. (Si le das alguna API de navegador web a Pascal, puedes crear todo tipo de juegos en el navegador web. Si le das API de navegador web a M, todavía solo puedes crear Buscaminas.) Podríamos decir metafóricamente que si Si elimina todas las API de un lenguaje de programación, lo importante es lo que queda.
¿Qué queremos decir con " expresiones regulares "?
Diferentes lenguajes de programación los implementan de manera ligeramente diferente. Pero la idea original era que las expresiones regulares expresan los llamados lenguajes regulares . Tenga en cuenta que aquí no hablamos sobre lenguajes de programación, sino sobre lenguajes (pseudo) humanos. Imagine que encuentra una tribu exótica que habla un idioma que consiste solo en palabras "ba", "baba", "bababa", etc. Podría describir este lenguaje verbalmente como "una sílaba 'ba' repetida una o más veces" o utilizando una expresión regular como "(ba) +".
Se supone que las expresiones regulares expresan: "nada", "esta letra", "esto, seguido de eso", "esto o aquello", "esto, repetido una o más veces", y "no esto". - Esa es la definición matemática . Cualquier otra cosa es solo un conveniente acceso directo creado a partir de los componentes anteriores. Por ejemplo, "esto, repetido dos o tres veces" puede traducirse como "esto, seguido de esto, seguido de (esto o nada)", pero podría ser más conveniente escribir "ba {2,3}" que "baba (licenciado en Letras)?".
En la vida real, una implementación típica de "expresiones regulares" implementa más que esto. Por ejemplo, usando la definición matemática, un lenguaje de "aba", "aabaa", "aaabaaa", etc., cualquier número de "a" s, seguido de una "b", seguido del mismo número de "a "s - no es un lenguaje normal. Sin embargo, muchas "expresiones regulares" utilizadas hoy podrían detectarlo, utilizando el concepto adicional de "lo mismo que encontramos antes", escrito como "(a +) b \ 1". Usando este concepto adicional, podemos hacer algunas cosas interesantes, por ejemplo, detectar palabras que consisten en un número primo de letras. Aún así, no podemos hacer ningún algoritmo ... para una explicación de por qué,
Entonces, volviendo al tema original: ¿son las expresiones regulares (definidas como: expresiones que describen lenguajes regulares en la jerarquía de Chomsky; o como: el primero, más la operación \ 1) un lenguaje de programación (definido como: Turing-complete)? La respuesta es no . No, no puede implementar ningún algoritmo utilizando expresiones regulares, y la capacidad de implementar cualquier algoritmo es lo que las personas que estudian informática generalmente entienden como la esencia del lenguaje de programación.
Por supuesto, cualquiera puede cambiar la respuesta insistiendo en una definición diferente . Como escribí al principio, los detalles técnicos son importantes aquí. Si te equivocas, obtienes una respuesta incorrecta.
Y si usted está no interesado en los detalles técnicos, la respuesta podría ser: ¿Se puede utilizar expresiones regulares (y nada más) para hacer un programa? No. Entonces, ¿por qué llamarlo un lenguaje de programación? (Sin embargo, una respuesta como esta se descargó y eliminó aquí, por eso escribí esta versión más larga).
EDITAR: Además, cualquiera puede crear una biblioteca implementando su propia nueva variante de "expresiones regulares" con algunas características nuevas agregadas. En algún momento, las nuevas características pueden ser suficientes para que todo el sistema se complete en Turing. Un ejemplo trivial sería incorporar un lenguaje completo de Turing usando alguna nueva sintaxis; pero también puede suceder menos obviamente. Quizás ya sucedió.
fuente
En .Net, Regex no solo puede manejar múltiples formas de condicionales, usando diferentes combinaciones de alternancia y lookarounds, sino que también puede manipular su propia pila.
Esto, por ejemplo, es un pequeño fragmento que escribí para recuperar una tabla HTML. A diferencia de otros motores de expresiones regulares, controla la pila de colecciones de captura (push, peek y pop) y puede manejar objetos anidados. Tengo uno más complejo, pero es más bien propietario.
Creo que en este ejemplo, se puede considerar que Regex tiene todos los requisitos básicos de un lenguaje de programación. Tiene variables, memoria en línea, condicionales, entrada y salida, se compila utilizando uno de los múltiples motores de compilación de expresiones regulares (.Net en este caso).
En respuesta al graznido sobreutilizado para (NUNCA) analizar HTML con expresiones regulares, seguí adelante y publiqué una respuesta preescrita que puedo publicar: Análisis HTML
Otro ejemplo (solo una demostración) es el siguiente:
Nuevamente, para los loros HTML: analizar HTML
Esto muestra una expresión regular más simple que realiza bucles y condicionales (¿algoritmos?). Lo único que falta es el cálculo matemático real. Esta es una expresión regular más detallada que simplemente extrae una célula TD más eficientemente que el método típico "(. *?)".
Pero incluso como entusiasta de Regex y maestro autoproclamado, no iría por ahí diciéndole a nadie que Regex es un lenguaje de programación. Mi propio argumento en mi contra es que no puede estar solo, debe ejecutarse a través de su propio motor mientras es compatible con otro motor de lenguaje de programación.
fuente
Si bien encontrar / reemplazar en una expresión regular no es un lenguaje de programación completo de Turing, como se explicó en las respuestas anteriores, si permite usar acciones repetidas de reemplazar con expresiones regulares, entonces sí, puede codificar cualquier máquina de Turing usando una expresión regular:
Buscar / reemplazar repetidamente con expresiones regulares es un lenguaje de programación completo de Turing
Como consecuencia, puede calcular cualquier función computable usando la misma búsqueda y reemplazar la expresión regular de javascript una y otra vez.
Para probar la integridad de Turing, es suficiente codificar una máquina de Turing en búsqueda / reemplazo de expresiones regulares. Suponga que el estado del editor es:
que se puede leer como una cinta de símbolos con un lector:
Para la regla que lee 0 en el estado 5, escribe 1 y cambia su estado a 3 y se mueve hacia la izquierda, lo abstraemos usando la siguiente notación:
Codificamos la notación anterior en una expresión regular de búsqueda:
y su expresión de reemplazo (similar a javascript)
Ok, ¿ahora cómo codificar muchas reglas? Utilizamos la concatenación con el
or
operador|
para la búsqueda de expresiones regulares, y combinamos los resultados en reemplazo, numerando números de grupo con desplazamientos. Por ejemplo, consideremos el conjunto de cuatro reglas.Los codificamos en una búsqueda y reemplazamos la expresión:
Pruébelo en su motor javascript favorito:
fuente