Esta es una reformulación de ¿Son los programas de gramáticas? previamente preguntado por Vag y con muchas sugerencias de los comentaristas.
¿De qué manera puede verse una gramática que especifica un modelo de cálculo? Si, por ejemplo, tomamos una gramática simple sin contexto, como
G ::= '1' -> '0' '+' '1'
'1' -> '1' '+' '0'
'2' -> '2' '+' '0'
'2' -> '1' '+' '1'
'2' -> '0' '+' '2'
'3' -> '3' '+' '0'
'3' -> '2' '+' '1'
'3' -> '1' '+' '2'
'3' -> '1' '+' '2'
Suponiendo que el analizador no distingue entre símbolos terminales y no terminales como he demostrado aquí, entonces es posible realizar una aritmética simple para números hasta 3.
Por ejemplo, toma la cuerda
"2 + 0 + 1"
Ejecutar un analizador LR (1) en esta cadena debería darnos el siguiente árbol de sintaxis concreta donde el resultado del cálculo se almacena en la raíz del árbol:
'3'
/ | \
/ | \
'2' '+' '1'
/ | \
/ | \
'2' '+' '0'
Por lo tanto, si consideramos que una gramática es un programa y un generador de analizadores para ser un compilador , ¿podríamos ver el lenguaje de especificación gramatical como un lenguaje de programación ?
Además, ¿podríamos construir programas completos de Turing especificando gramáticas similares a cómo podría construir programas completos de Turing con autómatas celulares o el cálculo lambda ?
En otras palabras, se sabe que, en el sentido de reconocer un idioma, los lenguajes regulares corresponden a autómatas de estado finito , los lenguajes libres de contexto corresponden a autómatas de empuje y los lenguajes sensibles al contexto corresponden a autómatas lineales . Sin embargo, si consideramos las gramáticas como dispositivos computacionales (es decir, programas en el sentido del ejemplo anterior), ¿cómo clasificamos la fuerza computacional de cada clase de gramáticas en la jerarquía de Chomsky?
- Gramáticas regulares
- Gramáticas libres de contexto
- Gramáticas sensibles al contexto
- Gramáticas sin restricciones (para lenguajes recursivamente enumerables )
Además, ¿qué hay de las subclases menos conocidas de gramáticas como
- Gramáticas deterministas sin contexto (también LR (k) / LL (k) / SLR / LALR, etc.)
- Gramáticas de palabras anidadas
- Gramáticas adyacentes a los árboles
- Gramáticas indexadas
EDITAR: Por cierto, este es un punto crítico en mi propia pregunta, pero no mencioné que no di ningún símbolo de inicio para la gramática de ejemplo y agité a mano la necesidad de distinguir entre terminales y no terminales. Técnica o tradicionalmente creo que la gramática probablemente debería escribirse en una forma más complicada como esta (donde S es el símbolo de inicio y $ representa el terminal de fin de flujo):
G ::= S -> R0 '$'
S -> R1 '$'
S -> R2 '$'
R0 -> '0'
R0 -> R0 '+' '0'
R1 -> '1'
R1 -> R0 '+' '1'
R1 -> '1' '+' R0
R1 -> R0 '+' '1' '+' R0
R2 -> '2'
R2 -> R0 '+' '2'
R2 -> '2' '+' R0
R2 -> R0 '+' '2' '+' R0
R2 -> R1 '+' '1'
R2 -> R1 '+' '1' '+' R0
... no es que realmente cambie nada, pero pensé que debería mencionarlo.
EDITAR: Algo más que me vino a la mente cuando leí la respuesta de Gasche es que cada rama en el árbol en mi ejemplo representa un sub-cálculo. Si observa cada regla de producción como una función donde el LHS representa el resultado y el RHS representa sus argumentos, entonces la estructura de la gramática determina cómo se componen las funciones.
En otras palabras, el contexto del analizador junto con su mecanismo de búsqueda anticipada ayuda a determinar no solo qué funciones aplicar ('un poco' como el polimorfismo paramétrico) sino cómo deben componerse juntas para formar nuevas funciones.
Al menos, supongo que podrías verlo de esta manera para CFG inequívocos, para otras gramáticas, la gimnasia mental es demasiado para mí en este momento.
Respuestas:
Existe una correspondencia biunívoca entre las gramáticas Chomsky Type-0 y las máquinas de Turing.
Esto se explora en el lenguaje de programación Thue que le permite escribir programas completos de Turing especificados por una cadena inicial y un conjunto de reglas de reescritura de cadenas (una gramática semi-Thue , que es equivalente a una gramática de tipo 0).
ACTUALIZAR:
Además de los lenguajes esotéricos "Turing tar-pit" como Thue, se pueden usar varios lenguajes de propósito general que permiten al programador extender su propia sintaxis para realizar el cómputo completo de Turing durante la etapa de compilación de análisis.
Los idiomas de la familia Lisp , en particular Common Lisp , son probablemente los ejemplos más obvios, pero también, en términos generales, los idiomas con comprobación de tipo estático que no siempre tienen que detenerse, como C ++ con plantillas , Scala y Qi .
fuente
Mi respuesta no pretende ser formal, precisa y absolutamente dentro del tema. Creo que la respuesta de Marc Hamman es sólida, pero su pregunta me hizo pensar en un tema relacionado.
Las gramáticas pueden considerarse casos especiales de sistemas deductivos: la entrada es un juicio, y el árbol de análisis es una derivación del juicio, o prueba de que el juicio es válido de acuerdo con las reglas (gramaticales).
En ese sentido, su pregunta podría estar relacionada con el enfoque de alguna parte de la comunidad de programación lógica / búsqueda de pruebas (estoy pensando en Dale Miller, por ejemplo), que es que la búsqueda de pruebas tiene contenido computacional, a diferencia del más clásico punto de vista de la teoría de tipo / prueba donde el cálculo es normalización de prueba .
Observación: releyendo mi respuesta, creo que la idea de que "la construcción del árbol de análisis es una búsqueda de prueba" es un poco descabellada aquí. La búsqueda de pruebas fluye más bien en la otra dirección: se parte de un juicio determinado y bastante complejo y, mediante el uso repetido de reglas de inferencia que trabajan en la estructura de la prueba, se espera obtener axiomas más simples que no es necesario probar más. Por lo tanto, sería más natural ver, en términos gramaticales, juicios complejos como no terminales, átomos como terminales, y la búsqueda de pruebas como un problema de generación de palabras, o prueba de no vacío.
fuente
No estoy seguro si entendí correctamente su pregunta, pero si está buscando un lenguaje de programación basado en un tipo de sistema de reescritura de cadenas, probablemente estaría interesado en Refal , que se basa en el formalismo del algoritmo de Markov (un Turing- formalismo completo, que también es un sistema de reescritura de cadenas tipo gramática).
fuente
S -> A a; S -> B b; A -> 0; B -> 0
. Si programamos esto invirtiendo las reglas, tendremos que elegir diferentes reglas para procesar0
en tiempo de ejecución para evaluar "0a" o "0b"S
.(Solo algunas consideraciones triviales. Podría ser un comentario, pero demasiado largo).
De hecho, lo que describe se ve en efecto como la visión muy natural de lo que es un idioma (en la comprensión humana del "lenguaje", su propósito) y cómo una gramática define un idioma.
Un lenguaje comprende (infinitamente) formas sintácticas correctas que se interpretan para dar los valores semánticos .
Si la interpretación es computable, entonces las formas sintácticas de un lenguaje pueden verse como programas que computan los valores semánticos.
Si suponemos que un idioma se implementa como un dispositivo finito, podemos llamar a esta representación finita de un idioma una "gramática". Según esta comprensión, una gramática se preocupa por la sintaxis, pero también por la semántica, es decir, cómo calcular el valor semántico de una expresión completa a partir de los valores de sus partes (las partes atómicas y sus valores se almacenan en un "léxico") .
Algunas teorías del lenguaje natural tienen esa forma (la forma que es consistente con las consideraciones anteriores; ya se mencionó en la respuesta de @ gasche aquí): un sistema deductivo que busca una derivación de la entrada (junto con el cálculo de la semántica valor, o la construcción del término de prueba; cf. correspondencia de Curry-Horward). Entonces, si observamos sistemas como ese y los consideramos gramáticas, entonces su pregunta es trivial : estos sistemas están diseñados exactamente para realizar cálculos de la manera que usted describe.
Pero lo que tradicionalmente se llama "lenguajes formales" y "gramáticas formales" carece del lado semántico de esta visión sobre los lenguajes y las gramáticas. Entonces, su pregunta se vuelve interesante: ¿en qué medida se puede "simular" el lado semántico (cálculo) en la sintaxis? ¿Cuáles son los poderes computacionales de cada una de las clases conocidas de gramáticas formales (si el cálculo debe entenderse como el análisis de abajo hacia arriba: una gramática calcula una función en el sentido de su pregunta si se trataGf G de una entrada válida si se analiza como el símbolo según )?f ( I ) = S I S GI f(I)=S I S G
(De hecho, los compiladores reales para lenguajes de programación se parecen más a un sistema con sintaxis y semántica: transforman la forma sintáctica de un programa en un ejecutable, que es el significado semántico del programa, y no simplemente un símbolo de inicio de la gramática)
fuente
Solo para agregar:
Una vista gramatical de la programación lógica por Pierre Deransart y Jan Maluszynski.
fuente
¿Qué pasa con algo como los números de Peano:
reconocerá cualquier cadena (número) de esta forma:
y debería devolver una estructura anidada, siendo la profundidad el número.
Pero comienza a complicarse cuando uno quiere implementar simplemente decir además:
Tiene mucho sentido ya que solo reconocerá entradas bien formadas como esta:
Pero esta gramática introduce una división en el árbol de análisis cada vez que hay una suma, por lo que, en lugar de tener un bonito árbol de una sola ramificación, que se mapea directamente a un número, tenemos la estructura de la expresión, todavía a unos pocos cálculos de lo efectivo valor. Entonces, no se realiza ningún cálculo, solo reconocimiento. El problema puede no ser la gramática sino el analizador. En cambio, uno puede usar otra cosa, idk ... Otro punto que viene a la mente es la adecuación del formalismo gramatical para expresar la computación. Cuando miras el axioma de Peano (en notación similar a Haskell):
La tercera regla establece explícitamente una transformación. ¿Alguien podría imaginar tener el mismo significado en una regla gramatical libre de contexto? Y si es así, ¿cómo?
fuente