aboutsummaryrefslogtreecommitdiff
path: root/compilador
diff options
context:
space:
mode:
Diffstat (limited to 'compilador')
-rw-r--r--compilador/arbol.py26
-rw-r--r--compilador/automatas/automata_cadenas.py43
-rw-r--r--compilador/automatas/automata_caracteres.py51
-rw-r--r--compilador/automatas/automata_enteros.py58
-rw-r--r--compilador/automatas/automata_flotantes.py78
-rw-r--r--compilador/automatas/automata_identificadores.py36
-rw-r--r--compilador/automatas/automata_operadores.py96
-rw-r--r--compilador/lexer.py205
-rw-r--r--compilador/main.py38
-rw-r--r--compilador/parser.py230
-rw-r--r--compilador/shared.py7
-rw-r--r--compilador/tabla.py70
12 files changed, 938 insertions, 0 deletions
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