0% encontró este documento útil (0 votos)
5 vistas24 páginas

Análisis Léxico y Sintáctico Java

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
5 vistas24 páginas

Análisis Léxico y Sintáctico Java

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 24

Instituto Tecnológico de Mexicali

Ingeniería en Sistemas Computacionales

Reporte sobre analizador sintáctico y analizador lexico

Lenguajes y autómatas

Nombre: Lorenzleon Larry Rivas


Paez 19491015
Reporte sobre Analizador Sintáctico y
Analizador Léxico
Introducción
En este reporte, se analizará el código proporcionado que implementa
un analizador léxico y un analizador sintáctico para un lenguaje de
programación de Java. El objetivo es comprender el funcionamiento de
estos componentes y evaluar su estructura y organización.

Analizador Léxico
El analizador léxico se encarga de dividir el código fuente en tokens,
que son las unidades básicas del lenguaje. La clase AnalizadorLexico es
la responsable de realizar este análisis.

Aspectos destacados:

 Utiliza un mapa palabrasReservadas para almacenar las palabras


clave del lenguaje y su correspondiente tipo de token.
 Recorre el código fuente carácter por carácter y utiliza diferentes
métodos para analizar identificadores, números, cadenas y
caracteres especiales.
 Mantiene un registro de la posición, línea y columna actual
durante el análisis, lo cual es útil para generar mensajes de error
precisos.
 Genera una lista de tokens como resultado del análisis léxico.

Posibles mejoras:

 Se podría considerar el uso de expresiones regulares para


simplificar la identificación de patrones léxicos comunes.
 Se podría agregar soporte para comentarios de una o varias líneas.

Analizador Sintáctico
El analizador sintáctico se encarga de verificar si la estructura del
código fuente cumple con las reglas gramaticales del lenguaje. La clase
AnalizadorSintactico es la responsable de realizar este análisis.
Aspectos destacados:

 Utiliza la lista de tokens generada por el analizador léxico como


entrada.
 Realiza un análisis descendente recursivo para verificar la
estructura del código fuente.
 Genera una lista de errores sintácticos encontrados durante el
análisis.
 Indica si el análisis se completó exitosamente o si se encontraron
errores.

Posibles mejoras:

 Se podría implementar un manejo de errores más sofisticado,


como la recuperación de errores y el reporte de errores más
detallado.
 Se podría considerar el uso de herramientas de generación de
analizadores sintácticos, como ANTLR o Bison, para simplificar
la implementación y mejorar la eficiencia.
Interfaz de Usuario
La interfaz de usuario proporcionada por la clase Interfaz permite
interactuar con el analizador de manera intuitiva.

Aspectos destacados:

 Utiliza componentes de Swing para construir una interfaz gráfica


amigable.
 Permite ingresar código fuente, realizar el análisis léxico y
sintáctico, y mostrar los resultados en pestañas separadas.
 Proporciona funcionalidades adicionales, como la carga de
ejemplos, la apertura y guardado de archivos, y la limpieza de los
campos de texto.

Posibles mejoras:

 Se podría mejorar la apariencia visual de la interfaz utilizando


bibliotecas de componentes más modernas, como JavaFX.
 Se podría agregar resaltado de sintaxis en el área de código fuente
para mejorar la legibilidad.
Conclusiones
El código proporcionado implementa de manera efectiva un analizador
léxico y un analizador sintáctico para un lenguaje de programación de
Java. La estructura del proyecto es clara y organizada, lo que facilita su
comprensión y mantenimiento.

El analizador léxico realiza un buen trabajo al dividir el código fuente


en tokens, utilizando un enfoque basado en el recorrido carácter por
carácter y el uso de un mapa para las palabras clave. El analizador
sintáctico, por su parte, verifica la estructura del código fuente
utilizando un análisis descendente recursivo y genera una lista de
errores encontrados.

La interfaz de usuario proporciona una forma intuitiva de interactuar


con el analizador, permitiendo ingresar código fuente, realizar el
análisis y visualizar los resultados de manera clara.

En general, el código cumple con su objetivo y demuestra una buena


comprensión de los conceptos de análisis léxico y sintáctico.

En conclusión, este proyecto es un buen punto de partida para


comprender el funcionamiento de un analizador léxico y sintáctico, y
proporciona una base sólida para futuras extensiones y mejoras.

