La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Analizador Sintáctico

Presentaciones similares


Presentación del tema: "Analizador Sintáctico"— Transcripción de la presentación:

1 Analizador Sintáctico
Shift-reduce parser La técnica del shift-reduce parser es utilizada en varios generadores automáticos de parsers. El SR-parsing intenta construir un árbol sintáctico (parse tree) para una cadena de entrada, a partir de los elementos terminales y por eso es llamado un parser del tipo Bottom-up. El proceso consiste en reducir una cadena de entrada w hasta alcanzar el símbolo inicial de la gramática.

2 Shift-Reduce parser Definiciones Básicas
Def. Llamamos handle de una forma sentencial derecha , consistente en una producción A   , y una posición de  en donde la cadena  puede ser localizada y remplazada por A para producir la forma sentencial derecha previa, en una derivación derecha de . Esto es, si: S * Aw    w con wVt* entonces A   en la posición siguiente a  es el handle de   w .  Si la gramática no es ambigüa entonces toda forma sentencial derecha tiene exactamente un handle.

3 Shift-Reduce parser La derivación de más a la derecha en reversa, frecuentemente es llamada secuencia reductiva canónica, y es obtenida al podar el handle. Existen dos problemas para implementar el handle: (1) Como localizar el handle para podarlo. (2) Que producción elegir si existen más de una regla con el mismo lado derecho.

4 Shift-Reduce parser Un método importante para implementar el Shift-Reduce parsing, es mediante la utilización de una pila y un buffer de entrada. Podemos utilizar el símbolo $ para marcar el fondo de la pila y el final de más a la derecha del buffer. Ejemplo: Pila Buffer $ el perro ladra $ El parser opera desplazando cero o más símbolos de entrada a la pila, hasta que un handle  aparece en el tope de la misma. Entonces el parser reduce a el lado derecho de la producción correspondiente (ej. A  ).

5 Shift-Reduce parser El parser repite este ciclo hasta que algún error es detectado o la pila contiene el símbolo inicial y el símbolo $ en el buffer de entrada: Pila Buffer $ S $ Si al final se tiene la configuración mostrada, el parser termina indicando ACCEPT.  Existe un hecho que justifica la utilización de la pila: el handle siempre aparecerá eventualmente en el tope de la pila, nunca dentro.

6 Shift-Reduce parser Ejemplo: Pila Buffer Acción $ $ el $ Det
$ Det perro $ Det Noun $ NP $ NP ladra $ NP Vi $ NP VP $ S el perro ladra $ perro ladra $ ladra $ Shift Reduce Del  el Reduce Noun  perro Reduce NP  Det Noun Reduce Vi  ladra Reduce VP  Vi Reduce S  NP VP ACCEPT

7 Shift-Reduce parser Operaciones Básicas
Shift – El siguiente símbolo de la entrada es desplazado al tope de la pila. Reduce – El parser identifica que la parte derecha del handle está en el tope de la pila. Debe entonces localizar la parte izquierda del handel dentro de la pila y decidir que no terminal sustituir por el handle. Accept – El parser anuncia haber completado exitosamente el reconocimiento sintáctico. Error – El parser identifica que un error de sintaxis ha sido detectado y llama a la rutina de recuperación de errores.

8 LR-parser Ahora tenemos lo necesario para construir parsers muy eficientes, para una clase grande de gramáticas libres de contexto CFGs. Estos parsers son llamados LR, dado que reconocen la entrada de izquierda-a-derecha y construyen una right-most derivation en reversa. Ventajas Se pueden construir para reconocer virtualmente toda construcción en un lenguaje de programación, para el cual una CFG puede ser escrita. El método LR es más general que otros métodos de parsing y muy eficiente. Es posible detectar errores de sintaxis casi al momento. Desventajas Muy difícil de implementar desde cero.

