aboutsummaryrefslogtreecommitdiff
path: root/compilador/lexer.py
diff options
context:
space:
mode:
Diffstat (limited to 'compilador/lexer.py')
-rw-r--r--compilador/lexer.py205
1 files changed, 205 insertions, 0 deletions
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))