///Código proporsionado:
package analizadores;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AnalizadorLexico {
private final String codigo;
private final List<Token> tokens;
private int posicion;
private int linea;
private int columna;
private static final Map<String, TipoToken> palabrasReservadas;

static {
palabrasReservadas = new HashMap<>();
palabrasReservadas.put("class", TipoToken.CLASS);
palabrasReservadas.put("public", TipoToken.PUBLIC);
palabrasReservadas.put("static", TipoToken.STATIC);
palabrasReservadas.put("void", TipoToken.VOID);
palabrasReservadas.put("if", TipoToken.IF);
palabrasReservadas.put("else", TipoToken.ELSE);
palabrasReservadas.put("while", TipoToken.WHILE);
palabrasReservadas.put("do", TipoToken.DO);
palabrasReservadas.put("for", TipoToken.FOR);
palabrasReservadas.put("int", TipoToken.INT);
palabrasReservadas.put("String", TipoToken.STRING);
palabrasReservadas.put("boolean", TipoToken.BOOLEAN);
palabrasReservadas.put("double", TipoToken.DOUBLE);
palabrasReservadas.put("true", TipoToken.TRUE);
palabrasReservadas.put("false", TipoToken.FALSE);
palabrasReservadas.put("switch", TipoToken.SWITCH);
palabrasReservadas.put("case", TipoToken.CASE);
palabrasReservadas.put("default", TipoToken.DEFAULT);
palabrasReservadas.put("break", TipoToken.BREAK);
palabrasReservadas.put("continue", TipoToken.CONTINUE);
palabrasReservadas.put("return", TipoToken.RETURN);
}

public AnalizadorLexico(String codigo) {


this.codigo = codigo;
this.tokens = new ArrayList<>();
this.posicion = 0;
this.linea = 1;
this.columna = 1;
}

public List<Token> analizar() {


while (posicion < codigo.length()) {
char c = codigo.charAt(posicion);

if (Character.isWhitespace(c)) {
if (c == '\n') {
linea++;
columna = 1;
} else {
columna++;
}
posicion++;
continue;
}

if (Character.isLetter(c) || c == '_') {
analizarIdentificador();
continue;
}

if (Character.isDigit(c)) {
analizarNumero();
continue;
}

if (c == '"') {
analizarCadena();
continue;
}

switch (c) {
case '(' -> agregarToken(TipoToken.PARENTESIS_IZQ,
String.valueOf(c));
case ')' -> agregarToken(TipoToken.PARENTESIS_DER,
String.valueOf(c));
case '{' -> agregarToken(TipoToken.LLAVE_IZQ, String.valueOf(c));
case '}' -> agregarToken(TipoToken.LLAVE_DER, String.valueOf(c));
case '[' -> agregarToken(TipoToken.CORCHETE_IZQ,
String.valueOf(c));
case ']' -> agregarToken(TipoToken.CORCHETE_DER,
String.valueOf(c));
case '=' -> {
if (siguienteEsIgual()) {
agregarToken(TipoToken.IGUAL_IGUAL, "==");
posicion++;
} else {
agregarToken(TipoToken.IGUAL, String.valueOf(c));
}
}
case '>' -> {
if (siguienteEsIgual()) {
agregarToken(TipoToken.MAYOR_IGUAL, ">=");
posicion++;
} else {
agregarToken(TipoToken.MAYOR_QUE, String.valueOf(c));
}
}
case '<' -> {
if (siguienteEsIgual()) {
agregarToken(TipoToken.MENOR_IGUAL, "<=");
posicion++;
} else {
agregarToken(TipoToken.MENOR_QUE, String.valueOf(c));
}
}
case '!' -> {
if (siguienteEsIgual()) {
agregarToken(TipoToken.NO_IGUAL, "!=");
posicion++;
} else {
agregarToken(TipoToken.NOT, String.valueOf(c));
}
}
case '&' -> {
if (siguienteEs('&')) {
agregarToken(TipoToken.AND, "&&");
posicion++;
} else {
throw new RuntimeException("Carácter '&' inesperado en línea " +
linea);
}
}
case '|' -> {
if (siguienteEs('|')) {
agregarToken(TipoToken.OR, "||");
posicion++;
} else {
throw new RuntimeException("Carácter '|' inesperado en línea " +
linea);
}
}
case '+' -> agregarToken(TipoToken.MAS, String.valueOf(c));
case '-' -> agregarToken(TipoToken.MENOS, String.valueOf(c));
case '*' -> agregarToken(TipoToken.MULTIPLICACION,
String.valueOf(c));
case '/' -> agregarToken(TipoToken.DIVISION, String.valueOf(c));
case '%' -> agregarToken(TipoToken.MODULO, String.valueOf(c));
case ';' -> agregarToken(TipoToken.PUNTO_COMA,
String.valueOf(c));
case ',' -> agregarToken(TipoToken.COMA, String.valueOf(c));
case '.' -> agregarToken(TipoToken.PUNTO, String.valueOf(c));
case ':' -> agregarToken(TipoToken.DOS_PUNTOS,
String.valueOf(c));
default -> throw new RuntimeException("Carácter no reconocido: " +
c);
}

posicion++;
columna++;
}

tokens.add(new Token(TipoToken.EOF, "", linea, columna));


return tokens;
}

private void analizarIdentificador() {


int inicioColumna = columna;
StringBuilder valor = new StringBuilder();

while (posicion < codigo.length() &&


(Character.isLetterOrDigit(codigo.charAt(posicion)) ||
codigo.charAt(posicion) == '_')) {
valor.append(codigo.charAt(posicion));
posicion++;
columna++;
}

String identificador = valor.toString();


TipoToken tipo = palabrasReservadas.getOrDefault(identificador,
TipoToken.IDENTIFICADOR);
tokens.add(new Token(tipo, identificador, linea, inicioColumna));
}
private void analizarNumero() {
int inicioColumna = columna;
StringBuilder valor = new StringBuilder();

while (posicion < codigo.length() &&


Character.isDigit(codigo.charAt(posicion))) {
valor.append(codigo.charAt(posicion));
posicion++;
columna++;
}

tokens.add(new Token(TipoToken.NUMERO, valor.toString(), linea,


inicioColumna));
}

private void analizarCadena() {


int inicioColumna = columna;
StringBuilder valor = new StringBuilder();
posicion++;
columna++;

while (posicion < codigo.length() && codigo.charAt(posicion) != '"') {


valor.append(codigo.charAt(posicion));
posicion++;
columna++;
}

if (posicion >= codigo.length()) {


throw new RuntimeException("Cadena no cerrada en línea " + linea);
}

posicion++;
columna++;
tokens.add(new Token(TipoToken.CADENA, valor.toString(), linea,
inicioColumna));
}

private void agregarToken(TipoToken tipo, String valor) {


tokens.add(new Token(tipo, valor, linea, columna));
}

private boolean siguienteEsIgual() {


return siguienteEs('=');
}

private boolean siguienteEs(char esperado) {


if (posicion + 1 < codigo.length()) {
return codigo.charAt(posicion + 1) == esperado;
}
return false;
}
}
package analizadores;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.List;
@SuppressWarnings("serial")
public class Interfaz extends JFrame {
private final JTextArea areaCodigoFuente;
private final JTextArea areaTokens;
private final JTextArea areaErrores;
private final JTextArea areaResultados;
private final JTabbedPane panelPestanas;
private final JFileChooser selectorArchivo;
public Interfaz() {
setTitle("Analizador Léxico y Sintáctico");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Inicialización de componentes
areaCodigoFuente = crearAreaTexto(20, 50);
areaTokens = crearAreaTexto(10, 50);
areaErrores = crearAreaTexto(10, 50);
areaResultados = crearAreaTexto(10, 50);
selectorArchivo = new JFileChooser();

// Configuración del panel principal


JPanel panelPrincipal = new JPanel(new BorderLayout(10, 10));
panelPrincipal.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

// Panel superior con código fuente


JPanel panelCodigo = new JPanel(new BorderLayout(5, 5));
panelCodigo.add(new JLabel("Código Fuente:"), BorderLayout.NORTH);
panelCodigo.add(new JScrollPane(areaCodigoFuente),
BorderLayout.CENTER);

// Panel de botones
JPanel panelBotones = crearPanelBotones();
panelCodigo.add(panelBotones, BorderLayout.SOUTH);

// Panel de pestañas para resultados


panelPestanas = new JTabbedPane();
panelPestanas.addTab("Tokens", new JScrollPane(areaTokens));
panelPestanas.addTab("Errores", new JScrollPane(areaErrores));
panelPestanas.addTab("Resultados", new JScrollPane(areaResultados));

// Agregar paneles al panel principal


panelPrincipal.add(panelCodigo, BorderLayout.NORTH);
panelPrincipal.add(panelPestanas, BorderLayout.CENTER);

// Configuración final de la ventana


add(panelPrincipal);
pack();
setLocationRelativeTo(null);

// Agregar ejemplo inicial


cargarEjemploInicial();
}
private JTextArea crearAreaTexto(int filas, int columnas) {
JTextArea area = new JTextArea(filas, columnas);
area.setFont(new Font("Monospaced", Font.PLAIN, 14));
area.setTabSize(4);
return area;
}
private JPanel crearPanelBotones() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));

