La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

M.C. Juan Carlos Olivares Rojas

Presentaciones similares


Presentación del tema: "M.C. Juan Carlos Olivares Rojas"— Transcripción de la presentación:

1 M.C. Juan Carlos Olivares Rojas
Análisis Sintáctico M.C. Juan Carlos Olivares Rojas

2 Agenda Introducción a las Gramáticas libres de contexto y árboles de derivación. Diagramas de sintaxis. Precedencia de operadores. Analizador sintáctico. Analizador descendente (LL). Analizador ascendente(LR, LALR).

3 Agenda Administración de tablas de símbolos
Manejo de errores sintácticos y su recuperación Generadores de código para analizadores sintácticos: Yacc, Bison

4 Introducción a las GICs y Árboles de Derivación
Todo lenguaje posee una serie de reglas para describir los programas fuentes (sintaxis). Un analizador sintáctico implementa estas reglas haciendo uso de GICs (Gramáticas Independientes del Contexto).

5 Gramáticas Son un formalismo matemático que permite decidir si una cadena pertenece a un lenguaje dado. Se define como la cuarteta G= (N, Σ, S, P), en donde N es el conjunto de símbolos terminales, Σ es conjunto de símbolos terminales, S es el símbolo inicial (S pertenece a N) y P es un cojuntode reglas de producción.

6 Gramáticas Los símbolos no terminales (N) son aquellos que pueden seguir derivando en otros; mientras que los terminales el proceso finaliza allí. Las reglas de producción siguen el formato: αβdonde α y βpertenecen a N y Σen cualquier forma.

7 Reglas de Producción Son las reglas que permiten decidir si la cadena pertenece a un lenguaje y la estructura que lleva: SA | aB Bε AaA | bC Cε S Genera cadenas del lenguaje a*b u a

8 Tipos de gramáticas Las gramáticas más sencillas son las gramáticas regulares, debido a que no presentan anomalías de ningún tipo. Desafortunadamente este tipo de gramáticas no permiten expresar todos los lenguajes posibles y en especial los humanos por lo que se necesitan otros tipos de gramáticas. Las más utilizadas en informáticas son las libres del contexto.

9 Gramáticas Regulares Son las que se forman a través de Autómatas Finitos Deterministas y Expresiones regulares. No presentan ambiguedades. Sus reglas de producción son del tipo: αβ donde α pertenece a N y β pertenece a (Σ)* N?

10 GICs Son aquellas G cuya reglas de producción son de la forma: αβ, en donde αpertenece a N y βpertenece (N u Σ)* Las ventajas de uso de GICs son: Proporcionan una estructura sintáctica precisa y fácil de comprender. Proporciona al lenguaje fuente una estructura adecuada para la generación del código. Por medio de las GICs es fácil construir analizadores sintácticos.

11 GICs Hay que revisar que la gramática no sea inherentemente ambigua para poder eliminar esa ambigüedad o rediseñar la gramática sin anomalías. Algunas formas de eliminar esa ambigüedad es utilizando técnicas como algoritmos CYK y las formas normales de Chomsky(FNCh) y Greibach(FNG).

12 Ejemplo de GICs Expresiones válidas en lenguajes C:
expr  (expr) | - expr | expr op expr | VAR | NUM Error sintáctico: cuando la secuencia de componentes léxicos no puede ser generada por la gramática del lenguaje fuente.

13 Ejemplos de GICs Declaración de variables en C:
Decl TIPO listavar PYC listavarvar | var COMA listavar varID | ASTER var dimensionCI ENTERO CD | CI ENTERO CD dimension

14 Gramática de un if prop if expr then prop | if expr then prop else prop | ε exprtermino oprel termino | termino termino id | num oprel  < |>|=|<=|<>|>=| idletra (letra | digito)*

15 Gramática de un if num digito+ (.digito+)? (E(+|-)? digito+)?
Eb delim+ Delim blanco | tab | linenueva

16 Jerarquía de Chomsky Las otras dos gramáticas en las cuales clasificó Chomsky (GR tipo 3, GIC tipo 2) son las gramáticas sensible al contexto (tipo 1, donde |α| < |β|, donde α y β pertenecen a (Σ u N)* salvo ε) y las gramáticas del tipo 0 o sin restricciones, las cuales sus reglas de producción pueden ser de cualquier tipo.

