Documente Academic
Documente Profesional
Documente Cultură
Vice-Rectorado Acadmico
Proyecto de Carrera: Ingeniera en Informtica
Lenguajes y Compiladores 2016-I
Seccin 2
Analizador Sintctico
PROFESOR:
INTEGRANTES: Flix Mrquez.
Capella
Genghis V-19800720
Castro Jhon V-18579925
Fernndez Carlos V-20219273
Morales Nstor V-19995576
Qu es el analizador sintctico
Es la fase del analizador que se encarga de chequear el texto de entrada en base a
una gramtica dada. Y en caso de que el programa de entrada sea vlido, suministra el
rbol sintctico que lo reconoce.
En teora, se supone que la salida del analizador sintctico es alguna
representacin del rbol sintctico que reconoce la secuencia de tokens suministrada
por el analizador lxico.
En la prctica, el analizador sintctico tambin hace:
Acceder a la tabla de smbolos (para hacer parte del trabajo del analizador
semntico).
Chequeo de tipos (del analizador semntico).
Generar cdigo intermedio.
Generar errores cuando se producen.
En definitiva, realiza casi todas las operaciones de la compilacin. Este mtodo
Tipos de Anlisis
De la forma de construir el rbol sintctico se desprenden dos tipos o clases de
analizadores sintcticos. Pueden ser descendentes o ascendente
Objetivo: El mtodo parte del axioma inicial y aplica todas las posibles
reglas al no terminal ms a la izquierda.
Mediante este rbol se pueden derivar todas las posibles sentencias reconocibles
por esta gramtica y el objetivo de este algoritmo es hacer una bsqueda en este rbol de
la rama que culmine en la sentencia a reconocer. El mecanismo funciona mediante una
Para demostrar que permite representar las mismas gramticas que la BNF, se hace por
induccin sobre las operaciones bsicas de BNF:
De esta forma todos los posibles caminos desde el inicio del grafo hasta el final,
representan formas sentenciales vlidas. En todo diagrama de Conway hay un origen y un
destino.
Ejemplo: Yuxtaposicin
Ejemplo:
La cadena a reconocer, junto con un apuntador, que nos indica cual es el token
actual.
Una pila de smbolos (terminales y no terminales)
Una tabla asociada de forma unvoca a una gramtica.
En este ejemplo no vamos a ver como calcular dicha tabla. La cadena de entrada acabar
en el smbolo $, que consideramos como si fuese un EOF (End Of File - Fin de Fichero).
Sea X el elemento encima de la pila, y a, el apuntado en la entrada. El algoritmo consiste
en:
1.- Si X = a = $ entonces ACEPTAR.
2.- Si X = a g $ entonces
- se quita X de la pila
- y se avanza el apuntador.
3.- Si X T y X g a entonces RECHAZAR.
4.- Si X N entonces consultamos la entrada M[X,a] de la tabla:
- M[X,a] es vacia: RECHAZAR.
- M [X,a] no es vacia, se quita a X de la pila y se inserta el
consecuente en orden inverso
- M [X,a] no es vacia, se quita a X de la pila y se inserta el
consecuente en orden inverso.
Ejemplo: Si M[X,a] = {X UVY}, se quita a X de la pila, y se meten UVY en orden
inverso
5.- Ir al paso 1.
Una vez aplicada una regla, no ser desaplicada por ningn tipo de retroceso.
El algoritmo comienza con $ y con el axioma inicial metidos en la pila.
Ejemplo:
Ejemplo:
Sencillo de implementar.
Muy eficiente.
Ejemplo:
Analizadores LR
Anlisis sintctico LR(k); la L es por el examen de la entrada de izquierda a
derecha (en ingls, left-to-right), la R por construir una derivacin por la derecha (en
ingls, rightmost derivation) en orden inverso, y la k por el nmero de smbolos de entrada
de examen por anticipado utilizados para tomar las decisiones del anlisis sintctico.
Cuando se omite, se asume que k, es 1. El anlisis LR es atractivo por varias razones.
Pueden reconocer la inmensa mayora de los lenguajes de programacin que puedan ser
generados mediante gramticas de contexto-libre. El mtodo de funcionamiento de estos
analizadores posee la ventaja de localizar un error sintctico en el mismo instante que se
produce con lo que se adquiere una gran eficiencia de tiempo de compilacin frente a
procedimientos menos adecuados como puedan ser los de retroceso.
mtodos si consiguen.
El segundo mtodo, llamado LR cannico, es el ms poderoso y costoso.
El tercer mtodo, llamado LR con examen por anticipado (LALR, en
ingls), est entre los otros dos en cuanto a poder y costo. El mtodo LALR
funciona con las gramticas de la mayora de los lenguajes de
programacin y, con un poco de esfuerzo, se puede implantar en forma
eficiente.
a * ( a + a) = id * (id + id)
(Suponemos que el estado s0 queda representado por 0).
Y no se podra seguir a partir de aqu porque en la gramtica no existe ninguna regla a esa
combinacin de smbolos. Para que no se presente este problema, cada vez que vaya a
hacer una reduccin, el analizador sintctico ascendente tiene que saber reconocer las
reglas de produccin, que no bloqueen el anlisis y produzcan el retroceso (backtracking).
La gramtica LR posee la propiedad de realizar el anlisis ascendente sin retroceso.
Opciones y declaraciones
La primera parte del archivo es el bloque donde se importarn los paquetes
que se van a utilizar para nuestro analizador, es decir, si en nuestro programa
utilizaremos componentes del paquete til debemos importar aqu dicho paquete:
import java.util.*;
Luego sigue un par de signos de porcentaje (%) para indicar que empezar
la definicin del bloque de configuracin del analizador. El bloque de
configuracin se define por el conjunto de parmetros que se especifican en el
archivo para decirle a nuestro a analizador como se debe comportar, cada
parmetro empieza con el smbolo % y se escribe solo uno por lnea, es decir, uno
de bajo del otro.
%unicode
%line
%column
Cdigo de usuario
En el siguiente fragmento de cdigo podremos incluir cdigo Java el cual
podemos utilizar en el analizador, cabe notar que el cdigo que aqu se escriba ser
incluido sin ninguna alteracin al resultado final del analizador, dicho fragmento
ira enmarcado entre las etiquetas%{ al inicio del cdigo y %} al final del mismo.
%{
public static void escribir(String cadena)
{
System.out.println(cadena);
}
%}
Reglas lexicogrficas
El siguiente fragmento formar parte esencial dentro del funcionamiento del
Variable = [:jletter:][:jletterdigit:]*
Si = Si
Entero = 0 | [1-9][0-9]*
condicin inicial esto quiere decir que podr ser evaluada en cualquier estado lxico que
se encuentre el escner.
<YYINITIAL>"Inicio" {System.out.println("Palabra Inicio")}
Dos mtodos importantes que se utilizan en el cdigo de accin de una expresin
regular son yybegin y yytext. yybegin se utiliza para decirle al escner que cambie el
estado lxico, por ejemplo: yybegin(CADENA), esto indica al escner que a partir del
llamado de esa funcin el escner se encontrar en el estado lxico CADENA, por otro
lado, tenemos yytext la cual devuelve la entrada la cual coincidi con la respectiva
expresin regular.
Reglas lxicas
Las reglas lxicas contienen un conjunto de expresiones regulares y acciones.
Definicin de la sintaxis
La sintaxis de las reglas lxicas de JFlex esta descrita por la siguiente gramtica:
LexicalRules ::= Rule+
Rule ::= [StateList] ['^'] RegExp [LookAhead] Action
| [StateList] 'EOF' Action
| StateGroup
StateGroup ::= StateList '{'Rule+ '}'
StateList ::= '<' Identifier (',' Identifier)* '>'
LookAhead ::= '$'| '/'RegExp
| '"'StringCharacter+ '"'
| Character
PredefinedClass ::= '[:jletter:]'
| '[:jletterdigit:]'
| '[:letter:]'
| '[:digit:]'
| '[:uppercase:]'
| '[:lowercase:]'
| '.'
La gramtica usa los siguientes smbolos terminales:
JavaCode
Es una secuencia que describe las especificaciones del lenguaje Java.
Number
Un nmero entero no negativo.
Identifier
Una secuencia de letras seguidas de cero o ms letras, dgitos o rallas al pie (_).
Character
Una secuencia de caracteres que no sean ninguno de los siguientes:
|(){}[]<>n.*+?^$/"!
StringCharacter
Una secuancia de caracteres que no sean ninguno de los siguientes:
\ "
Operadores en las expresiones regulares
Ahora se mostrarn los operadores que se pueden utilizar en la definicin de
a | b Unin
Es una expresin regular que encuentra todas las entradas que sean vlidas para
a b.
a b Concatenacin
Es una expresin regular que encuentra todas las entradas que sean vlidas para a
seguida de b.
a* Cerradura de Kleene
Es una expresin regular que encuentra todas las entradas que sean vlidas para
cero o ms repeticiones de a.
a+ Iteracin
Es una expresin regular que encuentra todas las entradas que sean vlidas para
a? Opcin
Es una expresin regular que encuentra todas las entradas que sean vlidas para
!a Negacin
Es una expresin regular que encuentra todas las entradas que sean vlidas para
a{n} Repeticin
Es una expresin regular que encuentra todas las entradas que sean vlidas para
exactamente n repeticiones de a.
a{n}{m}
Es una expresin regular que encuentra todas las entradas que sean vlidas para
entre n y m repeticiones de a.
a
Es una expresin regular que encuentra todas las entradas que coincidan
exactamente con a.
Precedencia de operadores
JFlex usa la siguiente precedencia de operadores estndar para expresiones regulares:
regular.
int yylength() Devuelve el tamao de la cadena que coincidi con la respectiva
expresin regular.
char yycharat(int pos) Devuelve el carcter que se encuentra en la posicin pos de
en donde el cdigo que se incluir en el archivo parser ser el que esta incluido entre las
etiquetas {: :}.
Luego de la declaracin del cdigo de accin se puede hacer la declaracin
opcional del cdigo del analizador el cual se agregar directamente a la clase parser, este
cdigo es til cuando se va a personalizar algunos de los mtodos del analizador:
parser code {: ... :};
Otra vez, el cdigo que se copia dentro de la clase parser es el que se encuentra entre las
etiquetas {: :}.
La siguiente declaracin opcional es:
init with {: ... :};
Esta declaracin provee el cdigo que se va a ejecutar antes de que el analizador llame al
primer token. Esta declaracin es usada usualmente para inicializar el escner con tablas y
cierto tipos de datos que luego podrn ser utilizados por las acciones semnticas. En este
caso, el cdigo se escribir en un metodo void que se encuentra dentro de la clase parser.
La siguiente declaracin opcional permite indicar al analizador como debe preguntar por
el siguiente token del escner.
scan with {: ... :};
Al igual que la declaracin init el cdigo de este bloque se incluye en un mtodo dentro de
la clase parser, de cualquier forma este mtodo deber devolver un objeto de tipo
java_cup.runtime.Symbol, en consecuencia con esto el cdigo que sea incluido dentro de
la declaracin scan with deber devolver un objeto de este tipo.
la parte derecha de alguna produccin. Para efectos de especificar al analizador que tipo
de objeto es cada smbolo terminal o no terminal, se hace de la siguiente forma:
terminal Nombre_de_la_clase simbolo1, simbolo2, ... ; terminal simbolo1, simbolo2, ... ;
non terminal Nombre_de_la_clase simbolo1, simbolo2, ... ; non terminal simbolo1,
simbolo2, ... ;
donde Nombre_de_la_clase es la clase a la que pertenece el objeto simbolox.
parser name: Hace que el archivo del analizador se llame name en vez de parser
symbols namr: Hace que el archivo de smbolos se llame name en vez de sym
expect
nowarn: Evita que analizador arroje mensajes de prevencin o alertas (En ingles:
warnings)
nosummary: Normalmente, el sistema imprime una lista con cierto tipo de cosas
como los terminales, no terminales, estados del analizador, etc. al final de cada
ejecucin. Esta opcin elimina esta funcionalidad.
progress: Esta opcin causa que el sistema imprima pequeos mensajes indicando
varias partes del proceso de la creacin del analizador.
dump: Esta opcin causa que el sistema imprima pedazos de la gramtica, estados
del analizador y tablas de anlisis con el en de resolver conflictos en el anlisis.
time: Causa que el sistema muestre detalles de las estadisticas sobre los tiempos
resultantes del analizador. Muy til para futuros mantenimientos y optimizacin
del analizador.
version: Causa que CUP imprima la versin actual con la que se esta trabajando.
%}
%eofval{
{System.exit(0);}
%eofval}
%line
%char
%state COMENTARIO
EspacioOTerminador = [\ \t\f\r|\n|\r\n]
Digito = [0-9]
Letra = [a-zA-Z]
INTAUX = ((("+"|"-")?({Digito})+)(("Ox(OX)"|"0")?))
ENTERO =((("+"|"-")?({Digito})(({Digito})*))(("Ox(OX)"|"0")?))
INT = ({ENTERO})
SEMI = ";"
COMMA = ","
TYPE = "int"
BINARYOP = ("+"|"-"|"*"|"/"|"%")
UNARYOP = ("++"|"--")
LOGICOSOP = (">"|">="|"<"|"<="|"=="|"!="|"&&"|"||"|"!")
ASIGOP = ("="|"+="|"-="|"*="|"/="|"%=")
LP = "("
RP = ")"
LB = "["
RB = "]"
LC = "{"
RC = "}"
STRUCT = "struct"
RETURN = "return"
IF = "if"
ELSE = "else"
BREAK = "break"
CONT = "continue"
FOR = "for"
ID = ({Letra}({Letra}|{Digito}|"_")*)
%%
<YYINITIAL> {TYPE}
{
System.out.println ("TYPE: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {BINARYOP}
{
System.out.println ("BINARYOP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {UNARYOP}
{
System.out.println ("UNARYOP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {LOGICOSOP}
{
System.out.println ("LOGICOSOP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {ASIGOP}
{
System.out.println ("ASIGOP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {LP}
{
System.out.println ("LP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {RP}
{
System.out.println ("RP: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {LB}
{
System.out.println ("LB: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {RB}
{
System.out.println ("RB: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {LC}
{
System.out.println ("LC: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {RC}
{
System.out.println ("RC: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {SEMI}
{
System.out.println ("SEMI: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {COMMA}
{
System.out.println ("COMMA: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {STRUCT}
{
System.out.println ("STRUCT: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {RETURN}
{
System.out.println ("RETURN: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {IF}
{
System.out.println ("IF: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {ELSE}
{
System.out.println ("ELSE: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {BREAK}
{
System.out.println ("BREAK: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {CONT}
{
System.out.println ("CONT: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {FOR}
{
System.out.println ("FOR: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {ID}
{
System.out.println ("ID: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> {INT}
{
System.out.println ("INT: " + yytext() + " en <lin " + yyline + " col " +
yychar + ">");
}
<YYINITIAL> [\n\r]+
{
yychar = 0;
}
<YYINITIAL> {EspacioOTerminador}+
{}
<YYINITIAL> "/*"
{
yybegin(COMENTARIO);
}
<COMENTARIO> [^"*/"]
{}
<COMENTARIO> "*/"
{
yybegin(YYINITIAL);
}
<YYINITIAL> .
{
System.out.println("Error lexico en " + yyline + " " + yychar +
" no se reconoce " + yytext());
yychar = 0; }
action code{:
public void ImprimeValor(String str){
System.out.println("el valor del token"+str) ;
}
:};
parser code{:
public void syntax_error(Symbol st){
token t=(token)st.value;
report_error("Error Sintactico:"+ t.getValue(),null);
}
public static void cargar(String archivo) throws Exception{
new parser(new scanner(new FileInputStream(archivo))).parse();
}
:};
/* Especificamos los terminales del lenguaje */
terminal Integer INT;
terminal String TYPE;
terminal SEMI, COMMA, BINARYOP, UNARYOP, LP, RP, LB, RB, LC, RC, STRUCT,
RETURN, IF, ELSE, BREAK, CONT, FOR, ID;
/*PARA EVITAR EL ERROR*/
terminal ASSIGN, DOT;
/* Especificamos los no terminales del lenguaje */
non terminal PROGRAM, EXTDEFS, EXTDEF, SEXTVARS, EXTVARS, STSPEC,
FUNC, PARAS, STMTBLOCK, STMTS, STMT, DEFS, SDEFS, SDECS, DECS, VAR, INIT,
EXP, EXPS, ARGS, ARRS;
//Precedencias
precedence left ELSE;
precedence left BINARYOP;
/*
precedence left "||";
precedence left "&&";
precedence left "|";
precedence left "^";
precedence left "&";
precedence left "==", "!=";
void
jButton2MouseClicked(java.awt.event.MouseEvent
evt)
{//GEN-
FIRST:event_jButton2MouseClicked
// TODO add your handling code here:
// TODO add your handling code here:
Salida.setText(" ");
if (dire == null) {
Salida.setText("Archivo invalido");
} else {
System.out.println("dir: "+dire);
parser p = new parser();
try {
p.cargar(dire);
} catch (Exception ex) {
Logger.getLogger(Sintactico.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
try {
BufferedReader bf = new BufferedReader(new FileReader("c:/Salida.out"));
try {
String str = "";
int x = 0;
bf.mark(0);
bf.reset();
String aux = " ";
while (aux != null) {
aux = bf.readLine();
if (aux == null) {
break;
}
str = str + aux + "\n";
x++;
}
Salida.setText(str);
} catch (IOException ex) {
}
} catch (FileNotFoundException ex) {
}
}
}//GEN-LAST:event_jButton2MouseClicked
Referencias Bibliogrficas
Informacin en Internet:
Metacompiladores:
http://www.ecured.cu/Analizador_sint%C3%A1ctico_descendente
http://documents.mx/documents/analisis-sintactico-ascendente-y-descendente-
558dd7f932893.html
https://ocw.uma.es/ingenierias/traductores-compiladores-e-interpretes/material-de-
clase-1/Capitulo_3.pdf
http://compiladoresasignatura.blogspot.com/2011/05/analisis-sintactico.html
http://www.lcc.uma.es/~galvez/ftp/tci/tictema3.pdf
http://users.dsic.upv.es/~jsilva/uned/compiladores/Apuntes04.pdf
http://informatica.uv.es/docencia/iiguia/asignatu/2000/PL/2007/tema5.pdf
http://www.jflex.de/docu.html
http://www.slkpg.com/documentation.html