9 Generación del LR-parser
El LR-parser consiste de dos partes: Una rutina controladora La tabla de parsing Dado que la rutina controladora es siempre la misma para todo LR-parser, el problema principal es generar la tabla de parsing. Tabla de parsing Generador de la Tabla Gramática

10 Generación del LR-parser
Operación del LR-parser: Buffer de Entrada a1 a2 ai an $ Pila sm $ Rutina Controladora Tabla de Parsing

11 Generación del LR-parser
Existen muchos métodos para generar la tabla de parsing. El método más simple de implementar es el llamado Simple LR-parser (SLR), que se introducirá más adelante. Como se mostró en el diagrama anterior existen tres estructuras importantes: la pila, el buffer de entrada y la tabla de parsing. La entrada se lee de izquierda-a-derecha, un símbolo a la vez. La pila contiene cadenas de la forma: s0 X1 s1 X2 s2 … Xm sm en donde sm está en el tope de la pila. Cada Xi es un símbolo de la gramática y cada si es un símbolo llamado ESTADO. Cada símbolo de ESTADO sumariza la información contenida bajo él, en la pila, y es utilizado para guiar la decisión de shift-reduce.

12 Algoritmo del LR-parser
La tabla de parsing consiste de dos partes: La función de acción del parser, llamada ACTION. La función GOTO. El programa controlador del LR-parser es siempre el mismo y opera de la siguiente manera: Determina el estado localizado en el tope de la pila, sm, y el símbolo de entrada ai en proceso. Consulta ACTION(sm , ai ). La entrada en la tabla de parsing que contiene la acción a ejecutar cuando éste se encuentra en el estado sm, para una entrada ai. La entrada ACTION(sm , ai ). puede tener uno de cuatro valores: (1) Shift s (2) Reduce A   (3) Accept (4) Error

13 Algoritmo del LR-parser
Modelo de un LR Parser Pila a1 a2 ai an $ Buffer sm Xm sm-1 Xm-1 s0 LR Parsing Program action goto

14 Algoritmo del LR-parser
La función goto(sk, ai ) de la tabla de parsing en una función de transición de estados. Toma un estado y un símbolo y genera otro estado. Esta función reconoce los prefijos viables de la gramática G. Una configuración de un LR Parser es un par cuyo primer componente es el contenido del stack y el segundo el resto de la entrada: (s0 X1 s1 X2 s2 … Xm sm, ai ai+1 … an$) Esta configuración representa la forma sentencial derecha: X1 X2 … Xm ai ai+1 … an

15 Algoritmo del LR-parser
Inicializa ip a la posición del primer símbolo de w$ Repetir Sea s el estado en el tope de la pila y a el símbolo apuntado por el ip. Si action[s, a] = shift s´ shift a y s´ al tope de la pila incrementa ip apuntando al siguiente símbolo fin sino Si action[s, a] = reduce A   pop 2*|  | símbolos de la pila supongamos que s´ es el estado en el tope de la pila push A y coloca goto[s´, A] en el tope de la pila imprime la producción A   sino Si action[s, a] = accept return sino error() fin hasta FALSE

16 Algoritmo del LR-parser
Ejemplo: Muestre las funciones de action y goto de una LE parsing table para la gramática de expresiones matemáticas que se muestra a continuación: (1) E  E + T (2) E  T (3) T  T * F (4) T  F (5) F  (E) (6) F  id Exp: id * id + id State id + action * ( ) $ goto E T F 1 2 3 s5 s6 r2 r4 s4 s7 acc r r2 r r4 4 5 6 7 r6 r r6 10 8 9 11 r1 r3 r5 s11 r r1 r r3 r r5

17 Construcción de la tabla de LR parsing
Una gramática para la cual podemos construir una tabla de parsing, llamada gramática LR, es aquella en la cual la entrada está unívocamente definida. No todas las gramáticas libres de contexto CFGs, son gramáticas LR. Sin embargo, es factible evitar aquellas que no lo son cuando se definen construcciones típicas de un lenguaje de programación. Algunos problemas: Una gramática ambigua no puede ser una gramática LR. Otro problema es cuando al tener un handle, más de una regla puede ser aplicada. El método mostrado a continuación es llamado el “simple LR” o SLR. .