17 Árboles de Derivación Es la representación gráfica de la derivación de una cadena. Se crea utilizando el símbolo inicial como la raíz, los símbolos N representan nodos del árbol y los símbolos Σ las hojas del árbol. A través de los árboles de derivación se puede verificar la sintaxis de un lenguaje así como comprobar el significado de las palabras.

18 Árboles de Derivación Si para la misma cadena existen dos o más árboles de derivación la gramática es ambigua.

19 BNF La Forma Backus-Naur es una meta-sintaxis; es decir, una sintaxis para representar sintaxis. Es un estándar para representar lenguajes. Los paréntesis triangulares < y > sirven para indicar los símbolos no terminales. La barra vertical | para representar Ó

20 BNF La doble flecha  indica las derivaciones
::= indica las producciones [] indican elementos opcionales {} indican términos repetitivos

21 BNF <postal-address> ::= <name-part> <street-address> <zip-part> <name-part> ::= <personal-part> <last-name> <opt-jr-part> <EOL> | <personal-part> <name-part> <personal-part> ::= <first-name> | <initial> "."

22 BNF <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL> <zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL> <opt-jr-part> ::= "Sr." | "Jr." | <roman-numeral> | ""

23 EBNF Extended Backus Naur Form es una metasintaxis ampliamente utilizada que mejora a su antecesor BNF. Ha cambiado la forma de realizar la especificación de las reglas de producción de la gramática. La motivación para usar EBNF radica que con BNF los elementos repetitivos necesitan de más reglas de producción para trabajar.

24 EBNF Las reglas de producción pueden contener espacios.
Los símbolos terminales se representan con comillas dobles (“”) cuando representan un símbolo del alfabeto y comillas simples (‘’) para representar cadenas El operador de producción ahora es el símbolo de igual (=)

25 EBNF Se recomienda escribir los símbolos no terminales en minúsculas.
Cada regla de producción termina con el símbolo de punto y com (;). El operador | indica una alternativa de regla de producción.

26 EBNF digito sin cero = “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9”; digito = “0” | digito sin cero Las comas (,) sirven para separar tanto terminales como no terminales de las reglas de producción. Las llaves ({}) indican elementos repetitivos (operador estrella: *)

27 EBNF natural = digito sin cero, {digito};
Los corchetes ([]) se manejan para elementos auxiliares. entero = “0” | [“-”], natural Entre símbolos de interrogación (?) se pueden poner símbolos especiales.

28 EBNF Un espacio en blanco se define como: espacio = ? US-ASCII character 32 ?; Se pueden poner comentarios con los símbolos (* comentario *) Los paréntesis “(” y “)” se utilizan para agrupar símbolos. El símbolo “-” sirve para expresar excepciones.

29 EBNF Se utiliza “*” para indicar repeticion, por ejemplo regla = “A”;
repetición = 3 * aa, “B”; Si se deriva la regla de producción repetición la cadena generada sería: AAAB

30 EBNF Se pueden anidar operadores como *, {} y [] para lograr cualquier tipo de repetición. Tanto BNF como EBNF pueden determinar cualquier tipo de gramática, sencillamente EBNF permite simplificar y tener menos ambigüedad en la metasintaxis.

31 Diagramas de Sintaxis Es otra forma (al igual que los árboles de derivación) de especificar gramáticas de cualquier tipo en especial de tipo 2. La característica de este esquema es que permite ver las derivaciones al instante de que ocurren. Es una forma visual de representar la gramática de un lenguaje.

32 Diagramas de Sintaxis

33 Precedencia de Operadores
La precedencia de operadores es de vital importancia en el proceso de análisis sintáctico ya que nos representará la forma en que debe construirse el árbol de derivación. En aritmética existen prioridades, por ejemplo: * y / tienen preferencia sobre + y -. () indican la máxima prioridad.

34 Precedencia de Operadores
La instrucción a = b + c / 2 en la mayoría de los lenguajes no se evalúa de la forma a = (b + c) /2, sino de la forma a = b + (c/2) La forma de evaluación depende de cómo se construyan los operadores, ya sea en infijo, postfijo o prefijo. Las operaciones se realizan de abajo hacia arriba.

