1 / 42

Compiladores

Compiladores. Unidad 3. Análisis Sintáctico. Contenido. Funcionalidad del analizador sintáctico. Gramáticas libres de contexto. Árboles de derivación. Especificación sintáctica de un lenguaje. Análisis sintáctico descendente. Análisis sintáctico ascendente.

dominy
Download Presentation

Compiladores

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Compiladores Unidad 3. Análisis Sintáctico

  2. Contenido • Funcionalidad del analizador sintáctico. • Gramáticas libres de contexto. • Árboles de derivación. • Especificación sintáctica de un lenguaje. • Análisis sintáctico descendente. • Análisis sintáctico ascendente. • Generadores de analizadores sintácticos. • YACC

  3. Funcionalidad del analizador sintáctico • La tarea del analizador sintáctico es determinar la estructura sintáctica de un programa a partir de los tokens producidos por el analizador léxico y, ya sea de manera explícita o implícita, construir un árbol de análisis gramatical o árbol sintáctico que represente esta estructura.

  4. Funcionalidad del analizador sintáctico … (2) • La secuencia de tokens ocurre durante la sucesión de llamadas a un procedimiento del analizador léxico (pj: yylex();). • En un compilador de múltiples pasadas se hace necesario generar un árbol sintáctico para transferir y completar información entre las distintas fases. • En un compilador de una sola pasada el analizador sintáctico incorpora todas las fases del compilador y por tanto puede no ser necesario un árbol sintáctico de forma explicita.

  5. Gramáticas libres de contexto • Todo lenguaje de programación tiene reglas que prescriben la estructura sintáctica de programas bien formados. • La estructura sintáctica se puede describir mediante gramáticas libres de contexto o notación BNF. • Así que una gramática libre de contexto puede verse como una especificación para la estructura sintáctica de un lenguaje de programación. • Dicha especificación es muy similar a la especificación de la estructura léxica del lenguaje, solo que ahora se tienen reglas recursivas.

  6. Gramáticas libres de contexto … (2) • Una gramática libre de contexto se compone de terminales, no terminales, un símbolo inicial y producciones: • Los terminales son símbolos básicos para formar secuencias. “componente léxico” es un sinónimo de “terminal”. • Los no terminales son variables sintácticas que denotan conjuntos de secuencias. Imponen una estructura jerárquica útil para el análisis y la traducción. • El símbolo inicial esta determinado por un único no terminal. • Las producciones especifican cómo se pueden combinar los terminales y no terminales para formar secuencias. Producción Metasímbolos exp → expopexp | (exp) | numero Terminales No terminales

  7. Gramáticas libres de contexto … (3) • Los metasímbolos a emplear de aquí en adelante son los de uso común, sin embargo se pueden encontrar otras representaciones En este ejemplo los no terminales están en cursivas, los terminales en negritas, los metasímbolos en texto normal y las producciones de definen por → exp→exp op exp|(exp)|numero op→+|-|*|/ Otras posibles representaciones del ejemplo anterior son: exp: exp op exp |‘(’exp‘)’ | NUMERO ; op:‘+’ |‘-’ |‘*’ |‘/’ ; exp→exp op exp exp→ ( exp ) exp→numero op→ + op→ - op→ * op→ / <exp> ::= <exp> <op> <exp> | ( <exp> ) | NUMERO <op> ::= + | - | * | /

  8. Gramáticas libres de contexto … (4) • Algunas convenciones de notación sobre gramáticas libres de contexto • Son terminales: • Las primeras letras minúsculas del alfabeto (a, b, c) • Los símbolos de operador (+, -, etc.) • Los símbolos de puntuación (;, (, ), etc.) • Los dígitos (0…9) • Cadenas en negritas (id, while, etc.) • Son símbolos no terminales • Las primeras letras del alfabeto (A, B, C) • La letra S, que cuando aparece se tomará como el símbolo inicial. • Los nombres en cursivas y minúsculas (exp, op) • Las últimas letras mayúsculas del alfabeto como X, Y, Z, representan símbolos gramaticales, es decir, terminales y no terminales • Las letras griegas minúsculas, , , , representan cadenas de símbolos gramaticales. Por tanto A →  señala que existe un no terminal A a la izquierda y una cadena de símbolos gramaticales a la derecha. • Si A → 1, A → 2, … A → k, son todas producciones de A, entonces se puede escribir A → 1 | 2 … | k. • A menos que se diga otra cosa, el lado izquierdo de la primera producción es el símbolo inicial. E→E A E| ( E ) |numero A→+|-|*|/

  9. Gramáticas libres de contexto … (5) • Derivaciones y el lenguaje definido por una gramática • Las reglas gramaticales libres de contexto determinan el conjunto de secuencias sintácticamente legales de tokens para las estructuras definidas por las reglas. Expresión aritmética: (34 – 3) * 42 Secuencia de tokens: ( numero – numero ) * numero Gramática: E → E A E | ( E ) | numero A → + | - | * | / Derivaciones Producciones E E A E  E A numero  E *numero  (E)*numero  (E A E)*numero  (E A numero)*numero  (E -numero)*numero  (numero-numero)*numero E → E A E E → numero A → * E → (E) E → E A E E → numero A → - E → numero

  10. Gramáticas libres de contexto … (6) • Se dice que A    si A  es una producción y  y  son secuencias arbitrarias de símbolos gramaticales. • Uso del símbolo  •  significa deriva en un paso • * significa deriva en cero o más pasos • + significa deriva en uno o más pasos • Dada una gramática G con símbolo inicial S, se puede utilizar la relación + para definir L(G), el lenguaje generado por G. • Las cadenas de L(G) pueden contener sólo símbolos de terminales de G. • Se dice que una cadena de terminales w está en L(G) si, y sólo si, S +w. • A la cadena w se le llama frase de G. • En el ejemplo anterior (34 – 3) * 42 es una frase ya que existe una derivación a partir de la gramática dada.

  11. Gramáticas libres de contexto … (7) • Elección del no terminal a sustituir • En cada derivación se debe elegir cuál no terminal sustituir y que regla de la gramática emplear. • Algunos analizadores sintácticos eligen el no terminal más a la izquierda, esto se conoce como derivación por la izquierda Derivaciones Producciones E E A E  (E) A E  (E A E) A E  (numero A E) A E  (numero- E) A E  (numero-numero) A E  (numero-numero)* E  (numero-numero)*numero E → E A E E → (E) E → E A E E → numero A → - E → numero A → * E → numero

  12. E E A E numero + numero Árboles de derivación • Un árbol de análisis gramatical correspondiente a una derivación es un árbol etiquetado • Los nodos interiores están etiquetados por no terminales • Los nodos hoja están etiquetados por terminales • Los nodos hijos de cada nodo interno representan el remplazo del no terminal asociado en un paso de la derivación Árbol de derivación Derivación (1) E E A E  numeroAE  numero +E  numero + numero (1) (2) (3) (4) (2) (3) (4)

  13. E E A E numero + numero Árboles de derivación … (2) • Un árbol de análisis gramatical se puede considerar como una representación gráfica de una derivación que no muestra la elección relativa al orden de sustitución. • Al final de la construcción del árbol las hojas se leen de izquierda a derecha para formar una frase del lenguaje, esta frase también es conocida como el producto frontera del árbol. Árbol de derivación (1) (1) Derivación por la derecha Derivación por la izquierda E E A E  EAnumero  E+numero  numero + numero (1) E E A E  numeroAE  numero +E  numero + numero (1) (4) (3) (2) (2) (3) (4) (2) (2) (3) (3) (4) (4)

  14. E E E A E E A E num + E A E E A E * num num num num num * + Árboles de derivación … (3) • Ambigüedad • Se dice que una gramática que produce más de un árbol de derivación para alguna frase es ambigua. • Para algunos tipos de analizadores es preferible que la gramática no sea ambigua ya que necesitan un árbol exclusivo por frase. • Algunos analizadores proporcionan métodos para admitir gramáticas ambiguas pero con especificaciones adicionales que permiten la generación de un único árbol por frase. Gramática: Frase: num + num * num Árbol (deriv. Izq.) Árbol (deriv. der) E→E A E | ( E ) |num A→+ |- |* |/

  15. Especificación sintáctica de un lenguaje • La descripción de una especificación sintáctica correspondiente a un lenguaje de programación por lo general se hace mediante una gramática libre de contexto. • Las gramáticas ofrecen ventajas significativas: • Se tiene una especificación sintáctica precisa y fácil de entender. • Algunas gramáticas permiten la construcción automática de un analizador sintáctico eficiente. • Un diseño adecuado imparte una estructura útil para traducir de lenguaje fuente a objeto y detectar errores. • Permiten la adaptación a la evolución propia del lenguaje a analizar.

  16. Especificación sintáctica de un lenguaje … (2) • Generalmente una especificación debe estar libre de ambigüedad. Esto se logra reescribiendo la gramática. Ejemplo: Frase: IfE1thenif E2thenS1elseS2 Gramática ambigua: prop ifexprthenprop | ifexprthenpropelseprop | otra Gramática equivalente no ambigua: prop prop_emparejada | prop_no_emparejada prop_emparejada ifexprthenprop_emparejadaelse prop_emparejada | otra Prop_no_emparejada ifexprthenprop | ifexprthenprop_emparejadaelse prop_emparejada

  17. Especificación sintáctica de un lenguaje … (3) • Especificación de gramáticas recursivas • Una gramática recursiva por la derecha corresponde a la siguiente regla genérica: • A  A |  • Una gramática recursiva por la izquierda corresponde a la siguiente regla genérica: • A A |  • Algunas veces es conveniente transformar una gramática recursiva por la izquierda en una recursiva por la derecha equivalente, para esto se aplican las siguientes sustituciones: • A A’ • A’  A’ |  Ejemplo: E E+T | T T T*F | F F (E) | id E TE’ E’ +TE’ |  T FT’ T’ *F T |  F (E) | id

  18. Especificación sintáctica de un lenguaje … (4) • Especificación de gramáticas factorizadas por la izquierda • La idea básica es que cuando no está claro cual de dos producciones alternativas elegir para ampliar un no terminal A, se pueden escribir las producciones de A para retrasar la decisión hasta haber visto lo suficiente de la entrada para elegir la alternativa correcta. • En general, si A→1 | 2 y la entrada inicia con un a cadena no vacía derivada de , no se sabe si expandir 1 o 2. Es posible retrazar la decisión expandiendo A en A’, entonces después de analizar  se puede expandir A’ en 1 o 2. • Es decir: • A→1 | 2 • Se convierte en: • A→A’ • A’→1 | 2

  19. Análisis sintáctico descendente • Construye el árbol a partir del nodo raíz, llegando a los nodos hoja en un recorrido preorden en profundidad. • Parten del axioma inicial, y van efectuando derivaciones por la izquierda hasta obtener la secuencia de derivaciones que reconocen la frase de entrada. • Algunos tipos de análisis descendente • Por descenso recursivo • Predictivos • Predictivos no recursivos • LL(1)

  20. Análisis sintáctico descendente … (2) • El análisis sintáctico por descenso recursivo pretende: • Encontrar una derivación por la izquierda para una cadena de entrada. • Construir un árbol de análisis sintáctico para la entrada comenzando desde la raíz y creando los nodos del árbol en orden previo. • Este tipo de análisis requiere gramáticas no recursivas por la izquierda. Ejemplo: S S S Gramática: d d d c c A A c A S→cAd A→ab | a Se crea el árbol a partir de S, se empata con la hoja situada más a la izquierda etiquetada con c, el primer símbolo de w b a a Frase: Se avanza al siguiente símbolo de la frase (a) y se considera la siguiente hoja etiquetada con A. Expandiendo la primera alternativa de A. La primera hoja de A empata pero la segunda no. Se señala un fallo y se verifica si existe otra alternativa de A que no se haya probado. Al regresar a A, se debe restablecer el apuntador de la entrada. Después se empata con la única hoja de Aa, y también se empata con la hoja d. Como ya se ha producido un árbol para la frase w se anuncia el éxito. w = cad

  21. Análisis sintáctico descendente … (3) • Analizadores sintácticos predictivos • Es una variante del método de análisis sintáctico por descenso recursivo. • Se emplean cuando se tiene una gramática sin recursividad por la izquierda y factorizada por la izquierda, cumpliendo con estas dos condiciones no se necesita el retroceso. • La alternativa apropiada de la gramática se detecta con ver prácticamente el primer símbolo al que da lugar.

  22. Análisis sintáctico descendente … (4) • Análisis sintáctico predictivo no recursivo • Se puede eliminar la recursividad explicita manteniendo una pila. • Se busca la producción que debe aplicarse en una tabla de análisis sintáctico. • Modelo: Alfabeto de entrada formado por los símbolos terminales a + b $ ENTRADA Programa para análisis sintáctico predictivo X PILA SALIDA Y Z Alfabeto de pila formado por terminales y no terminales junto con el símbolo de $ delimitador de la cadena de entrada La tabla de análisis en un arreglo de la forma M[X,a] donde X representa un símbolo no terminal y a representa un símbolo terminal Tabla de análisis sintáctico M $ M[X,a]

  23. Análisis sintáctico descendente … (5) • Análisis sintáctico predictivo no recursivo … • Funcionamiento: • Al principio la pila contiene el símbolo inicial de la gramática encima de $. • Se tiene en cuenta X, el símbolo en el tope de la pila, y a, el símbolo en curso de la entrada, entonces; • Si X = a = $, el análisis se detiene exitosamente. • Si X = a $, el analizador saca X de la pila y mueve el apuntador de la entrada al siguiente símbolo. • Si X e un símbolo no terminal, entonces: • Si M[X, a] tiene una regla X→UVW, entonces saca X del tope e introduce WVU en la pila (U queda en el tope) • Si M[X, a] = error, se llama la rutina de recuperación de error

  24. Análisis sintáctico descendente … (6) • Análisis sintáctico predictivo no recursivo … • Ejemplo: Algoritmo Movimientos dada la entrada id + id * id Gramática: E → TE’ E’ → +TE’ |  T → FT’ T’ → *FT’ |  F → (E) | id Tabla M:

  25. Análisis sintáctico descendente … (7) • Análisis sintáctico predictivo no recursivo … • Se facilita la construcción de un analizador sintáctico predictivo con dos funciones asociadas a la gramática G: • PRIMERO() • Conjunto de terminales que inician cadenas derivadas de  • Si  * , entonces  también está en primero. • SIGUIENTE (A) • Conjunto de terminales a que pueden aparecer inmediatamente a la derecha de A. • S* Aa para algún  y . • Entre A y a pudieron existir derivaciones que terminaron en . Es decir si S* ABCa, y B*  y C* , entonces a esta en SIGUIENTE (A) • $ esta situado en SIGUIENTE (A) • Para calcular todos los PRIMERO (X) • Si X es terminal, entonces PRIMERO (X) es {X} • Si X → , entonces añádase  a PRIMERO (X) • Si X es no terminal y X → Y1, Y2, .. Yk, entonces poner a en PRIMERO (X) si, para alguna i, a está en PRIMERO (Yi) y Y1, Y2, .. Yi-1 * . • Para calcular SIGUIENTE (A) • Poner $ en SIGUIENTE (S), donde S es el símbolo inicial • Si hay una producción A → B, entonces todo lo que esté en PRIMERO () excepto  se pone en SIGUIENTE (B) • Si hay una producción A → B o una producción A → B, donde PRIMERO () contenga , entonces todo lo que esté en SIGUIENTE (A) se pone en SIGUIENTE (B) • Ejemplo: E → TE’ E’ → +TE’ |  T → FT’ T’ → *FT’ |  F → (E) | id PRIMERO(): SIGUIENTE (A): PRIMERO (E) = PRIMERO (T) = PRIMERO (F) = {(, id} PRIMERO (E’) = {+, } PRIMERO (T’) = {*, } SIGUIENTE (E) = SIGUIENTE (E’) = P {$, )} SIGUIENTE (T) = SIGUIENTE (T’) = {+, $, )} SIGUIENTE (F) = {*, +, $, )}

  26. Análisis sintáctico descendente … (8) • Análisis sintáctico predictivo no recursivo … • Construcción de tablas de análisis sintáctico • Para cada producción A →  de la gramática, dense los pasos 2 y 3 • Para cada terminal a de PRIMERO (), añádase A →  a M[A, a] • Si  está en PRIMERO (), añádase A →  a M[A, b] para cada terminal b de SIGUIENTE (A). Si  está en SIGUIENTE (A), añádase A →  a M [A, $] • Hacer cada entrada no definida de M sea error. SIGUIENTE (A): PRIMERO(): Gramática: SIGUIENTE (E) = SIGUIENTE (E’) = P {), $} SIGUIENTE (T) = SIGUIENTE (T’) = {+, ), $} SIGUIENTE (F) = {+, *, ), $} PRIMERO (E) = PRIMERO (T) = PRIMERO (F) = {(, id} PRIMERO (E’) = {+, } PRIMERO (T’) = {*, } E → TE’ E’ → +TE’ |  T → FT’ T’ → *FT’ |  F → (E) | id Gramática: P → iEtPP’ | a P’ → eP |  E → b

  27. Análisis sintáctico descendente … (9) • Gramáticas LL(1) • La entrada se lee de izquierda a derecha [LL(1)], las derivaciones se realizan por la izquierda [LL(1)] y se necesita conocer un token de la entrada por anticipado [LL(1)]. • Propiedades: • Ninguna gramática ambigua o recursiva por la izquierda puede ser LL(1) • G es LL(1), si y sólo si, cuando A →  |  sean dos producciones distintas de G cumplen con: • Para ningún terminal a tanto  como  derivan a la vez cadenas que comiencen con a. • A lo sumo una de  y  pude derivar en cadena vacía. • Si  * ,  no deriva ninguna cadena que comience con un terminal en SIGUIENTE (A). • Cuando se tienen dos entradas en una celda de la tabla del análisis sintáctico la gramática es ambigua, entonces se puede intentar: • Eliminar toda la recursión por la izquierda, y • Factorizar por la izquierda siempre que sea posible • Sin embargo puede darse el caso de que ni así se elimina la ambigüedad • La mayor dificultad del análisis sintáctico predictivo consiste en escribir una gramática para el lenguaje fuente tal que el analizador se pueda construir a partir de dicha gramática.

  28. Análisis sintáctico ascendente • Este tipo de análisis también es conocido como análisis sintáctico por desplazamiento y reducción • Intenta construir un árbol de análisis sintáctico para una frase de entrada que comienza por las hojas y avanza hacia la raíz. • Este proceso se puede considerar como “reducir” la frase w al símbolo inicial de la gramática. • En cada paso de reducción se sustituye una subcadena determinada que concuerde con el lado derecho de una producción por el símbolo izquierdo de dicha producción. • Si en cada caso se elige correctamente la subcadena, se traza una derivación por la derecha en sentido inverso. • Ejemplo: Gramática Frase: Reducción: abbcde aAbcde aAde aABe S S → aABe A → Abc | b B → d abbcde

  29. 2) Consumiendo el 1er token id + id   1) Al principio  id + id   Análisis sintáctico ascendente … (2) • La construcción del árbol sintáctico de abajo hacia arriba permite: • Disminuir el número de reglas mal aplicadas respecto a los analizadores descendentes con retroceso. • Ampliar el número de gramáticas susceptibles de ser analizadas respecto a las gramáticas LL(1) • Tomando en cuenta que la lectura de la frase a reconocer es de izquierda a derecha, esta se compone de dos partes: •  representa un segmento de la frase de entrada por consumir •   T* • Coincidirá siempre con algún segmento de la parte derecha de la frase de entrada • Al principio coincide con la frase completa (incluyendo el EOF) •  representa un segmento de la frase de entrada consumido •   (N  T)* • Coincidirá siempre con el resto de la frase de entrada a la cual ya se le aplicó una regla de reducción en sentido inverso. • Ejemplo: 4) aplicando la regla (2) hacia atrás y consumiendo el 2do token 3) Aplicando las reglas (5) y (4) hacia atrás Gramática: Frase: E   (1)E → T + E (2) | T (3)T → F * T (4) | F (5)F → id (6) | (E) id + id   T T F F id + id id + id  

  30. Análisis sintáctico ascendente … (3) • Operaciones en un analizador ascendente • Aceptar • Se acepta la frase   EOF • Rechazar • Se rechaza cuando la entrada no es válida • Reducir • Aplica una regla de producción hacia atrás a algunos elementos posicionados a la derecha de  • Si se tiene:   [X1 X2 … XpXp+1 … Xm] -   [am+1 … an] • Y existe una regla: Ak → Xp+1 … Xm , entonces: • Una reducción quedaría:   [X1 X2 … XpAk] -   [am+1 … an] • Por otro lado para una regla de tipo: Ak →  • Se obtiene   [X1 X2 … Xp Xp+1 … XmAk] -   [am+1 … an] • Desplazar • Consume (quita) el terminal más a la izquierda de  y ponerlo a la derecha de . • Si se tiene   [X1 X2 … Xp Xp+1 … Xm] -   [am+1 … an] • Aplicando un desplazamiento queda:   [X1 X2 … Xp Xp+1 … Xm am+1] -   [am+2 … an] • En resumen: • Mediante desplazamientos y reducciones se debe aceptar o rechazar la frase de entrada.

  31. Análisis sintáctico ascendente … (4) • Los diferentes tipos de analizadores sintácticos ascendentes se distinguen unos de otros en base a la lógica de cuando aplicar cada una de las cuatro operaciones del analizador. • Los tipos de analizadores se pueden ver en función de la gramática que son capaces de procesar, estas son: • SLR(k) • Simple Left-to-right Rightmost derivation • LALR(k) • Look Ahead Left-to-right Rightmost derivation • LR(k) • Left-to-right Rightmost derivation • Dichas gramáticas están incluidas unas en otras de la siguiente forma: • SLR(K)  LALR(K)  LR(K)

  32. Análisis sintáctico ascendente … (5) • Análisis ascendente de gramáticas LR(1) • Es capaz de reconocer prácticamente cualquier lenguaje de programación que pueda ser generado por una gramática libre de contexto. • Puede localizar un error sintáctico casi en el mismo instante en que se produce. • Permite emitir mensajes de error indicando con cierta precisión la fuente del error. • Tiene el inconveniente de hacer demasiado extensa la implementación “manual” del analizador, afortunadamente existen generadores automáticos de analizadores sintácticos LR, en particular LALR(1) el YACC.

  33. Análisis sintáctico ascendente … (6) • Estructura general de un analizador LR Xi es un símbolo de la gramática si son los estados del autómata asociado a la gramática si E Consultando el estado en la cabeza de la pila y el siguiente token en la entrada se decide que reducción efectuar o si es necesario desplazar y el siguiente estado.

  34. Análisis sintáctico ascendente … (7) • Funcionamiento del analizador LR • Suponiendo que en un momento dado el estado que hay en la cima de la pila es sm y el token actual es ai se deben aplicar reiteradamente los siguientes pasos hasta aceptar o rechazar la frase: • Consultar la entrada (sm, ai) en la tabla ACCION • El contenido de la casilla puede ser: • Aceptar, Rechazar, Reducir por A  , Desplazar • Si se acepta o se rechaza se da por finalizado el análisis • Si se desplaza se mete ai a la pila • Si se reduce, entonces la cima de la pila coincide con el consecuente  y se sustituye  por A. • Una vez hecho el paso anterior en la cima de la pila hay un símbolo, lo que dará una entrada en la tabla de GOTO. El contenido de dicha tabla se coloca en la cima de la pila.

  35. Análisis sintáctico ascendente … (8) • Por razones de espacio las tablas de ACCION y GOTO suelen tratarse como una sola dividida en dos partes: • Unas columnas comunes a ACCION y GOTO • Contienen • D-i: Desplazar y pasar al estado i • R j: Reducir por la regla de producción número j. En este caso debe aplicarse a continuación la tabla GOTO. • Aceptar • Cacillas vacías rechazan la gramática • Otras columnas solo a GOTO • Contienen números de estado a los que se transita • Casillas vacías representan un error

  36. Análisis sintáctico ascendente … (9) • Ejemplo: (1)E → T + E (2) | T (3)T → F * T (4) | F (5)F → (E) (6) | id

  37. Análisis sintáctico ascendente … (10) • Algunas consideraciones sobre el análisis LR • Recursividad • Para que la pila se mantenga de un tamaño razonable alternando entre desplazamientos y reducciones es aconsejable utilizar gramáticas recursivas por la izquierda. • Conflictos • Desplazar/Reducir (shift/reduce) • Suele darse debido a gramáticas recursivas • El programa no sabe si desplazar o reducir, ya que ambas opciones aparecen en la tabla asociada a la gramática • Reducir/Reducir (reduce/reduce) • Se debe a que la gramática no admite un análisis LR(1), es decir se necesita más de un token de preanálisis • Por lo regular estos errores se pueden eliminar retrasando la desición de reducción al último momento.

  38. Generadores de analizadores sintácticos • Clasificación de los generadores de analizadores

  39. Generadores de analizadores sintácticos … (2) • Un generador de analizadores sintácticos es un programa que convierte una especificación sintáctica de un lenguaje (en términos de una GLC) en un analizador sintáctico del lenguaje especificado. • La utilización de generadores de analizadores automáticos permite: • Reducir la complejidad y el tiempo de implementación • Aumentar la calidad del compilador • Actualizar y corregir con mayor facilidad el compilador

  40. Generadores de analizadores sintácticos … (3) • Proceso para construir un analizador sintáctico mediante un generador de analizadores sintácticos • Describir la gramática • Cada generador tiene sus propias reglas para la especificación • Procesar la gramática con el generador • El resultado es el código fuente del analizador (parser) en algún lenguaje en particular (típicamente en C) • Compilar el código fuente del analizador • Puede ser necesario hacer este paso en conjunto con la compilación de las otras fases Compilador (C, C++, etc.) Generador de parser Procesador de Lenguaje Código fuente del parser Gramática Código fuente del scanner

  41. YACC • Se trata de un generador de analizadores sintácticos • Se basa en gramáticas LALR(1) • Se apoya en LEX para el reconocimiento de tokens

  42. YACC … (2) • El entorno de yacc

More Related