18 Construcción de la tabla de LR parsing
Items LR(0) Los ítems LR(0) o ítems canónicos para una gramática G, consisten en una producción de G con un punto en algún lugar de su lado derecho. Ej. A  X Y Z genera 4 items: A  . X Y Z A  X .Y Z A  X Y. Z A  X Y Z . La producción A  genera solo el item: A  . Intuitivamente, un ítem indica que tanto de la producción hemos identificado en un punto determinado del proceso de parsing. Estos ítems se agrupan formando conjuntos que constituyen estados de un autómata finito determinístico AFN, reconociendo prefijos viables de una producción.

19 Construcción de la tabla de LR parsing
Los llamados ítems canónicos, o la colección LR(0), proveen la base para la construcción de aquella clase de parsers LR, llamados LR simples o SLR. Para la construcción de esta colección canónica para una gramática G dada, se necesitan: Una gramática aumentada Dos funciones: CLOSURE y GOTO Def. Sea G una gramática libre de contexto, con símbolo inicial S. Llamamos gramática aumentada G´ al resultado de agregar a G, el símbolo S´ y la producción S´ S.

20 Construcción de la tabla de LR parsing
CERRADURA (closure) Si I es un conjunto de ítems para una gramática G, entonces el conjunto de ítems llamado cerradura(I) se construye a partir de I a través de las reglas: (i) Para todo i  I, i  cerradura(I) (ii) Si A   . B esta en la cerradura(I), y B   es una producción, entonces agregar el ítem B .  a la cerradura de I, si no se encuentra ya adentro. Esta regla se aplica hasta que ya no se puedan agregar más items a la cerradura(I).

21 Construcción de la tabla de LR parsing
Ej. Sea la siguiente gramática aumentada: E´  E E  E + T | T T  T * F | F F  ( E ) | id Si I es un conjunto que contiene un solo ítem {E´  . E}, entonces la cerradura(I) contiene los ítems: E´ . E E  . E + T E  . T T  . T * F T  . F F  . ( E ) F  . id

22 Construcción de la tabla de LR parsing
GOTO La función Ii=GOTO( I, X), en donde I es el conjunto de ítems, X es un símbolo de la gramática, y Ii es el conjunto resultado de aplicar la cerradura a los ítems [A X . ] tales que [A. X ] es en I. Ej. Si I es el conjunto de ítems: { E´E ., E  E . + T} Entonces GOTO(I, +) consiste en: E  E + . T T  . T * F T  . F F  . ( E ) F  . id

23 Construcción de la tabla de LR parsing
Procedimiento de construcción de conjuntos de ítems LR(0) Procedure ITEMS(G´) Begin C = {cerradura({S´ . S})} Repeat Para cada conjunto de ítems Ii en C y para cada símbolo X, tal que GOTO(Ii, X) no está vacío y no se encuentra en C, haz: Agrega GOTO(Ii, X) a C. until NO se puedan agregar más conjuntos a C. end

24 Construcción de la tabla de LR parsing
Ejemplo: La colección de conjuntos canónicos de ítems de LR(0) para la gramática del ejemplo anterior: I0: E´ . E I1: E´ E . I5: F  id . I9: E  E + T . E  . E + T E  E . + T T  T . * F E  . T I6: E  E + . T T  . T * F I2: E  T T  . T * F I10: T  T * F . T  . F T  T . * F T  . F F  . ( E ) F  . ( E ) I11: F  ( E ) . F  . id I3: T  F F  . id I4: F  ( . E ) I7: T  T * . F E  . E + T F  . ( E ) E  . T F  . id T  . T * F T  . F I8: F  ( E . ) F  . ( E ) E  E . + T F  . id

