From c78465010691d45f5e5bfa6a36a96800d30962ac Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Tue, 15 Nov 2022 08:08:06 -0600 Subject: Se elimina código de interfaz y se reorganizan directorios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compilador/arbol.py | 26 +++ compilador/automatas/automata_cadenas.py | 43 +++++ compilador/automatas/automata_caracteres.py | 51 +++++ compilador/automatas/automata_enteros.py | 58 ++++++ compilador/automatas/automata_flotantes.py | 78 ++++++++ compilador/automatas/automata_identificadores.py | 36 ++++ compilador/automatas/automata_operadores.py | 96 ++++++++++ compilador/lexer.py | 205 ++++++++++++++++++++ compilador/main.py | 38 ++++ compilador/parser.py | 230 +++++++++++++++++++++++ compilador/shared.py | 7 + compilador/tabla.py | 70 +++++++ 12 files changed, 938 insertions(+) create mode 100644 compilador/arbol.py create mode 100644 compilador/automatas/automata_cadenas.py create mode 100644 compilador/automatas/automata_caracteres.py create mode 100644 compilador/automatas/automata_enteros.py create mode 100644 compilador/automatas/automata_flotantes.py create mode 100644 compilador/automatas/automata_identificadores.py create mode 100644 compilador/automatas/automata_operadores.py create mode 100644 compilador/lexer.py create mode 100644 compilador/main.py create mode 100644 compilador/parser.py create mode 100644 compilador/shared.py create mode 100644 compilador/tabla.py (limited to 'compilador') diff --git a/compilador/arbol.py b/compilador/arbol.py new file mode 100644 index 0000000..7abcbe0 --- /dev/null +++ b/compilador/arbol.py @@ -0,0 +1,26 @@ +class Nodo: + def __init__(self, dato = None): + self.dato = dato + self.hijos = [] + + def print(self, n = 0): + s = ' ' * n + 'Nodo:' + "\n" + s += ' ' * n + "dato = " + str(self.dato) + "\n" + s += ' ' * n + "hijos =\n" + for h in self.hijos: + s += h.print(n + 1) + s += "\n" + return s + + def __str__(self): + return self.print() + + +class Arbol: + def __init__(self, raiz: Nodo = Nodo()): + self.raiz = raiz + + def __str__(self): + if self.raiz: + return str(self.raiz) + return "None" diff --git a/compilador/automatas/automata_cadenas.py b/compilador/automatas/automata_cadenas.py new file mode 100644 index 0000000..dc15a98 --- /dev/null +++ b/compilador/automatas/automata_cadenas.py @@ -0,0 +1,43 @@ +class automata_cad: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(str[i]) + else: + return 0 + if self.stateN == 2 + return 1 + else: + return 0 + + def start(self, c): + if (c == '\"'): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self,c): + if (c != '\"'): + self.stateN = 1 + else: + self.stateN = 2 + + def state2(self,c): + self.stateN = -1 + + def verified(self,token) + { + if isAccepted(token): + return true + else: + return false + } \ No newline at end of file diff --git a/compilador/automatas/automata_caracteres.py b/compilador/automatas/automata_caracteres.py new file mode 100644 index 0000000..139f86b --- /dev/null +++ b/compilador/automatas/automata_caracteres.py @@ -0,0 +1,51 @@ +class automata_car: + stateN = 0 + + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + else: + return 0 + if self.stateN == 3: + return 1 + else: + return 0 + + def start(self,c): + if (c == '\''): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self,c): + if (c != '\''): + self.stateN = 2 + else: + self.stateN = 3 + + def state2(self,c): + if (c == '\''): + self.stateN = 3 + else: + self.stateN = -1 + + def state3(self,c): + self.stateN = -1 + + def verified(self,token){ + if isAccepted(token): + return true + else: + return false + } diff --git a/compilador/automatas/automata_enteros.py b/compilador/automatas/automata_enteros.py new file mode 100644 index 0000000..c97659e --- /dev/null +++ b/compilador/automatas/automata_enteros.py @@ -0,0 +1,58 @@ +class automata_ent: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + else: + return 0 + if self.stateN == 2 or self.stateN == 3: + return 1 + else: + return 0 + + + def start(self,c): + if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else if (c == '0'): + self.stateN = 2 + else if (c == '-'): + self.stateN = 1 + else + self.stateN = -1 + + def state1(self,c): + if (c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state2(self,c): + self.stateN = -1 + + def state3(self,c) + { + if c.isdigit(): + self.stateN = 3 + else: + self.stateN = -1 + } + + def verified(self,token) + { + if isAccepted(token): + return true + else: + return false + } \ No newline at end of file diff --git a/compilador/automatas/automata_flotantes.py b/compilador/automatas/automata_flotantes.py new file mode 100644 index 0000000..b7be7d8 --- /dev/null +++ b/compilador/automatas/automata_flotantes.py @@ -0,0 +1,78 @@ +class automata_flot: + stateN = 0 + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + if self.stateN == 4: + self.state4(_str[i]) + if self.stateN == 5: + self.state5(_str[i]) + else: + return 0 + + if self.stateN == 5: + return 1 + else: + return 0 + + def start(self, c): + if (c == '0'): + self.stateN = 1 + else if(c == '-'): + self.stateN = 2 + else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or + c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state1(self,c): + if (c == '.'): + self.stateN = 4 + else: + self.stateN = -1 + + def state2(self,c): + if(c == '0'): + self.stateN = 1 + else if(c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or + c == '6' or c == '7' or c == '8' or c == '9'): + self.stateN = 3 + else: + self.stateN = -1 + + def state3(self,c): + if(c == '.'): + self.stateN = 4 + else if c.isdigit(): + stateN = 3 + else: + self.stateN = -1 + + def state4(self,c): + if c.isdigit(): + self.stateN = 5 + else: + self.stateN = -1 + + def state5(self,c): + if c.isdigit(): + self.stateN = 5 + else: + self.stateN = -1 + + def verified(self,token): + if isAccepted(token) + return true + else: + return false \ No newline at end of file diff --git a/compilador/automatas/automata_identificadores.py b/compilador/automatas/automata_identificadores.py new file mode 100644 index 0000000..c26adfb --- /dev/null +++ b/compilador/automatas/automata_identificadores.py @@ -0,0 +1,36 @@ +class automata_ident: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + else: + return 0 + if self.stateN == 1: + return 1 + else: + return 0 + + def start(self, c): + if (c.isalpha() or c == '_'): + self.stateN = 1 + else: + self.stateN = -1 + + def state1(self, c): + if (c.isalpha() or c == '_' or c.isdigit()): + self.stateN = 1 + else: + self.stateN = -1 + + def no_es_main(self,token): + if isAccepted(token): + return true + else: + return false \ No newline at end of file diff --git a/compilador/automatas/automata_operadores.py b/compilador/automatas/automata_operadores.py new file mode 100644 index 0000000..af10e61 --- /dev/null +++ b/compilador/automatas/automata_operadores.py @@ -0,0 +1,96 @@ + +class automata_ope: + stateN = 0 + + def isAccepted(self, _str): + i = len(_str) + _len = len(_str) + + for i in range(len): + if self.stateN == 0: + self.start(_str[i]) + if self.stateN == 1: + self.state1(_str[i]) + if self.stateN == 2: + self.state2(_str[i]) + if self.stateN == 3: + self.state3(_str[i]) + if self.stateN == 4: + self.start4(_str[i]) + if self.stateN == 5: + self.state5(_str[i]) + if self.stateN == 6: + self.state6(_str[i]) + if self.stateN == 7: + self.state7(_str[i]) + if self.stateN == 8: + self.state8(_str[i]) + else: + return 0 + if (self.stateN == 1 or self.stateN == 7 or self.stateN == 8 or self.stateN == 2 or self.stateN == 3 or self.stateN == 6): + return 1 + else: + return 0 + + def start(self,c): + if(c == '=' or c == '>' or c == '<' or c == '/' or c == '*' or c == '%' or c == '!'): + self.stateN = 1 + else if(c == '&'): + self.stateN = 4 + else if(c == '|'): + self.stateN = 5 + else if(c == '-'): + selfstateN = 6 + else if(c == '+'): + selfstateN = 3 + else: + self.stateN = -1 + + def state1(self,c): + if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state2(self,c): + self.stateN = -1 + + def state3(self,c): + if(c == '+'): + self.stateN = 7 + else if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state4(self,c): + if(c == '&'): + self.stateN = 2 + else: + self.stateN = -1 + + def state5(self,c): + if(c == '|'): + self.stateN = 2 + else: + self.stateN = -1 + + def state6(self,c): + if(c == '-'): + self.stateN = 8 + else if(c == '='): + self.stateN = 2 + else: + self.stateN = -1 + + def state7(self,c): + self.stateN = -1 + + def state8(self,c): + self.stateN = -1 + + def verified(self,token): + if isAccepted(token): + return true + else: + return false \ No newline at end of file diff --git a/compilador/lexer.py b/compilador/lexer.py new file mode 100644 index 0000000..1952a16 --- /dev/null +++ b/compilador/lexer.py @@ -0,0 +1,205 @@ +from enum import Enum +from tabla import LexToken, TablaLex, tokens +from parser import Parser +from shared import Control + +op_compuestos = ['>=', '<=', '==', '!=', '&&', '||', '++', '--'] +op_simples_a = ['=', '+', '-', '&', '|'] # pueden ir al final del op compuesto +op_simples_b = ['!', '<', '>'] # solo pueden ir al inicio del op compuesto +op_simples = op_simples_a + op_simples_b +otros_tokens = ['{', '}', '(', ')', ',', '.', ';'] +reservadas = { + 'booleano': 'BOOLEAN', + 'detener': 'BREAK', + 'cadena': 'STRING', + 'caracter': 'CHAR', + 'sino': 'ELSE', + 'porcada': 'FOR', + 'si': 'IF', + 'entero': 'INT', + 'imprimir': 'PRINT', + 'leer': 'READ', + 'retorna': 'RETURN', + 'vacio': 'VOID', + 'mientras': 'WHILE' +} + +class Selector(Enum): + NINGUNO = 0 + STRING_LIT = 1 + CHAR_LIT = 2 + ID_RESERVADA = 3 + COMMENT = 4 + ENTERO = 5 + +class Lexer: + def __init__(self, data): + self.tabla = TablaLex() + self.numlinea = 1 + self.selector = Selector.NINGUNO + self.recol_string = '' + self.recol_caracter = '' + self.recol_comentario = '' + self.recol_operador = '' + self.recol_ident = '' + self.recol_entero = '' + self.data = data + + def inicio(self): + for l in self.data.splitlines(): + for c in l + "\n": + r = self.procesar(c) + if r == 2: return + while r != Control.SIGUIENTE: + r = self.procesar(c) + if r == Control.ERROR: return + self.numlinea += 1 + + # Imprimir tabla de símbolos + print (str(self.tabla)) + Parser(self.tabla).inicio() + + + def procesar(self, c): + # if c != "\t" and c != "\n": + # print (c + ' (' + str(self.selector) + ')') + + if self.selector == Selector.NINGUNO: + # Entrada a string + if c == '"': + self.selector = Selector.STRING_LIT + return Control.SIGUIENTE + # Entrada a caracter + elif c == '\'': + self.selector = Selector.CHAR_LIT + return Control.SIGUIENTE + # Entrada a id o palabra reservada + elif c.isalpha() or c == '_': + self.selector = Selector.ID_RESERVADA + # Entrada a entero + elif c.isdigit(): + self.selector = Selector.ENTERO + # Entrada a comentario + elif c == '/': + self.recol_comentario = '/' + # Entrada a operador (simple o compuesto) + elif c in op_simples_a and self.recol_operador == '': + self.recol_operador = c + return Control.SIGUIENTE + # Entrada a operador (simple) + elif c in op_simples_b: + self.recol_operador = c + return Control.SIGUIENTE + # Entrada a tokens simples + elif c in otros_tokens or (c == '*' and self.recol_comentario == ''): + self.insertar_tabla(c, None, None) + return Control.SIGUIENTE + + # Apertura de comentario + if self.recol_comentario == '/' and c == '*': + self.selector = Selector.COMMENT + self.recol_comentario = '' + return Control.SIGUIENTE + + # Apertura de operador compuesto + if len(self.recol_operador) > 0: + rc = self.recol_operador + c + if rc in op_compuestos: + # Operador compuesto + self.insertar_tabla(rc, None, None) + self.recol_operador = '' + return Control.SIGUIENTE + else: + # Operador simple + self.insertar_tabla(self.recol_operador, None, None) + if c in op_simples: + self.insertar_tabla(c, None, None) + self.recol_operador = '' + return Control.SIGUIENTE + + # Cadenas de texto + if self.selector == Selector.STRING_LIT: + return self.procesar_cadena(c) + + # Caracteres + if self.selector == Selector.CHAR_LIT: + return self.procesar_caracter(c) + + # Comentarios + if self.selector == Selector.COMMENT: + return self.procesar_comentario(c) + + # Identificador o palabra reservada + if self.selector == Selector.ID_RESERVADA: + return self.procesar_identificador(c) + + # Enteros + if self.selector == Selector.ENTERO: + return self.procesar_entero(c) + + return Control.SIGUIENTE + + def procesar_cadena(self, c): + if c == '"': + self.insertar_tabla('STRING_LIT', None, self.recol_string) + self.selector = Selector.NINGUNO + self.recol_string = '' + else: + self.recol_string += c + return Control.SIGUIENTE + + def procesar_caracter(self, c): + if len(self.recol_caracter) > 1: + print ('Error: más de un caracter en una literal de caracter') + return Control.ERROR + if c == '\'': + if len(self.recol_caracter) == 0: + print ('Error: literal de caracter vacía') + return Control.ERROR + self.insertar_tabla('CHAR_LIT', None, self.recol_caracter) + self.selector = Selector.NINGUNO + self.recol_caracter = '' + else: + self.recol_caracter += c + return Control.SIGUIENTE + + def procesar_comentario(self, c): + if c == '*': + self.recol_comentario = c + elif self.recol_comentario == '*': + if c == '/': + self.selector = Selector.NINGUNO + self.recol_comentario = '' + else: + self.recol_comentario = '' + return Control.SIGUIENTE + + def procesar_identificador(self, c): + if c.isalnum() or c == '_': + self.recol_ident += c + else: + if self.recol_ident in reservadas.keys(): + self.insertar_tabla(reservadas[self.recol_ident], None, None) + elif self.recol_ident == 'verdadero': + self.insertar_tabla('BOOLEAN_LIT', None, True) + elif self.recol_ident == 'falso': + self.insertar_tabla('BOOLEAN_LIT', None, False) + else: + self.insertar_tabla('IDENT', self.recol_ident, None) + self.recol_ident = '' + self.selector = Selector.NINGUNO + return Control.REPETIR + return Control.SIGUIENTE + + def procesar_entero(self, c): + if c.isdigit(): + self.recol_entero += c + else: + self.insertar_tabla('INT_LIT', None, int(self.recol_entero)) + self.recol_entero = '' + self.selector = Selector.NINGUNO + return Control.REPETIR + return Control.SIGUIENTE + + def insertar_tabla(self, token, nombre, valor): + self.tabla.insertar(LexToken(token, nombre, valor, self.numlinea)) diff --git a/compilador/main.py b/compilador/main.py new file mode 100644 index 0000000..c27c107 --- /dev/null +++ b/compilador/main.py @@ -0,0 +1,38 @@ +import sys, getopt +from tkinter import * +from tkinter import ttk, filedialog +from lexer import * + +class Main: + input_file = None + output_file = None + + def print_help (self, arg0): + print("Uso: % s -i entrada.ñ -o salida.ñ" % arg0) + print(" % s -h" % arg0) + + def main(self, argv): + try: + opts, args = getopt.getopt(argv[1:], "hi:o:", ["input=", "output="]) + except getopt.GetoptError as err: + print(err) + print_help(argv[0]); + sys.exit(2) + + for o, a in opts: + if o == "-h": + self.print_help (argv[0]) + elif o in ("-i", "--input"): + self.input_file = a + elif o in ("-o", "--output"): + self.output_file = a + else: + assert False, "opción desconocida" + + if self.input_file and self.output_file: + with open(self.input_file) as f: + data = f.read() + Lexer(data).inicio() + +if __name__ == "__main__": + Main().main(sys.argv) diff --git a/compilador/parser.py b/compilador/parser.py new file mode 100644 index 0000000..61ab21a --- /dev/null +++ b/compilador/parser.py @@ -0,0 +1,230 @@ +from enum import Enum +from tabla import LexToken, TablaLex, tokens +from arbol import Arbol, Nodo +from shared import Control +from pprint import pprint + +valores = ['IDENT', 'BOOLEAN_LIT', 'CHAR_LIT', 'INT_LIT', 'STRING_LIT'] + +operadores = [ + '>=', '<=', '==', '!=', '&&', '||', '++', '--', + '=', '+', '-', '&', '|', '!', '<', '>' +] + +class Selector(Enum): + NINGUNO = 0 + DEF_VARIABLE = 1 + DIRECTIVA = 2 + EXPRESION = 3 + IF = 4 + FOR = 5 + WHILE = 6 + FUNCION = 7 + +class Parser: + def __init__(self, tabla): + self.arbol = Arbol() + self.pila_selector = [ + [Selector.NINGUNO, []] # selector, recolector + ] + self.pila_arbol = [self.arbol.raiz] + self.expresion = None + self.tabla = tabla + + def inicio (self): + for t in self.tabla.tabla: + r = self.procesar(t) + if r == 2: return + while r != Control.SIGUIENTE: + r = self.procesar(t) + if r == Control.ERROR: return + + print(str(self.arbol)) + + def procesar (self, t: LexToken): + if len(self.pila_selector) == 0: + return Control.SIGUIENTE + + pprint (self.pila_selector[-1]) + + cima = self.pila_selector[-1] + + if cima[0] == Selector.NINGUNO: + # Entrada a definición de variable (o función) + if t.tipo in ['BOOLEAN', 'CHAR', 'INT', 'VOID']: + self.pila_selector.pop() + self.pila_selector.append([Selector.DEF_VARIABLE, [t]]) + return Control.SIGUIENTE + # Entrada a directiva del lenguaje + elif t.tipo in ['PRINT', 'READ', 'RETURN']: + self.pila_selector.pop() + self.pila_selector.append([Selector.DIRECTIVA, [t]]) + return Control.SIGUIENTE + # Entrada a expresión + elif t.tipo in valores: + self.pila_selector.pop() + self.pila_selector.append([Selector.EXPRESION, [t]]) + return Control.SIGUIENTE + # Entrada a if + elif t.tipo == 'IF': + self.pila_selector.pop() + self.pila_selector.append([Selector.IF, []]) + return Control.SIGUIENTE + # Entrada a for + elif t.tipo == 'FOR': + self.pila_selector.pop() + self.pila_selector.append([Selector.FOR, []]) + return Control.SIGUIENTE + # Entrada a while + elif t.tipo == 'WHILE': + self.pila_selector.pop() + self.pila_selector.append([Selector.WHILE, []]) + return Control.SIGUIENTE + + if cima[0] == Selector.DEF_VARIABLE: + return self.procesar_def_variable(t) + + if cima[0] == Selector.DIRECTIVA: + return self.procesar_directiva(t) + + if cima[0] == Selector.EXPRESION: + return self.procesar_expresion(t) + + if cima[0] == Selector.IF: + return self.procesar_if(t) + + if cima[0] == Selector.FOR: + return self.procesar_for(t) + + if cima[0] == Selector.WHILE: + return self.procesar_while(t) + + if cima[0] == Selector.FUNCION: + return self.procesar_funcion(t) + + return Control.SIGUIENTE + + def procesar_def_variable(self, t): + recol = self.pila_selector[-1][1] + + # tipo + if len(recol) == 1: + if t.tipo != 'IDENT': + print('Error: se esperaba identificador') + return Control.ERROR + recol.append(t) + return Control.SIGUIENTE + + # tipo + ident + if len(recol) == 2: + if t.tipo == ';': + self.pila_arbol[-1].hijos.append(Nodo({ + 'selector': Selector.DEF_VARIABLE, + 'tipo': recol[0].tipo, + 'nombre': recol[1].nombre + })) + self.pila_selector.pop() + self.pila_selector.append([Selector.NINGUNO, []]) + elif t.tipo == '=': + recol.append(t) + else: + print('Error: se esperaba `;` o `=`') + return Control.ERROR + return Control.SIGUIENTE + + # tipo + ident + = + if len(recol) == 3: + if t.tipo in valores: + self.pila_selector.append([Selector.EXPRESION, [t]]) + recol.append(t) + else: + print('Error: se esperaba una expresión') + return Control.ERROR + return Control.SIGUIENTE + + # tipo + ident + = + expr + if len(recol) == 4: + if t.tipo == ';': + self.pila_arbol[-1].hijos.append(Nodo({ + 'selector': Selector.DEF_VARIABLE, + 'tipo': recol[0].tipo, + 'nombre': recol[1].nombre, + 'valor': self.expresion + })) + self.expresion = None + self.pila_selector.pop() + self.pila_selector.append([Selector.NINGUNO, []]) + else: + print('Error: se esperaba `;`') + return Control.ERROR + + return Control.SIGUIENTE + + def procesar_directiva(self, t): + recol = self.pila_selector[-1][1] + + # directiva + if len(recol) == 1: + if t.tipo in valores: + self.pila_selector.append([Selector.EXPRESION, [t]]) + recol.append(t) + else: + print('Error: se esperaba una expresión') + return Control.ERROR + return Control.SIGUIENTE + + # directiva + expr + if len(recol) == 2: + if t.tipo == ';': + self.pila_arbol[-1].hijos.append(Nodo({ + 'selector': Selector.DIRECTIVA, + 'expresion': self.expresion + })) + self.expresion = None + self.pila_selector.pop() + self.pila_selector.append([Selector.NINGUNO, []]) + else: + print('Error: se esperaba `;`') + return Control.ERROR + + return Control.SIGUIENTE + + def procesar_expresion(self, t): + recol = self.pila_selector[-1][1] + tipo_ultimo = recol[-1].tipo + + if len(recol) == 1: + if tipo_ultimo in valores: + recol.append(recol[-1]) + else: + print('Error: se esperaba un identificador o una literal') + return Control.ERROR + + if tipo_ultimo in valores and t.tipo in operadores: + recol.append(t) + elif tipo_ultimo in operadores and t.tipo in valores: + recol.append(t) + elif tipo_ultimo in valores and t.tipo in valores: + print('Error: se esperaba un operador') + return Control.ERROR + elif tipo_ultimo in operadores and t.tipo in operadores: + print('Error: se esperaba un identificador o una literal') + return Control.ERROR + else: + self.expresion = recol[1:] + self.pila_selector.pop() + return Control.REPETIR + + return Control.SIGUIENTE + + def procesar_if(self, t): + return + + def procesar_for(self, t): + return + + def procesar_while(self, t): + return + + def procesar_funcion(self, t): + return diff --git a/compilador/shared.py b/compilador/shared.py new file mode 100644 index 0000000..e356255 --- /dev/null +++ b/compilador/shared.py @@ -0,0 +1,7 @@ +from enum import Enum + +class Control(Enum): + ERROR = -1 + SIGUIENTE = 0 + REPETIR = 1 + TERMINAR = 2 diff --git a/compilador/tabla.py b/compilador/tabla.py new file mode 100644 index 0000000..c8ca424 --- /dev/null +++ b/compilador/tabla.py @@ -0,0 +1,70 @@ +from enum import Enum +from dataclasses import dataclass +from typing import Any + +reservadas = [ + 'BOOLEAN', + 'BREAK', + 'CHAR', + 'DOUBLE', + 'ELSE', + 'FOR' + 'IDENT', + 'IF', + 'INT', + 'PRINT', + 'READ', + 'RETURN', + 'STRING', + 'VOID', + 'WHILE' +] + +literales = [ + 'BOOLEAN_LIT', + 'CHAR_LIT', + 'DOUBLE_LIT', + 'INT_LIT', + 'STRING_LIT' +] + +tokens = reservadas + literales + [ + '{', '}', '(', ')', ',', '\'', + '"', ';', '=', '*', '/', '+', + '-', '>', '<', '>=', '<=', '&&', + '||', '==', '!=', '++', '--', '//' +] + +@dataclass +class LexToken: + tipo: str + nombre: str + valor: Any + numlinea: int + + def __str__(self): + return "LexToken(%s,%s,%s,%i)" % ( + self.tipo, self.nombre, self.valor, self.numlinea + ) + +class TablaLex: + def __init__(self): + self.tabla = [] + + def insertar(self, tok: LexToken): + self.tabla.append(tok) + + def buscar(self, nombre: str): + return [t for t in self.tabla if t.nombre == nombre][0] + + def actualizar(self, nombre: str, tok: LexToken): + for i, t in enumerate(self.tabla): + if t.nombre == nombre: + self.tabla[i] = tok + return + + def __str__(self): + output = "" + for t in self.tabla: + output += str(t) + "\n" + return output -- cgit v1.2.3