JButton btnAnalizar = new JButton("Analizar");


JButton btnLimpiar = new JButton("Limpiar");
JButton btnAbrir = new JButton("Abrir Archivo");
JButton btnGuardar = new JButton("Guardar");
JButton btnEjemplo = new JButton("Cargar Ejemplo");

btnAnalizar.addActionListener(e -> analizarCodigo());


btnLimpiar.addActionListener(e -> limpiarTodo());
btnAbrir.addActionListener(e -> abrirArchivo());
btnGuardar.addActionListener(e -> guardarArchivo());
btnEjemplo.addActionListener(e -> cargarEjemploInicial());

panel.add(btnAnalizar);
panel.add(btnLimpiar);
panel.add(btnAbrir);
panel.add(btnGuardar);
panel.add(btnEjemplo);

return panel;
}
private void analizarCodigo() {
String codigo = areaCodigoFuente.getText().trim();

if (codigo.isEmpty()) {
mostrarError("Por favor, ingrese código para analizar.");
return;
}
try {
// Análisis léxico
AnalizadorLexico analizadorLexico = new AnalizadorLexico(codigo);
List<Token> tokens = analizadorLexico.analizar();

// Mostrar tokens
StringBuilder resultadoTokens = new StringBuilder("Tokens
identificados:\n\n");
for (Token token : tokens) {
resultadoTokens.append(String.format("%-15s | %-20s | línea %-4d |
columna %-4d\n",
token.obtenerTipo(),
token.obtenerValor(),
token.obtenerLinea(),
token.obtenerColumna()));
}
areaTokens.setText(resultadoTokens.toString());

// Análisis sintáctico
AnalizadorSintactico analizadorSintactico = new
AnalizadorSintactico(tokens);
boolean exitoSintactico = analizadorSintactico.analizar();

// Mostrar errores sintácticos


List<String> errores = analizadorSintactico.obtenerErrores();
StringBuilder resultadoErrores = new StringBuilder();

if (!errores.isEmpty()) {
resultadoErrores.append("Errores encontrados:\n\n");
for (String error : errores) {
resultadoErrores.append("• ").append(error).append("\n");
}
} else {
resultadoErrores.append("No se encontraron errores sintácticos.");
}
areaErrores.setText(resultadoErrores.toString());

// Mostrar resultado final


areaResultados.setText(exitoSintactico ?
"Análisis completado exitosamente." :
"El análisis encontró errores. Revise la pestaña de errores para más
detalles.");

// Cambiar a la pestaña correspondiente


panelPestanas.setSelectedIndex(exitoSintactico ? 0 : 1);

} catch (Exception e) {
mostrarError("Error durante el análisis: " + e.getMessage());
}
}
private void limpiarTodo() {
areaCodigoFuente.setText("");
areaTokens.setText("");
areaErrores.setText("");
areaResultados.setText("");
}
private void abrirArchivo() {
if (selectorArchivo.showOpenDialog(this) ==
JFileChooser.APPROVE_OPTION) {
try {
FileReader reader = new
FileReader(selectorArchivo.getSelectedFile());
areaCodigoFuente.read(reader, null);
reader.close();
} catch (IOException e) {
mostrarError("Error al abrir el archivo: " + e.getMessage());
}
}
}
private void guardarArchivo() {
if (selectorArchivo.showSaveDialog(this) ==
JFileChooser.APPROVE_OPTION) {
try {
FileWriter writer = new FileWriter(selectorArchivo.getSelectedFile());
areaCodigoFuente.write(writer);
writer.close();
} catch (IOException e) {
mostrarError("Error al guardar el archivo: " + e.getMessage());
}
}
}
private void mostrarError(String mensaje) {
areaErrores.setText("ERROR: " + mensaje);
panelPestanas.setSelectedIndex(1); // Cambiar a la pestaña de errores
}
private void cargarEjemploInicial() {
String ejemploCodigo = """
class Ejemplo {
public static void main(String[] args) {
int numero = 42;
String mensaje = "Hola mundo";

if (numero > 0) {
System.out.println(mensaje);
}
}
}
""";
areaCodigoFuente.setText(ejemploCodigo);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClass
Name());
} catch (Exception e) {
e.printStackTrace();
}
new Interfaz().setVisible(true);
});
package analizadores;

