Anda di halaman 1dari 10

INSTITUTO

TECNOLOGICO
DE
VILLAHERMOSA
INTEGRANTES:
Luis Enrique Cruz Morales
Erick Jose Santos Morales
Paula Antonia

MATERIA:
Lenguajes Y Automatas II

ITVH

MAESTRO:
ING. Mauricio
Arturo Reyes
Hernandez

REPORTE:
Analizador
lexico,
sintactico y
semantico
CARRERA:
Ing. Sistemas
computacionales

FECHA:
Noviembre del
2014

Introduccin
En la programacin, un analizador lxico es la parte de un compilador o analizador
(parser) que trata de descomponer el lenguaje proporcionado como entrada en
tokens.
Un token es la unidad mnima con significado. Tokens habituales son los identificadores,
enteros, flotantes, constantes, etc.
Para el desarrollo, utilizamos una herramienta llamda, JavaCC. Mediante expresiones
regulares podemos definir cmodamente los tokens de nuestro lenguaje.
JavaCC es una herramienta que generalmente se utiliza para generar analizadores
lxicos y sintcticos (parsers) de una forma muy cmoda, actualmente se encuentra
mantenida por Sun Microsystems y es muy robusta, eficiente y fiable.
Las especificaciones de nuestro lenguaje son:
Tokens:
Constantes:
Cadenas: Caracteres entrecomillados, ejemplo: "cadena"
Enteros: Nmeros positivos, ejemplo: 234 o 0
Lgicas: TRUE y FALSE
Identificadores: Todos los identificadores son una secuencia de letras (a-zA-Z) y
nmeros que obligatoriamente deben comenzar con una letra (y no un nmero). Los
identificadores que se refieran a cadenas terminarn en "$".
Palabras reservadas: En el lenguaje hay palabras reservadas que darn vida al
lenguaje, estas sern: "not, if, end, let, call, then, case, else, input, print, select y static".
El anlisis lxico-sintctico tiene por objeto reconocer la forma de las sentencias de un
lenguaje. Reconocer la forma de una sentencia implica reconocer sus lexemas y
estructuras sintcticas.
Para reconocer los lexemas de un lenguaje usaremos expresiones regulares y para
reconocer estructuras sintcticas usaremos gramticas independientes de contexto
(gramtica en adelante).
Una gramtica es un conjunto de reglas. Cada regla es de la forma genrica:
cabeza : cuerpo1 | cuerpo2 | ... |
La cabeza de la regla es un smbolo llamado no terminal que representa una estructura
sintctica. El cuerpo de la regla est compuesto por smbolos terminales (lexemas) y no
terminales. La composicin de estos smbolos se consigue haciendo uso de alternativas,
iteraciones y yuxtaposiciones.
El anlisis sintctico se puede realizar aplicando reglas de G de izquierda a derecha
(anlisis descendente). La aplicacin de una regla se denomina derivacin. En el
anlisis sintctico descendente, el objetivo es encontrar una derivacin que reconozca
la sentencia. Los smbolos no terminales son smbolos generativos porque producen

derivaciones. Los lexemas son smbolos no generativos porque no producen