25 Construcción de la tabla de LR parsing
El algoritmo nos genera la siguiente tabla: goto(0, e, 1). goto(4, id, 5). goto(0, t, 2). goto(6, t, 9). goto(0, f, 3). goto(6, f, 3). goto(0, pi, 4). goto(6, pi, 4). goto(0, id, 5). goto(6, id, 5). goto(1, +, 6). goto(7, f, 10). goto(2, *, 7). goto(7, pi, 4). goto(4, e, 8). goto(7, id, 5). goto(4, t, 2). goto(8, pd, 11). goto(4, f, 3). goto(8, +, 6). goto(4, pi, 4). goto(9, *, 7).

26 Construcción de la tabla de LR parsing
Los conjuntos canónicos para LR(0) generados por la función GOTO se presentan como un diagrama de transición de un Autómata Finito Determinístico. id id I7 * I0 I5 id id * F T I10 I2 E T T I9 I1 F F I3 “)” I11 + F I6 + “(“ I4 “(“ I8 E “(“ “(“

27 Construcción de la tabla de LR parsing
Cada estado de la figura anterior es un estado final e I0 es el estado inicial. Entonces el AFD M reconoce exactamente los prefijos viables de la gramática original. Para cualquier gramática G, la función GOTO de la colección canónica de conjuntos de ítems define un autómata finito determinístico que reconoce los prefijos viables de G. Existe una transición de A. X a AX.  etiquetada X, y existe una transición de A.B a B. etiquetada . Entonces, la cerradura(I) para conjuntos de ítems I (estados de M), es exactamente la cerradura- del conjunto de estados del autómata finito no determinístico definido.

28 Construcción de la tabla de LR parsing
Def. Decimos que el ítem A 1. 2 es válido para un prefijo viable 1, si existe una derivación: S´==>A==> 12  En general un ítem será válido para varios prefijos viables. El hecho de que A 1. 2 sea válido para 1, nos dice mucho con respecto a si debemos aplicar un shift o un reduce cuando encontremos 1 en la pila de parsing: (i) si 2 ≠ entonces 2 aún no ha sido procesado y la acción será un shift. (ii) si 2 = entonces existe una regla A1 y debemos aplicar un reduce con esta producción.

29 Construcción de la tabla de LR parsing
Teorema. El conjunto de ítems validos para cada prefijo viable , es exactamente el conjunto de ítems alcanzado desde el estado inicial, a lo largo de la ruta etiquetada  en el AFD construido a partir de la colección canónica de conjuntos de ítems con transiciones dadas por GOTO. Ejemplo: Mostrar que la cadena E+T* que nos lleva al estado I7 del AFD desarrollado, es un prefijo viable para los ítems definidos en ese estado: I7: T  T * . F F  . ( E ) F  . id

30 Construcción de la tabla de LR parsing
FIRST y FOLLOW Existen dos funciones asociadas con una gramática G, que ayudan a la construcción de un parser predictivo. Def. Sea  una cadena cualquiera de símbolos de la gramática G, definamos FIRST() como el conjunto de terminales que inician las cadenas derivadas de . Si  ==>*  , entonces la palabra vacía, , también está en FIRST(). Def. Para un noterminal A, definimos FOLLOW(A), como el conjunto de terminales a, tal que pueden aparecer inmediatamente a la derecha de A en alguna forma sentencial. Es decir, el conjunto de terminales a, tal que existe una derivación de la forma S==>* Aa . Si A puede ser el símbolo de más a la derecha de alguna sentencia, entonces $ esta en FOLLOW(A).

31 Construcción de la tabla de LR parsing
Para evaluar FIRST(X) para todos los símbolos X de la gramática, aplique las siguientes reglas hasta que ningún otro terminal o la palabra vacía  pueda ser agregado a FIRST(X): Si X es un terminal, entonces haz FIRST(X) = {X}. Si X es una producción, entonces agrega  a FIRST(X). Si X es un noterminal y XY1Y2…Yk es una producción, entonces Coloque a en FIRST(X) si para algún i, a es en FIRST(Yi), y  ocurre en todos los FIRST(Y1),…FIRST(Yi-1); esto es, Y1 ==>* … Yi-1==>* . Si  is in FIRST(Yj), para todos los j=1,2,…,k, entonces agregue  a FIRST(X). Esto es, todo lo que está en FIRST(Y1), está en FIRST(X), pero si FIRST(Y1) contiene , entonces agrege el contenido de FIRST(Y2), y así sucesivamente.

32 Construcción de la tabla de LR parsing
Computemos ahora FIRST() en donde  es una cadena de símbolos X1X2…Xn Agregue a FIRST(X1X2…Xn) todos los símbolos distintos de  en FIRST(X1). Agregue también todos los símbolos no- en FIRST(X2); sólo si  está en FIRST(X1). Agrege todos los símbolos no- de FIRST(X3); sólo si  está en FIRST(X2) y  está en FIRST(X1) y continúe así sucesivamente. Finalmente, agregue el símbolo  a FIRST(X1X2…Xn) si, para todos los i´s, FIRST(Xi) contiene a .

33 Construcción de la tabla de LR parsing
Para evaluar FOLLOW(A) para todos los noterminals A, aplique las siguientes reglas hasta que nada más pueda ser agregado a ningún conjunto FOLLOW: Coloca $ en Follow(S), en donde S es el símbolo inicial y $ la marca de fin del buffer de entrada. Si existe una producción A B, entonces todo lo que se encuentre en FIRST() excepto , se coloca en FOLLOW(B). Si existe una producción A B, o una producción A B en donde FIRST() contiene  (es decir,  ==>* ), entonces todo lo que se encuentra en FOLLOW(A) está en FOLLOW(B).

34 Construcción de la tabla de LR parsing
Ejemplo: Genere los conjuntos FIRST(X) y FOLLOW(Y) para todos los símbolos noterminales X y Y, de la gramática cuyas producciones se muestran a continuación: ETE’ E’ +TE’|  TFT’ T’*FT’|  F(E) | id

35 Construcción de la tabla de LR parsing
Solución: FIRST(E)=FIRST(T)=FIRST(F)={(,id} FIRST(E’) = {+, } FIRST(T’) = {*, } FOLLOW(E)=FOLLOW(E’)={),$} FOLLOW(T)=FOLLOW(T’)={+,),$} FOLLOW(F) = {+,*,),$}

36 Tablas de parsing SLR Algoritmo: Construcción de la tabla SLR
Input: Una gramática aumentada. Output: Las funciones acción y goto para la tabla SLR para G´. Método: 1. Construya C={I0, I1, …, In}, la colección de conjuntos de ítems de LR(0) para G´. 2. El estado i se construye a partir de Ii. Las acciones de parsing para el estado i se determinan de la siguiente manera: Si [A  . a ] esta en Ii, y goto(Ii, a) = Ij, entonces fija acción[i, a] como “shift j”. Es requisito que a sea un terminal. Si [A  .] esta en Ii, entonces fija acción[i, a] como “reduce A ” para toda a en FOLLOW(A); en donde A no puede ser S´. Si [S´ S .] es en Ii, entonces fija acción[i, $] como “aceptar” Si algún conflicto de acciones se presenta, decimos que la gramática no es una gramática SLR(1) y el algorítmo falla en producir el parser.

37 Tablas de parsing SLR Algoritmo: Construcción de la tabla SLR (cont. )
3. Las transiciones GOTO para el estado i se construyen para todos los símbolos no terminales A, utilizando la regla: si GOTO(Ii, A)=Ij, entonces GOTO[i, A]=j. 4. Todas las entradas no definidas por las reglas 2 y 3, se marcan como “error”. 5. El estado inicial del parser es aquel constituido por el conjunto de ítems conteniendo [S´ S].


Descargar ppt "Analizador Sintáctico"

Presentaciones similares


Anuncios Google