La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

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

Presentaciones similares


Presentación del tema: "Compiladores Unidad 3. Análisis Sintáctico. Contenido Funcionalidad del analizador sintáctico. Gramáticas libres de contexto. Árboles de derivación. Especificación."— Transcripción de la presentación:

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.

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. exp exp op exp | ( exp ) | numero No terminales Terminales MetasímbolosProducción

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 exp exp op exp | ( exp ) | numero op + | - | * | / 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 Otras posibles representaciones del ejemplo anterior son: ::= | ( ) | NUMERO ::= + | - | * | / exp : exp op exp | ( exp ) | NUMERO ; op : + | - | * | / ; exp exp op exp exp ( exp ) exp numero op + op - op * 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. (34 – 3) * 42Expresión aritmética: Secuencia de tokens:( numero – numero ) * numero 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 ProduccionesDerivaciones Gramática:E E A E | ( E ) | numero A + | - | * | /

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 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 ProduccionesDerivaciones

12 Á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 E EAE numero+ Árbol de derivación E E A E numero A E numero + E numero + numero Derivación (1) (2) (3) (4) (1) (2)(3)(4)

13 Á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. E EAE numero+ Árbol de derivación E E A E numero A E numero + E numero + numero Derivación por la izquierda (1) (2) (3) (4) (1) (2)(3)(4) E E A E E A numero E + numero numero + numero Derivación por la derecha (1) (2) (3) (4) (1) (2)(3)(4)

14 Á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. E E A E | ( E ) | num A + | - | * | / Frase: num + num * num Gramática: E E A num+ E E E A * Árbol (deriv. der) E E A num* E E E A + Árbol (deriv. Izq.)

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: prop if expr then prop | if expr then prop else prop | otra If E 1 then if E 2 then S 1 else S 2 Gramática ambigua: Frase: prop prop_emparejada | prop_no_emparejada prop_emparejada if expr then prop_emparejada else prop_emparejada | otra Prop_no_emparejada if expr then prop | if expr then prop_emparejada else prop_emparejada Gramática equivalente no ambigua:

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: Gramática: ScAd Aab | a Frase: w = cad S c A d 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 S c A d a b 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. S c A d a Al regresar a A, se debe restablecer el apuntador de la entrada. Después se empata con la única hoja de A a, y también se empata con la hoja d. Como ya se ha producido un árbol para la frase w se anuncia el éxito.

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: Programa para análisis sintáctico predictivo Tabla de análisis sintáctico M a+b$ X Y Z $ PILA ENTRADA SALIDA M[X,a] Alfabeto de pila formado por terminales y no terminales junto con el símbolo de $ delimitador de la cadena de entrada Alfabeto de entrada formado por los símbolos terminales 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

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 XUVW, 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: E TE E +TE | T FT T *FT | F (E) | id Gramática: Tabla M: Algoritmo Movimientos dada la entrada id + id * id

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) 1. Si X es terminal, entonces PRIMERO (X) es {X} 2. Si X, entonces añádase a PRIMERO (X) 3. Si X es no terminal y X Y 1, Y 2,.. Y k, entonces poner a en PRIMERO (X) si, para alguna i, a está en PRIMERO (Y i ) y Y 1, Y 2,.. Y i-1 *. Para calcular SIGUIENTE (A) 1. Poner $ en SIGUIENTE (S), donde S es el símbolo inicial 2. Si hay una producción A B, entonces todo lo que esté en PRIMERO ( ) excepto se pone en SIGUIENTE (B) 3. 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 1. Para cada producción A de la gramática, dense los pasos 2 y 3 2. Para cada terminal a de PRIMERO ( ), añádase A a M[A, a] 3. 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, $] 4. Hacer cada entrada no definida de M sea error. E TE E +TE | T FT T *FT | F (E) | id Gramática: 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) = {+, *, ), $} P iEtPP | a P eP | E b Gramática:

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: S aABe A Abc | b B d abbcde GramáticaFrase:Reducción: abbcde aAbcde aAde aABe S

29 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: Gramática: (1) E T + E (2) | T (3) T F * T (4) | F (5) F id (6) | (E) Frase: id + id id + id 1) Al principio 2) Consumiendo el 1 er token id + id 3) Aplicando las reglas (5) y (4) hacia atrás id + id F T 4) aplicando la regla (2) hacia atrás y consumiendo el 2 do token id + id F T E

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: [X 1 X 2 … X p X p+1 … X m ] - [a m+1 … a n ] Y existe una regla: A k X p+1 … X m, entonces: Una reducción quedaría: [X 1 X 2 … X p A k ] - [a m+1 … a n ] Por otro lado para una regla de tipo: A k Se obtiene [X 1 X 2 … X p X p+1 … X m A k ] - [a m+1 … a n ] Desplazar Consume (quita) el terminal más a la izquierda de y ponerlo a la derecha de. Si se tiene [X 1 X 2 … X p X p+1 … X m ] - [a m+1 … a n ] Aplicando un desplazamiento queda: [X 1 X 2 … X p X p+1 … X m a m+1 ] - [a m+2 … a n ] 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 descendentes 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 X i es un símbolo de la gramática s i son los estados del autómata asociado a la gramática s i 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 s m y el token actual es a i se deben aplicar reiteradamente los siguientes pasos hasta aceptar o rechazar la frase: Consultar la entrada (s m, a i ) 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 a i 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 Gramática Generador de parser Código fuente del parser Compilador (C, C++, etc.) Procesador de Lenguaje Código fuente del scanner


Descargar ppt "Compiladores Unidad 3. Análisis Sintáctico. Contenido Funcionalidad del analizador sintáctico. Gramáticas libres de contexto. Árboles de derivación. Especificación."

Presentaciones similares


Anuncios Google