From 032fe000cfc2b36dc9c1f00c734fada41133403e Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 22 Nov 2022 09:02:46 -0600 Subject: Se implementa semáforo (fases de compilación) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compilador/lexer.py | 21 ++++----- compilador/main.py | 49 +++++++++++++++++---- compilador/parser.py | 10 +++-- compilador/tabla.py | 11 ++++- interfaz/main.py | 122 +++++++++++++++++++++++++++++++++++++++------------ 5 files changed, 161 insertions(+), 52 deletions(-) diff --git a/compilador/lexer.py b/compilador/lexer.py index bc2b14a..8bb7c13 100644 --- a/compilador/lexer.py +++ b/compilador/lexer.py @@ -34,7 +34,7 @@ class Selector(Enum): ENTERO = 5 class Lexer: - def __init__(self, data, input_file): + def __init__(self, input_file: str): self.tabla = TablaLex() self.numlinea = 1 self.selector = Selector.NINGUNO @@ -44,26 +44,23 @@ class Lexer: self.recol_operador = '' self.recol_ident = '' self.recol_entero = '' - self.data = data - self.tabla_file = None - if input_file: - self.tabla_file = input_file + '.tab' + self.input_file = input_file + with open(input_file) as f: + self.data = f.read() def inicio(self): for l in self.data.splitlines(): for c in l + "\n": r = self.procesar(c) - if r == Control.ERROR: exit(1) + if r == Control.ERROR: return 1 while r != Control.SIGUIENTE: r = self.procesar(c) - if r == Control.ERROR: exit(1) + if r == Control.ERROR: return 1 self.numlinea += 1 - # Imprimir tabla de símbolos - if self.tabla_file: - self.tabla.exportar(self.tabla_file) - Parser(self.tabla).inicio() - + # Exportar tabla de símbolos + self.tabla.exportar(self.input_file + '.tab') + return 0 def procesar(self, c): # if c != "\t" and c != "\n": diff --git a/compilador/main.py b/compilador/main.py index 186ca83..98e23c9 100644 --- a/compilador/main.py +++ b/compilador/main.py @@ -1,21 +1,30 @@ -import sys, getopt +import sys, getopt, os, traceback +from enum import Enum from tkinter import * from tkinter import ttk, filedialog from lexer import * +class Step(Enum): + LEXICO = 0 + SINTACTICO = 1 + SEMANTICO = 2 + class Main: input_file = None output_file = None output_table = False + step = None def print_help (self, arg0): print("Uso: % s -i entrada.es -o salida.es" % arg0) - print(" % s -i entrada.es -o salida.es -t") + print(" % s -i entrada.es -o salida.es [-l|-p|-s] [-t]" % arg0) print(" % s -h" % arg0) def main(self, argv): try: - opts, args = getopt.getopt(argv[1:], "hi:o:t", ["input=", "output=", "table"]) + opts, args = getopt.getopt(argv[1:], "hi:o:lpst", [ + "input=", "output=", "lex", "parse", "semantic", "table" + ]) except getopt.GetoptError as err: print(err) print_help(argv[0]); @@ -30,16 +39,40 @@ class Main: self.output_file = a elif o in ("-t", "--table"): self.output_table = True + elif o in ("-l", "--lex"): + self.step = Step.LEXICO + elif o in ("-p", "--parse"): + self.step = Step.SINTACTICO + elif o in ("-s", "--semantic"): + self.step = Step.SEMANTICO else: assert False, "opción desconocida" if self.input_file and self.output_file: - with open(self.input_file) as f: - data = f.read() - if self.output_table: - Lexer(data, self.input_file).inicio() + table_file = self.input_file + '.tab' + delete_tab = not self.step and not self.output_table and not os.path.exists(table_file) + try: + if self.step == Step.LEXICO: + sys.exit(Lexer(self.input_file).inicio()) + elif self.step == Step.SINTACTICO: + sys.exit(Parser(self.input_file).inicio()) + elif self.step == Step.SEMANTICO: + print("NOT IMPLEMENTED") + sys.exit(1) else: - Lexer(data, None).inicio() + if Lexer(self.input_file).inicio() != 0: + raise Exception("Error léxico") + if Parser(self.input_file).inicio() != 0: + raise Exception("Error sintáctico") + except Exception as e: + traceback.print_exception(type(e), e, e.__traceback__) + sys.exit(1) + # Borrar tabla de símbolos + if delete_tab: + os.remove(table_file) + else: + self.print_help(argv[0]) + sys.exit(2) if __name__ == "__main__": Main().main(sys.argv) diff --git a/compilador/parser.py b/compilador/parser.py index 6c6d223..951b517 100644 --- a/compilador/parser.py +++ b/compilador/parser.py @@ -23,24 +23,26 @@ class Selector(Enum): FUNCION = 7 class Parser: - def __init__(self, tabla): + def __init__(self, input_file: str): self.arbol = Arbol() self.pila_selector = [ [Selector.NINGUNO, []] # selector, recolector ] self.pila_arbol = [self.arbol.raiz] self.expresion = None - self.tabla = tabla + self.tabla = TablaLex() + self.tabla.importar(input_file + '.tab') def inicio (self): for t in self.tabla.tabla: r = self.procesar(t) - if r == Control.ERROR: exit(1) + if r == Control.ERROR: return 1 while r != Control.SIGUIENTE: r = self.procesar(t) - if r == Control.ERROR: exit(1) + if r == Control.ERROR: return 1 print(str(self.arbol)) + return 0 def procesar (self, t: LexToken): if len(self.pila_selector) == 0: diff --git a/compilador/tabla.py b/compilador/tabla.py index 637b9a6..ebe6225 100644 --- a/compilador/tabla.py +++ b/compilador/tabla.py @@ -70,7 +70,7 @@ class TablaLex: data.append({ 'tipo': t.tipo, 'nombre': t.nombre, - 'valor': str(t.valor), + 'valor': t.valor, 'numlinea': t.numlinea }) output = json.dumps(data) @@ -80,6 +80,15 @@ class TablaLex: f.truncate(0) f.write(output) + def importar(self, input_file): + with open(input_file, 'r') as f: + data = json.loads(f.read()) + for t in data: + self.insertar(LexToken(t['tipo'], + t['nombre'], + t['valor'], + t['numlinea'])) + def __str__(self): output = "" for t in self.tabla: diff --git a/interfaz/main.py b/interfaz/main.py index d59241d..b6c5ac9 100644 --- a/interfaz/main.py +++ b/interfaz/main.py @@ -24,9 +24,9 @@ class Semaforo(Gtk.DrawingArea): if color == self.Color.VERDE: self.set_draw_func(self.dibujar_sem_verde, None) elif color == self.Color.AMARILLO: - self.set_draw_func(self.dibujar_sem_rojo, None) - elif color == self.Color.ROJO: self.set_draw_func(self.dibujar_sem_amarillo, None) + elif color == self.Color.ROJO: + self.set_draw_func(self.dibujar_sem_rojo, None) else: self.set_draw_func(self.dibujar_sem_ninguno, None) @@ -100,6 +100,7 @@ class MainWindow(Gtk.ApplicationWindow): self.save_button = Gtk.Button(label='Guardar') self.save_button.set_icon_name('document-save-symbolic') + self.save_button.set_sensitive(False) self.save_button.connect('clicked', self.guardar_archivo) header.pack_start(self.save_button) @@ -140,6 +141,7 @@ class MainWindow(Gtk.ApplicationWindow): self.grid.attach(scrolled_win, 0, 0, 1, 1) self.sourcebuf = GtkSource.Buffer() + self.sourcebuf.connect('changed', self.edito_codigo) self.sourceview = GtkSource.View.new_with_buffer(self.sourcebuf) self.sourceview.set_show_line_numbers(True) self.sourceview.set_auto_indent(True) @@ -227,14 +229,8 @@ class MainWindow(Gtk.ApplicationWindow): notebook.append_page(semgrid, Gtk.Label.new('Semáforo')) - def analisis_lexico(self, button): - print("analisis_lexico(...)") - - def analisis_sintactico(self, button): - print("analisis_sintactico(...)") - - def analisis_semantico(self, button): - print("analisis_semantico(...)") + def edito_codigo(self, buffer): + self.reset_semaforos() def abrir_archivo(self, button): self.open_dialog = Gtk.FileChooserNative.new( @@ -252,8 +248,10 @@ class MainWindow(Gtk.ApplicationWindow): with open(self.input_file) as f: data = f.read() self.sourcebuf.set_text(data) + self.save_button.set_sensitive(True) self.run_button.set_sensitive(True) self.btn_lexico.set_sensitive(True) + self.sem_lexico.set_color(Semaforo.Color.AMARILLO) def guardar_archivo(self, button): if self.input_file: @@ -284,30 +282,89 @@ Tecnológico Nacional de México en Celaya''') self.about_dialog.set_logo_icon_name('applications-development') self.about_dialog.show() + def analisis_lexico(self, button): + self.guardar_archivo(None) + self.limpiar_tabla() + self.reset_semaforos() + result = subprocess.run([ + 'python', compilador_dir, + '-i', self.input_file, + '-o', self.output_file, + '-l' + ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = result.stdout.decode('utf-8') + self.msgbuf.set_text(output) + + if result.returncode == 0: + self.sem_lexico.set_color(Semaforo.Color.VERDE) + self.sem_sintactico.set_color(Semaforo.Color.AMARILLO) + self.btn_sintactico.set_sensitive(True) + self.llenar_tabla() + else: + self.sem_lexico.set_color(Semaforo.Color.ROJO) + + def analisis_sintactico(self, button): + self.limpiar_tabla() + self.sem_semantico.set_color(Semaforo.Color.NINGUNO) + self.btn_semantico.set_sensitive(False) + result = subprocess.run([ + 'python', compilador_dir, + '-i', self.input_file, + '-o', self.output_file, + '-p' + ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = result.stdout.decode('utf-8') + self.msgbuf.set_text(output) + + if result.returncode == 0: + self.sem_sintactico.set_color(Semaforo.Color.VERDE) + self.sem_semantico.set_color(Semaforo.Color.AMARILLO) + self.btn_semantico.set_sensitive(True) + self.llenar_tabla() + else: + self.sem_sintactico.set_color(Semaforo.Color.ROJO) + self.btn_sintactico.set_sensitive(False) + + def analisis_semantico(self, button): + self.limpiar_tabla() + result = subprocess.run([ + 'python', compilador_dir, + '-i', self.input_file, + '-o', self.output_file, + '-s' + ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = result.stdout.decode('utf-8') + self.msgbuf.set_text(output) + + if result.returncode == 0: + self.sem_semantico.set_color(Semaforo.Color.VERDE) + self.llenar_tabla() + else: + self.sem_semantico.set_color(Semaforo.Color.ROJO) + def correr(self, button): self.guardar_archivo(None) + self.reset_semaforos() self.limpiar_tabla() - if self.input_file: - result = subprocess.run([ - 'python', compilador_dir, - '-i', self.input_file, - '-o', self.output_file, - '-t' - ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - output = result.stdout.decode('utf-8') - self.msgbuf.set_text(output) - - if result.returncode == 0: - # Tabla de símbolos - with open(self.input_file + '.tab', 'r') as f: - data = f.read() - self.llenar_tabla(data) + result = subprocess.run([ + 'python', compilador_dir, + '-i', self.input_file, + '-o', self.output_file, + '-t' + ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output = result.stdout.decode('utf-8') + self.msgbuf.set_text(output) + + if result.returncode == 0: + self.llenar_tabla() def limpiar_tabla(self): for i in range(4): self.tablagrid.remove_column(0) - def llenar_tabla(self, data): + def llenar_tabla(self): + with open(self.input_file + '.tab', 'r') as f: + data = f.read() tabla = json.loads(data) label_linea = Gtk.Label.new(None) label_linea.set_markup('Línea') @@ -327,7 +384,18 @@ Tecnológico Nacional de México en Celaya''') self.tablagrid.attach(Gtk.Label.new(t['tipo']), 1, row, 1, 1) self.tablagrid.attach(Gtk.Label.new(t['nombre']), 2, row, 1, 1) self.tablagrid.attach(Gtk.Label.new(str(t['valor'])), 3, row, 1, 1) - + + def reset_semaforos(self): + if self.input_file: + self.sem_lexico.set_color(Semaforo.Color.AMARILLO) + self.btn_lexico.set_sensitive(True) + else: + self.sem_lexico.set_color(Semaforo.Color.NINGUNO) + self.btn_lexico.set_sensitive(False) + self.sem_sintactico.set_color(Semaforo.Color.NINGUNO) + self.btn_sintactico.set_sensitive(False) + self.sem_semantico.set_color(Semaforo.Color.NINGUNO) + self.btn_semantico.set_sensitive(False) def on_activate(app): win = MainWindow() -- cgit v1.2.3