35 Precedencia de Operadores
Podría pensarse que esta parte corresponde a la parte semántica dado que el resultado de las operaciones depende del orden. Al hablar de orden se hace referencia al aspecto sintáctico y gramatical. Las reglas gramaticales de mayor prioridad deben de definirse primero. ¿Cómo se diferencia el operador “-” binario del unario?

36 Tarea UML es el lenguaje de modelado unificado. Tiene la característica principal de ser visual y extensible. Al ser un lenguaje formal debe de contener una estructura bien definida, en este caso vocabulario (alfabeto) bien definido y reglas gramaticales para definir el orden o sintaxis de los elementos así como una semántica o significado propio.

37 Tarea Realizar un trabajo de investigación que contenga la definición de una gramática visual y sus características. Además, se debe de investigar de un diagrama UML en particular (versión 2.0 o superior) los elementos de léxico, sintaxis y semántica. Se deberá preseleccionar (orden en que lleguen los correos) el tipo de diagrama.

38 Tarea La tarea se entregará el martes 3 de noviembre.
La tarea es individual. Se recomienda consultar libros de UML sólo se deberá tener cuidado de encontrar como la sintaxis y semántica del documento (se puede utilizar una herramienta de diagramación pero quizás no cumpla con el estándar).

39 Analizador Sintáctico
Un analizador sintáctico (Parser) es un programa que reconoce si una o varias cadenas de caracteres forman parte de un determinado lenguaje. Los lenguajes habitualmente reconocidos por los analizadores sintácticos son los lenguajes libres de contexto.

40 Analizador Sintáctico
Los analizadores sintácticos fueron extensivamente estudiados durante la década de 1970, detectándose numerosos patrones de funcionamiento en ellos, cosa que permitió la creación de programas generadores de analizadores sintácticos a partir de una especificación de la sintaxis del lenguaje, tales como YACC, GNU bison y javacc.

41 Análisis Sintáctico Es el proceso de determinar si una cadena dada puede ser generada por una gramática. Los analizadores sintácticos de lenguajes de programación suele hacerse de izquierda a derecha, viendo un componente léxico a la vez.

42 Análisis Sintáctico

43 Análisis Sintáctico Los analizadores pueden clasificarse dependiendo de la forma en como se construyen los nodos del árbol de derivación sintáctico: ascendentes y descendentes. El análisis sintáctico impone una estructura jerárquica. Sea la expresion: id1 := id2 + id3 * 60

44 Análisis Sintáctico Dicha expresión queda expresada en un árbol sintáctico de la siguiente forma: := id1 + id2 * id3 60

45 Tipos de Analizadores Sintácticos
LL (left toleft) leen la cadena de izquierda a derecha y derivan por la izquierda LR (lefttoright) SaA AaBbC Bb Cc

46 Analizador Descendente
Existen diferentes métodos de análisis sintáctico. La mayoría caen en una de dos categorías: ascendentes y descendentes. Los ascendentes construyen el árbol desde las hojas hacia la raíz. Los descendentes lo hacen en modo inverso. Un analizador ampliamente utilizado es el llamado de análisis predictivo descendente recursivo que es muy sencillo.

47 Analizador Descendente
Derivación izquierda: SAaaBbCaabbCaabbc(1234) SaAaaBbaaBbcaabbc(3421) LL(k) traductores “top-down” Un análisis anticipado de k caracteres (predictivo de caracteres)

48 Analizador Descendente
SaS | cA AbA | cB | ε BcB |a | ε Construir la cadena acbb: SaS o ScA; al anticipar el primer símbolo.

49 Analizador Descendente

50 Administración de la Tabla de Símbolos
La tabla de símbolos se crea durante la fase de análisis léxico a través de los componentes léxicos, pero en el proceso de análisis sintáctico sufren algunas modificaciones. Generalmente se agregan valores de tipo y significado para el análisis sintáctico.

51 Manejo de errores sintácticos y su recuperación
Si los traductores tuvieran que procesar programas correctas el proceso de implantación se simplificaría mucho. ¿Cómo debe de responder un compilador de pascal a un código Fortran? Ningún método de recuperación de errores resuelve todos los problemas

