diff options
author | Iván Ávalos <avalos@disroot.org> | 2022-11-15 00:34:55 -0600 |
---|---|---|
committer | Iván Ávalos <avalos@disroot.org> | 2022-11-15 00:34:55 -0600 |
commit | a55cd744c6dae4bba01ec83c6d3603e4ec0627a3 (patch) | |
tree | 70e62cfdc755aa1b97ea9e6eaafec23377e95164 | |
parent | de272f939f2ae0266a4ee363a854558ace5a59e2 (diff) | |
download | javanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.tar.gz javanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.tar.bz2 javanol-a55cd744c6dae4bba01ec83c6d3603e4ec0627a3.zip |
Primeras fases de análisis sintáctico
-rw-r--r-- | arbol.py | 26 | ||||
-rw-r--r-- | lexer.py | 45 | ||||
-rw-r--r-- | main.py | 2 | ||||
-rw-r--r-- | parser.py | 203 | ||||
-rw-r--r-- | shared.py | 7 | ||||
-rw-r--r-- | tabla.py (renamed from symbol.py) | 0 |
6 files changed, 260 insertions, 23 deletions
diff --git a/arbol.py b/arbol.py new file mode 100644 index 0000000..7abcbe0 --- /dev/null +++ b/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" @@ -1,10 +1,13 @@ from enum import Enum -from symbol import LexToken, TablaLex, tokens +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', @@ -29,24 +32,21 @@ class Selector(Enum): COMMENT = 4 ENTERO = 5 -class Control(Enum): - SIGUIENTE = 0 - REPETIR = 1 - ERROR = 2 - class Lexer: - tabla = TablaLex() - numlinea = 1 - selector = Selector.NINGUNO - recol_string = '' - recol_caracter = '' - recol_comentario = '' - recol_operador = '' - recol_ident = '' - recol_entero = '' - - def inicio_lexer(self, data): - for l in data.splitlines(): + 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 @@ -57,10 +57,12 @@ class Lexer: # 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 c != "\t" and c != "\n": + # print (c + ' (' + str(self.selector) + ')') if self.selector == Selector.NINGUNO: # Entrada a string @@ -89,8 +91,7 @@ class Lexer: self.recol_operador = c return Control.SIGUIENTE # Entrada a tokens simples - elif (c == '{' or c == '}' or c == '(' or c == ')' or - c == ',' or c == '.' or c == ';' or (c == '*' and self.recol_comentario == '')): + elif c in otros_tokens or (c == '*' and self.recol_comentario == ''): self.insertar_tabla(c, None, None) return Control.SIGUIENTE @@ -27,7 +27,7 @@ class Main: def compilar_programa(self): self.output_file = filedialog.asksaveasfilename() data = self.text.get('1.0', 'end-1c') - Lexer().inicio_lexer(data) + Lexer(data).inicio() def ejecutar_programa(self): print('ejecutar_programa()') diff --git a/parser.py b/parser.py new file mode 100644 index 0000000..7b48bbd --- /dev/null +++ b/parser.py @@ -0,0 +1,203 @@ +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'] + +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() + 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): + return + + 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 in operadores: + recol.append(t) + elif tipo_ultimo in operadores and t in valores: + recol.append(t) + elif tipo_ultimo in valores and t in valores: + print('Error: se esperaba un operador') + return Control.ERROR + elif tipo_ultimo in operadores and t in operadores: + print('Error: se esperaba un identificador o una literal') + return Control.ERROR + else: + self.expresion = recol + 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/shared.py b/shared.py new file mode 100644 index 0000000..e356255 --- /dev/null +++ b/shared.py @@ -0,0 +1,7 @@ +from enum import Enum + +class Control(Enum): + ERROR = -1 + SIGUIENTE = 0 + REPETIR = 1 + TERMINAR = 2 |