derivaciones.
Los lexemas o tokens son los smbolos terminales que aparecen en la gramtica y
representan las distintas categoras de palabras y smbolos de puntuacin que
podemos encontrar en una sentencia del lenguaje. Los lexemas de un lenguaje se
definen con reglas de la forma:
LEXEMA : expresin regular donde expresin regular puede ser:
(1) carcter (ej. '('),
(2) concatenacin de caracteres (ej. "INSTRUCCIONES") ,
(3) rango de caracteres (ej. '0'..'9'),
(4) nmeros (ej. (0-1)),
(5) opcin (ej. (('a'..'z')?),
(6) alternativa (ej. 'a'..'z'|'A'..'Z') y
(7) cierre (ej. (LETRA)+).
El anlisis semntico utiliza como entrada el rbol sintctico detectado por el anlisis
sintctico para comprobar restricciones de tipo y otras limitaciones semnticas y
preparar la generacin de cdigo.

Estructura del cdigo fuente


PARSER_BEGIN(comp)
class comp
{
public static void main( String[] args )throws ParseException
{
try
{
comp analizador = new comp( System.in ) ;
analizador.Programa() ;
}
catch(ParseException e)
{
System.out.println(e.getMessage());
System.out.println("Analizador: Se han encontrado errores en el analisis.");
}
}
}
PARSER_END(comp)
SKIP :
{
" "|"\n" | "\r" | "\r\n"
}
PARSER_END(comp)
TOKEN :
{
<ASIGNACION : "="> {System.out.println("ASIGNACION -> "+image+"\r\n");}
| <PLUS : "+" > {System.out.println("SUMAR -> "+image+"\r\n");}
| <MINUS:"-">{System.out.println("RESTAR -> "+image+"\r\n");}
| <MULTIPLY:"*">{System.out.println("MULTIPLICAR -> "+image+"\r\n");}
| <DIVIDE:"/">{System.out.println("DIVIDIR -> "+image+"\r\n");}
| <INCR: "++" >{System.out.println("INCREMENTO -> "+image+"\r\n");}
| <DECR: "--" >{System.out.println("DECREMENTO -> "+image+"\r\n");}//7
}
TOKEN:
{
<MAIN: "publico estatico vacio principal() ">{System.out.println("MAIN -> "+image);}
| <PROGRAMA: "clase " > {System.out.println("CLASE -> "+image);}
| <PRIVATE: "privado " > {System.out.println("PRIVATE -> "+image);}
| <PUBLIC: "publico " > {System.out.println("PUBLIC -> "+image);}
| <IF: "si " >{System.out.println("IF -> "+image);}
| <ELSE:"sino " >{System.out.println("ELSE -> "+image);}
| <ELSEIF:"sino si " >{System.out.println("ELSE IF -> "+image);}
| <FOR:"para " >{System.out.println("FOR -> "+image);}
| <SWITCH:"interruptor " >{System.out.println("SWITCH -> "+image);}
| <CASE:"caso " >{System.out.println("CASE -> "+image);}
| <BREAK:"ruptura " >{System.out.println("BREAK -> "+image);}
| <DEFAUL:"pordefecto " >{System.out.println("DEFAULT -> "+image);}
| <DO:"hacer " >{System.out.println("DO -> "+image);}
| <WHILE:"mientras " >{System.out.println("WHILE -> "+image);}//21
}
TOKEN:
{
<LPAREN: "(" >{System.out.println("IPAREN -> "+image);}
| <RPAREN: ")" >{System.out.println("DPAREN -> "+image);}
| <LBRACE: "{" >{System.out.println("IMETODO -> "+image);}
| <RBRACE: "}" >{System.out.println("TMETODO -> "+image);}
| <LBRACKET: "[" >{System.out.println("ICORC -> "+image);}
| <RBRACKET: "]" >{System.out.println("DCORC -> "+image);}
| <SEMICOLON: ";" >{System.out.println("FIN DE INSTRUCCION -> "+image);}
| <COMMA: "," >{System.out.println("COMA -> "+image);}
| <DOUBLEPOINT : ":">{System.out.println("DOS PUNTOS -> "+image);}
| <DOT: "." >{System.out.println("PUNTO -> "+image);}
| <DOUBLECOMMA: "\""> //32
}
TOKEN:
{
<EQ: "==" >{System.out.println("IGUALACION -> "+image);}
| <LE: "<=" >{System.out.println("MENOR O IGUAL -> "+image);}
| <MN: "<" >{System.out.println("MENOR QUE -> "+image);}
| <GE: ">=" >{System.out.println("MAYOR O IGUAL -> "+image);}

| <GR: ">" >{System.out.println("MAYOR QUE -> "+image);}


| <NE: "!=" >{System.out.println("DIFERENTE -> "+image);}
| <OR: "||" >{System.out.println("OR -> "+image);}
| <AND: "&&">{System.out.println("AND -> "+image);}//40
}
TOKEN:
{
<BOO: "booleano" > {System.out.print("Boolean -> "+image+"\r\n");}//41
| <BYT: "byte" > {System.out.print("Byte -> "+image+"\r\n");}//42
| <INT: "entero" > {System.out.print("Int -> "+image+"\r\n");}//43
| <LON: "largo" > {System.out.print("Long -> "+image+"\r\n");}//44
| <FLO: "flotante" > {System.out.print("Float -> "+image+"\r\n");}//45
| <DEC: "doble" > {System.out.print("Double -> "+image+"\r\n");}//46
| <CHR: "caracter" > {System.out.print("Char -> "+image+"\r\n");}//47
| <STR: "cadena" > {System.out.print("String -> "+image+"\r\n");}//48
| <CARAC: "'"["a"-"z","A"-"Z","0"-"9"]"'" > {System.out.print("CARACTER -> "+image+"\r\n");}//49
| <CADENA: <DOUBLECOMMA>["a"-"z","A"-"Z","0"-"9"," "](["a"-"z","A"-"Z","0"-"9"," ",":",";","."])*<DOUBLECOMMA> >
{System.out.print("CADENA -> "+image+"\r\n");}//50
| <NUMBER : (["0"-"9"])+ > {System.out.print("NUMERO -> "+image+"\r\n");}//51
| <DECIMAL : (["0"-"9"])+["."](["0"-"9"])+ > {System.out.print("DECIMAL -> "+image+"\r\n");}//52
| <BOV: "verdadero"|"falso" > {System.out.print("Valor booleano -> "+image+"\r\n");}//53
| <VOID: "vacio ">//54
| <MULOP: ["0"-"9","+","-","*","/","(",")"]>
| <IDENTIFIER : ["a"-"z","A"-"Z"](["a"-"z","A"-"Z","0"-"9","_"])* > {System.out.print("IDENTIFICADOR -> "+image+"\r\n");}//55
}
void Programa() :
{}
{
<PROGRAMA><IDENTIFIER><LBRACE>Bloque()<RBRACE><EOF>
}
void Bloque():
{}
{
DeclaracionGlobal() | Principal()
}
void DeclaracionGlobal():
{}
{
<TYPES>VariablesGlobales()
}
void VariablesGlobales():
{}
{
/*<IDENTIFIER>", "<IDENTIFIER> |*/ <IDENTIFIER> <SEMICOLON> W()
}
void W():
{}
{
DeclaracionGlobal() | Principal()
}
void Principal():
{}
{
<MAIN>
<LBRACE>Sentencias()<RBRACE>
}
void DeclaracionLocal():
{}
{
<TYPES>VariablesLocales()
}
void VariablesLocales():
{}
{
/*<IDENTIFIER>", "<IDENTIFIER> | */<IDENTIFIER> <SEMICOLON> VS()
}
void VS():
{}
{
DeclaracionLocal() | Sentencias()
}
void Sentencias():

{}
{
(
DeclaracionLocal()
| SentenciaIf()
| SentenciaFor()
| SentenciaDo()
| SentenciaAsignacion()
| SentenciaWrite()
| SentenciaRead()
|<EOF>
//| SentenciaSwitch()
/*| Sentencias() Left Recursion: Poner Sentencias() a la finalizacion de cada metodo?*/
)*
}
//Sentencia IF
void SentenciaIf():
{}
{
<IF><LPAREN> A() <RPAREN> <LBRACE> Sentencias() <RBRACE> /*|
"ien " "( " A() ") " "{ "Sentencias()"} ""Sino "*/
}
/*void Sino():
{}
{
"iotro " "{ "Sentencias()"} "
}*/
void A():
{}
{
Comparaciones()
/*| Comparaciones() "&& " Comparaciones()
| Comparaciones() "|| " Comparaciones()*/
}
//Fin sentencia if
void Comparaciones():
{}
{
Valor()Operadores()Valor()
}
void Valor():
{}
{
<IDENTIFIER> | <NUMBER> /*| Expresion()*/
}
void Expresion():
{}
{
/*<NUMBER> | <IDENTIFIER> |*/ <IDENTIFIER><PLUS><IDENTIFIER><SEMICOLON> /*| <NUMBER> OpAritmetico()
<NUMBER> |
<IDENTIFIER> OpAritmetico() <IDENTIFIER>|
<IDENTIFIER> OpAritmetico() <NUMBER> | <IDENTIFIER> */
}
void Operadores():
{}
{
<EQ> | <LE> |<GE>|<NE>
}
void OpAritmetico():
{}
{
<PLUS>|<MINUS>|<MULTIPLY>|<DIVIDE>
}
//Sentencia FOR
void SentenciaFor():
{}
{
<FOR> <LPAREN> SentenciaAsignacion() <SEMICOLON> Comparaciones() SentenciaAsignacion() <RPAREN> <LBRACE>
Sentencias() <RBRACE>/*|
"irepetir " "( " SentenciaAsignacion() "; " Comparaciones() SentenciaAsignacion() ") " "{ " Sentencias() "} "Sentencias()*/
}
//Sentencia DO
void SentenciaDo():
{}

{
<DO> <LBRACE>Sentencias() <RBRACE> <WHILE> <LPAREN> Comparaciones() <RPAREN> /*|
"iespera " "( " Comparaciones() ") " "{ " Sentencias() "} "
*/
}
//Sentencia ASIGNACION
void SentenciaAsignacion():
{}
{
<IDENTIFIER> <ASIGNACION> Expresion()
}
//Sentencia WRITE
void SentenciaWrite():
{}
{
<WRITE> <LPAREN> Expresion() <RPAREN> <SEMICOLON> /*|
"iescribir " "( " "^ " <CADENA> "^ " ") " "; "*/
}
//Sentencia READ
void SentenciaRead():
{}
{
<READ><LPAREN><RPAREN><SEMICOLON>
}

Analizador en ejecucin
Con errores:

Sin errores:

Conclusion
Hay ocasiones en que necesitamos procesar una determinada expresin, por ejemplo
para hacer una bsqueda por una serie de criterios obtenidos de la misma. La forma
habitual es hacerlo creando un algoritmo especfico ms o menos complejo segn lo
sea la expresin con varios splits, expresiones regulares, condiciones, bucles, etc..., que
normalmente resulta en cdigo difcil de desarrollar, mantener, entender lo que hace
y poco flexible ante cambios. Esta es la primera opcin que se nos ocurre pero no es la
mejor
forma
de
hacerlo
como
veremos
en
esta
entrada.
Cuando nos enfrentamos a un problema de procesar una expresin debemos tener en
cuenta primeramente dos cosas: cul es su lxico (las palabras que lo forman) y su
sintaxis (las reglas que definen el orden del lxico). Ms tarde por otra parte para
procesar la expresin necesitaremos de acciones lxicas y sintcticas que es cdigo
que se ejecutar para realizar las tareas que necesitemos al procesar la expresin.
Para facilitar la tarea existen los compiladores como resultado de la invencin de los
primeros lenguajes y aunque parecen algo complejo de hacer no lo son tanto como
desarrollar un algoritmo especfico. JavaCC es una herramienta que nos permite definir
el lxico de una expresin o lenguaje, la sintaxis del mismo y las acciones lxicas y
sintcticas generando posteriormente con la definicin de estas cosas una serie de
archivos .java con el cdigo fuente de un analizador lxico, sintctico y otra serie de
archivos
.java
de
utilidad
para
los
mismos.
El cdigo fuente de nuestro pequeo compilador cuya misin ser interpretar la
expresin de la mejor de las formas. El compilador est dividido en varias partes:
PARSER_BEGIN y PARSE_END: define el nombre de nuestro analizador e incluye mtodos
de utilidad (en perfecto cdigo Java) que ser incluidos en el analizador sintctico sin
modificar y que podremos usar desde las acciones sintcticas. Los mtodos
importantes de esta primera parte son los constructores (JavaCC inserta unos pero
como vemos podemos definir ms), que ser cuando el analizador sintctico detecte
un trmino, es la misin principal de nuestro compilador. Estos mtodos no tienen mayor
complicacin
son
puro
cdigo
Java.
SKIP y TOKEN: esta parte es la que define el analizador lxico con las palabras de
nuestra expresin o lenguaje. Ah estn la forma de las palabras reservadas,
operadores, identificadores, los separadores. Bsicamente son una forma de
expresiones
regulares
para
definir
cada
uno
de
ellos
procesarQuery, procesar, termino. Son propiamente los mtodos del analizador
sintctico y van a definir la sintaxis de nuestro lenguaje. Procesar contiene una de las
partes ms importantes ya que es el punto de partida, va cogiendo los tokens
proporcionados por el analizador lxico (que genera JavaCC) y determina los
mtodos, trmino o algo desconocido. Segn lo detectado se ejecuta el bloque de
cdigo posterior que va entre {} y que constituye una accin sintctica.

Por qu se trata un elemento DESCONOCIDO? Porque si no el analizador sintctico


dara un excepcin al no saber lo que es, terminara y no devolvera nada. De esta
forma conseguimos que si una expresin que no se entiende se ignore y se devuelvan
al
menos
el
resto
de
expresiones.
Esta es una de esas herramientas muy tiles y con la cual sabiendo usarla o al menos
tener conocimiento de ella nos puede ahorrar mucho tiempo y conseguir hacer las
cosas mejor. Adems y dado que lo que genera como resultado son una serie de
archivos .java podremos utilizarlos en cualquier entorno, como en alguna
administracin pblica cuyo nombre no citar aqu y en la que no esta permitido usar
libreras no homologadas por ellos, dado que se trata de cdigo fuente y que no tiene
dependencias sobre otras libreras no tendremos ningn problema en usar JavaCC en
casos como este.