52 Tipos de Errores Léxicos: como escribir mal un identificador, palabra clave u operador. Sintácticos: como una expresión aritmética con paréntesis no equilibrados. Semánticos: como un operador aplicado a un operando incompatible. Lógicos: como una llamada infinitamente recursiva.

53 Tipos de Errores La mayoría de los errores se centra en la fase de análisis sintáctico. El manejador de errores debe: Informar la presencia de errores con claridad y exactitud. Brindar una posible solución al problema.

54 Administrador de Errores
Recuperar de cada error con la suficiente rapidez como para detectar errores posibles. No debe retrasar de manera significativa el procesamiento de programas correctos. Debe indicar la línea del error y algún mensaje informativo

55 Estrategia de Recuperación de Errores
Modo Pánico Nivel de Frase Producciones de error Corrección global

56 Recuperación en Modo Pánico
Es el más sencillo de implantar. El analizador sintáctico desecha componentes léxicos hasta encontrar un carácter de sincronización. Estos caracteres son el punto y como (;) entre otros. En C/Java es muy común este tipo de errores.

57 Recuperación en Modo Pánico
int a.b,c; struct c { …. } main() { int a;

58 Recuperación a nivel de frase
Esta técnica utiliza una corrección de caracteres adyacentes, ya sea por inserción, eliminación o intercambio. Esta técnica permite sustituir “,” por “;”, etc. Son traductores que corrigen errores. Desafortunadamente para muchos casos no aplican por lo que no se utilizan demasiados.

59 Producción de Errores Se pueden generar gramáticas para generar producciones de error y así de esta forma seguir con el proceso. La dificultad radica en el sentido de encontrar esas reglas gramaticales para generar error. En algunos casos sería inclusiva más extensa que la gramática del propio lenguaje. for(i<3, a<10; i++)

60 Corrección Global Idealmente, sería recomendable que un traductor hiciera el mínimo de cambios para procesar una entrada inválida. Este algoritmo genera menores costos globales para realizar cambios. El problema radica en que el implementar estas estrategias son muy costosas en tiempo y espacio.

61 Generadores de Analizadores Sintácticos: YACC & Bison
YACC (YET ANOTHER COMPILER- COMPILER): es una herramienta que nos permite validar lenguajes a través de la especificación de reglas gramaticales. Esta fuertemente relacionado con Lex para la identificación de caracteres extraños.

62 YACC La forma de trabajar con yacc es la siguiente:
Analizador.y (#include“lex.yy.c”)  bison  analizador.c (y.tab.c)  gcc analizador $gcc analizador.c –o analizador –lfl Se necesita modificar el valor de retorno en el analizador léxico para trabajar de manera conjunta.

63 Estructura de un programa en YACC/BISON
%{ Declaraciones globales C }% Declaraciones bison %% Gramáticas Nombre:prod1|prod2|…|prodn; Código auxiliar C

64 Consejos Todo lexema debe ser un entero: #define VAR 200 (256)
return (VAR); Gramática vacía: prod1| prod2| ; Es sumamente sensible a los separadores.

65 Consejos Yacc no es una herramienta que se caracterice por optimizar gramáticas. Por lo tanto, se pueden presentar algunos problemas de ambigüedad: Reduce/Reduceambigüedad infinita Shift/Reduce A continuación se muestran algunos ejemplos de Yacc.

66 Analizador.lex %{ #include“ytab.h” }% sp [\n\r\t] if [i][f] %% {if} {return(IF);} “(” {return(PI); } . return(ERROR);

67 ytab.h /*Se deben colocar todos los tokens*/ #define IF 1 #define

68 Analizador.y %{ #include“lex.yy.c” }% %token IF PI PD LLI LLD
%token ID NUM OPREL OPLOG %% programa: linea programa | ; Linea: iflinea | ; if: ifPI condicionPD LLI campo LLD ;

69 Analizador.y .: {printf(“Error sintáctico”);} %%
main(intargc, char*argv[]) { FILE *f = fopen(argv[1], “r”); yyin= f; while(yyparse()); fclose(f); }

70 Compilación con Yacc $flexanalizador.lex $bisonanalizador.y
$gccanalizador.c –o analizador –lfl yytextcomponente léxico yyinflujo de entrada yylinenolínea de error

71 Manejo de errores con Yacc
%% yyerror() { printf(“Error sintáctico en %dlinea”, yylineno); } En general, el manejo de errores se realiza de forma trivial. De lo contrario tendría que ser más específico.

72 CUP Es el generador de analizadores sintácticos más populares para Java. Al igual que con lex, los archivos de JLEX deben de modificarse para poder trabajar en conjunto. Se deben devolver valores de la clase sym, además de incluir la biblioteca de cup. A continuación se muestra un ejemplo de un analizador sintáctico de expresiones.

73 CUP import java_cup.runtime.SymbolFactory; %% %cup %class Scanner %{ public Scanner(java.io.InputStream r, SymbolFactory sf){ this(r); this.sf=sf; }

74 CUP private SymbolFactory sf; %} %eofval{ return sf.newSymbol("EOF",sym.EOF); %eofval} %% ";" { return sf.newSymbol("Semicolon",sym.SEMI); } "+" { return sf.newSymbol("Plus",sym.PLUS); } "*" { return

75 CUP sf.newSymbol("Times",sym.TIMES); } "(" { return sf.newSymbol("Left Bracket",sym.LPAREN); } ")" { return sf.newSymbol("Right Bracket",sym.RPAREN); } [0-9]+ { return sf.newSymbol("Integral Number",sym.NUMBER, new Integer(yytext())); } [ \t\r\n\f] { /* ignore white space. */ } . { System.err.println("Illegal character: "+yytext()); }

76 CUP En cup se definen las gramáticas en una sintaxis muy similar a BNF. El archivo define algunas secciones para código auxiliar y definición de terminales y no terminales. Para compilar se debe de incluir en el path la ruta de la biblioteca de cup. El archivo generado por cup se denomina parser.java y sym.java que se compilan con el lexer.java

77 CUP import java_cup.runtime.*; parser code {: public static void main(String args[]) throws Exception { SymbolFactory sf = new DefaultSymbolFactory(); if (args.length==0) new parser(new Scanner(System.in,sf),sf).parse(); else new parser(new Scanner(new java.io.FileInputStream(args[0]),sf),sf).parse();

78 CUP } :} terminal SEMI, PLUS, TIMES, LPAREN, RPAREN;
terminal Integer NUMBER; non terminal expr_list, expr_part; non terminal Integer expr; precedence left PLUS; precedence left TIMES;

79 CUP expr_list ::= expr_list expr_part | expr_part; expr_part ::= expr:e {: System.out.println(" = "+e+";"); :} SEMI; expr ::= NUMBER:n {: RESULT=n; :} | expr:l PLUS expr:r {: RESULT=new Integer(l.intValue() + r.intValue()); :} | expr:l TIMES expr:r {: RESULT=new Integer(l.intValue()

80 CUP * r.intValue()); :} | LPAREN expr:e RPAREN {: RESULT=e; :} ;

81 Examen Escrito: 70% Próxima unidad se juntará análisis sintáctico y semántico del ensamblador de Java. Etiquetas para unidad 5: aconst_null, aload, bipush, breakpoint, cmpgd, cmpldconst, iadd, iaload, iand, iastore, iconst, idiv, if_acmpeq, if_acmpne, if_icmpeq, if_icmpge, if_icmpgt, if_icmple,

82 Examen if_icmplt, if_icmpne, ifeq, ifge, ifgt, ifle, iflt, ifne, ifnonnull, ifnull, iinc, iload, iload_<n>, imul, ineg, ishl, ishr, istore, istore_<n>, isub, iushr, ixor, jsr, jsr_w.

83 Pendientes Práctica 9: viernes programa para reconocer if en yacc/cup.

84 Referencias Aho, Sethi, Ullman. Compiladores Principios, técnicas y herramientas Ed. Addison Wesley. Beck,. Software de Sistemas, Introducción a la programación de Sistemas Ed. Addison-Wesley Iberoamericana. Kenneth C. Louden. Construcción de compiladores Principios y práctica. Ed. Thomson.

85 Referencias EBNF, Wikipedia la Enciclopedia Libre, Recuperado en octubre de 2007.

86 ¿Preguntas?


Descargar ppt "M.C. Juan Carlos Olivares Rojas"

Presentaciones similares


Anuncios Google