public enum TipoToken {

// Palabras clave

CLASS,

PUBLIC,

STATIC,

VOID,

IF,

ELSE,

WHILE,

FOR,

DO,

SWITCH,

CASE,

DEFAULT,

BREAK,

CONTINUE,

RETURN,

INT,

STRING,

BOOLEAN,

DOUBLE,

TRUE,

FALSE,
// Identificadores y literales

IDENTIFICADOR,

NUMERO,

CADENA,

// Operadores aritméticos

MAS, // +

MENOS, // -

MULTIPLICACION,// *

DIVISION, // /

MODULO, // %

// Operadores de comparación

IGUAL, // =

IGUAL_IGUAL, // ==

MAYOR_QUE, // >

MENOR_QUE, // <

MAYOR_IGUAL, // >=

MENOR_IGUAL, // <=

NO_IGUAL, // !=

// Operadores lógicos

AND, // &&

OR, // ||

NOT, // !

// Símbolos especiales
PARENTESIS_IZQ, // (

PARENTESIS_DER, // )

LLAVE_IZQ, // {

LLAVE_DER, // }

CORCHETE_IZQ, // [

CORCHETE_DER, // ]

PUNTO_COMA, // ;

COMA, // ,

PUNTO, // .

DOS_PUNTOS, // :

// Final de archivo

EOF;

@Override

public String toString() {

return switch(this) {

case AND -> "operador '&&'";

case BOOLEAN -> "tipo 'boolean'";

case BREAK -> "palabra reservada 'break'";

case CADENA -> "cadena";

case CASE -> "palabra reservada 'case'";

case CLASS -> "palabra reservada 'class'";

case COMA -> "','";

case CONTINUE -> "palabra reservada 'continue'";

case CORCHETE_DER -> "']'";

case CORCHETE_IZQ -> "'['";


case DEFAULT -> "palabra reservada 'default'";

case DIVISION -> "operador '/'";

case DO -> "palabra reservada 'do'";

case DOS_PUNTOS -> "':'";

case DOUBLE -> "tipo 'double'";

case ELSE -> "palabra reservada 'else'";

case EOF -> "fin de archivo";

case FALSE -> "literal 'false'";

case FOR -> "palabra reservada 'for'";

case IDENTIFICADOR -> "identificador";

case IF -> "palabra reservada 'if'";

case IGUAL -> "operador '='";

case IGUAL_IGUAL -> "operador '=='";

case INT -> "tipo 'int'";

case LLAVE_DER -> "'}'";

case LLAVE_IZQ -> "'{'";

case MAS -> "operador '+'";

case MAYOR_IGUAL -> "operador '>='";

case MAYOR_QUE -> "operador '>'";

case MENOR_IGUAL -> "operador '<='";

case MENOR_QUE -> "operador '<'";

case MENOS -> "operador '-'";

case MODULO -> "operador '%'";

case MULTIPLICACION -> "operador '*'";

case NO_IGUAL -> "operador '!='";

case NOT -> "operador '!'";

case NUMERO -> "número";


case OR -> "operador '||'";

case PARENTESIS_DER -> "')'";

case PARENTESIS_IZQ -> "'('";

case PUBLIC -> "modificador 'public'";

case PUNTO -> "'.'";

case PUNTO_COMA -> "';'";

case RETURN -> "palabra reservada 'return'";

case STATIC -> "modificador 'static'";

case STRING -> "tipo 'String'";

case SWITCH -> "palabra reservada 'switch'";

case TRUE -> "literal 'true'";

case VOID -> "tipo 'void'";

case WHILE -> "palabra reservada 'while'";

};

package analizadores;

public class Token {

private final TipoToken tipo;

private final String valor;

private final int linea;

private final int columna;

/**

* Constructor para crear un nuevo token

* @param tipo El tipo de token


* @param valor El valor o lexema del token

* @param linea La línea donde se encontró el token

* @param columna La columna donde se encontró el token

*/

public Token(TipoToken tipo, String valor, int linea, int columna) {

this.tipo = tipo;

this.valor = valor;

this.linea = linea;

this.columna = columna;

/**

* @return El tipo de token

*/

public TipoToken obtenerTipo() {

return tipo;

/**

* @return El valor o lexema del token

*/

public String obtenerValor() {

return valor;

/**

* @return La línea donde se encontró el token


*/

public int obtenerLinea() {

return linea;

/**

* @return La columna donde se encontró el token

*/

public int obtenerColumna() {

return columna;

/**

* Representación en cadena del token

* @return Una cadena con la información del token

*/

@Override

public String toString() {

return String.format("Token{tipo=%s, valor='%s', línea=%d, columna=%d}",

tipo, valor, linea, columna);

También podría gustarte