En la teoría del lenguaje formal de la informática , la recursión izquierda es un caso especial de recursión en el que una cadena se reconoce como parte de un lenguaje por el hecho de que se descompone en una cadena de ese mismo lenguaje (a la izquierda) y un sufijo (a la derecha). Por ejemplo,puede reconocerse como una suma porque se puede dividir en, también una suma, y, un sufijo adecuado.
En términos de gramática libre de contexto , un no terminal es recursivo por la izquierda si el símbolo más a la izquierda en una de sus producciones es él mismo (en el caso de recursión directa por la izquierda) o puede convertirse en sí mismo mediante alguna secuencia de sustituciones (en el caso de recursión indirecta por la izquierda).
Definición
Una gramática es recursiva por la izquierda si y solo si existe un símbolo no terminal.que puede derivar en una forma sentencial con ella misma como el símbolo más a la izquierda. [ 1 ] Simbólicamente,
- ,
dóndeindica la operación de realizar una o más sustituciones, yes cualquier secuencia de símbolos terminales y no terminales.
Recursión directa por la izquierda
La recursión izquierda directa ocurre cuando la definición se puede satisfacer con una sola sustitución. Requiere una regla de la forma
dóndees una secuencia de no terminales y terminales. Por ejemplo, la regla
es directamente recursivo por la izquierda. Un analizador sintáctico descendente recursivo de izquierda a derecha para esta regla podría verse así:
void Expresión () { Expresión (); coincidencia ( '+' ); Término (); }y dicho código caería en una recursión infinita al ejecutarse.
Recursión izquierda indirecta
La recursión izquierda indirecta se produce cuando la definición de recursión izquierda se satisface mediante varias sustituciones. Implica un conjunto de reglas que siguen el patrón
dóndeson secuencias que pueden producir cada una la cadena vacía , mientras quePuede ser cualquier secuencia de símbolos terminales y no terminales. Tenga en cuenta que estas secuencias pueden estar vacías. La derivación
luego dacomo la más a la izquierda en su forma oracional final.
Usos
La recursión izquierda se usa comúnmente como un modismo para hacer que las operaciones sean asociativas por la izquierda : que una expresión a+b-c-d+ese evalúe como (((a+b)-c)-d)+e. En este caso, ese orden de evaluación podría lograrse como una cuestión de sintaxis a través de las tres reglas gramaticales.
Estos solo permiten analizar ela+b-c-d+ecomo compuesto pora+b-c-dye, donde a+b-c-da su vez consiste en ela+b-cyd, mientras que a+b-cconsta de laa+byc, etc.
Eliminando la recursión izquierda
La recursión izquierda suele plantear problemas a los analizadores sintácticos, ya sea porque los lleva a una recursión infinita (como en el caso de la mayoría de los analizadores descendentes ) o porque esperan reglas en una forma normal que la prohíbe (como en el caso de muchos analizadores ascendentes ). Por lo tanto, a menudo se preprocesa una gramática para eliminar la recursión izquierda.
Eliminando la recursión directa por la izquierda.
A continuación se muestra el algoritmo general para eliminar la recursión izquierda directa. Se han realizado varias mejoras a este método. [ 2 ] Para un no terminal recursivo izquierdo, descartar cualquier regla de la formay consideremos a los que quedan:
dónde:
- cadaes una secuencia no vacía de no terminales y terminales, y
- cadaes una secuencia de no terminales y terminales que no comienza con.
Reemplazar estos con dos conjuntos de producciones, un conjunto para:
y otro conjunto para el nuevo no terminal(a menudo llamada la "cola" o el "resto"):
Repita este proceso hasta que no quede ninguna recursión izquierda directa.
Como ejemplo, consideremos el conjunto de reglas.
Esto podría reescribirse para evitar la recursión izquierda como
Eliminando toda la recursión izquierda.
El proceso anterior se puede extender para eliminar toda la recursión izquierda, convirtiendo primero la recursión izquierda indirecta en recursión izquierda directa en el no terminal de mayor número en un ciclo.
- Entradas Una gramática: un conjunto de no terminalesy sus producciones
- Salida: Una gramática modificada que genera el mismo lenguaje pero sin recursión izquierda.
- Para cada no terminal:
- Repita el proceso hasta que una iteración no altere la gramática:
- Para cada regla, elsiendo una secuencia de terminales y no terminales:
- Sicomienza con un no terminaly:
- Dejarsersin su liderazgo.
- Eliminar la regla.
- Para cada regla:
- Agregar la regla.
- Sicomienza con un no terminaly:
- Para cada regla, elsiendo una secuencia de terminales y no terminales:
- Eliminar la recursión izquierda directa paracomo se describió anteriormente.
- Repita el proceso hasta que una iteración no altere la gramática:
- Para cada no terminal:
El paso 1.1.1 consiste en expandir el no terminal inicial.en el lado derecho de alguna regla, pero solo si. SiSi se trataba de un paso en un ciclo de producciones que daba lugar a una recursión izquierda, entonces esto ha acortado ese ciclo en un paso, pero a menudo a costa de aumentar el número de reglas.
El algoritmo puede considerarse como el establecimiento de un orden topológico en no terminales: después solo puede haber una regla.siCabe señalar que este algoritmo es muy sensible al ordenamiento no terminal; las optimizaciones suelen centrarse en elegir bien dicho ordenamiento.
Escollos
Si bien las transformaciones anteriores preservan el lenguaje generado por una gramática, pueden modificar los árboles de análisis sintáctico que registran el reconocimiento de cadenas. Con una gestión adecuada, la reescritura de árboles puede recuperar los originales, pero si se omite este paso, las diferencias pueden alterar la semántica del análisis.
La asociatividad es particularmente vulnerable; los operadores asociativos por la izquierda suelen aparecer en configuraciones similares a las asociativas por la derecha bajo la nueva gramática. Por ejemplo, partiendo de esta gramática:
Las transformaciones estándar para eliminar la recursión izquierda dan como resultado lo siguiente:
Analizar la cadena "1 - 2 - 3" con la primera gramática en un analizador LALR (que puede manejar gramáticas recursivas por la izquierda) habría dado como resultado el árbol de análisis:

Este árbol de análisis agrupa los términos de la izquierda, dando la semántica correcta (1 - 2) - 3 .
El análisis sintáctico con la segunda gramática da como resultado

lo cual, interpretado correctamente, significa 1 + (-2 + (-3)) , también correcto, pero menos fiel a la entrada y mucho más difícil de implementar para algunos operadores. Nótese cómo los términos de la derecha aparecen más abajo en el árbol, de forma similar a como una gramática recursiva derecha los organizaría para 1 - (2 - 3) .
Adaptación de la recursión izquierda en el análisis sintáctico descendente
Una gramática formal que contiene recursión izquierda no puede ser analizada por un analizador LL(k) u otro analizador descendente recursivo ingenuo a menos que se convierta a una forma recursiva derecha débilmente equivalente . Por el contrario, la recursión izquierda es preferida para los analizadores LALR porque resulta en un menor uso de pila que la recursión derecha . Sin embargo, los analizadores descendentes más sofisticados pueden implementar gramáticas libres de contexto generales mediante el uso de la restricción. En 2006, Frost y Hafiz describieron un algoritmo que admite gramáticas ambiguas con reglas de producción recursivas izquierdas directas . [ 3 ] Ese algoritmo fue extendido a un algoritmo de análisis sintáctico completo para acomodar la recursión izquierda indirecta y directa en tiempo polinomial , y para generar representaciones compactas de tamaño polinomial del número potencialmente exponencial de árboles de análisis sintáctico para gramáticas altamente ambiguas por Frost, Hafiz y Callaghan en 2007. [ 4 ] Los autores luego implementaron el algoritmo como un conjunto de combinadores de analizadores sintácticos escritos en el lenguaje de programación Haskell . [ 5 ]
Véase también
Referencias
- ↑ "Notas sobre teoría del lenguaje formal y análisis sintáctico" (PDF) . Archivado del original el 27/11/2007 . Consultado el 30/10/2023 .
{{cite web}}: CS1 maint: bot: estado de la URL original desconocido ( enlace ) . James Power, Departamento de Ciencias de la Computación, Universidad Nacional de Irlanda, Maynooth, Condado de Kildare, Irlanda. JPR02 - ↑ Moore, Robert C. (mayo de 2000). "Eliminación de la recursión izquierda de las gramáticas libres de contexto" (PDF) . 6.ª Conferencia de Procesamiento del Lenguaje Natural Aplicado : 249–255 .
- ↑ Frost, R.; R. Hafiz (2006). "Un nuevo algoritmo de análisis sintáctico descendente para acomodar la ambigüedad y la recursión izquierda en tiempo polinomial" . ACM SIGPLAN Notices . 41 (5): 46– 54. doi : 10.1145/1149982.1149988 . S2CID 8006549 . Disponible a través del autor en http://hafiz.myweb.cs.uwindsor.ca/pub/p46-frost.pdf . Archivado el 8 de enero de 2015 en Wayback Machine.
- ↑ Frost, R.; R. Hafiz; P. Callaghan (junio de 2007). "Análisis sintáctico descendente modular y eficiente para gramáticas recursivas izquierdas ambiguas" (PDF) . 10.º Taller Internacional sobre Tecnologías de Análisis Sintáctico (IWPT), ACL-SIGPARSE : 109–120 . Archivado del original (PDF) el 27 de mayo de 2011.
- ↑ Frost, R.; R. Hafiz; P. Callaghan (enero de 2008). «Combinadores de analizadores sintácticos para gramáticas recursivas izquierdas ambiguas». Aspectos prácticos de los lenguajes declarativos (PDF) . Lecture Notes in Computer Science. Vol. 4902. págs. 167–181 . doi : 10.1007/978-3-540-77442-6_12 . ISBN 978-3-540-77441-9Archivado del original (PDF) el 21 de diciembre de 2008.
Enlaces externos
- Consideraciones prácticas para las gramáticas LALR(1) Archivado el 1 de diciembre de 2020 en Wayback Machine
- Flujo de control
- Lenguajes formales
- Análisis sintáctico
- Recursión