aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lexer.py227
1 files changed, 129 insertions, 98 deletions
diff --git a/lexer.py b/lexer.py
index 0232645..5190a2e 100644
--- a/lexer.py
+++ b/lexer.py
@@ -2,13 +2,25 @@ from enum import Enum
from symbol import LexToken, TablaLex, tokens
op_compuestos = ['>=', '<=', '==', '!=', '&&', '||', '++', '--']
-op_simples_a = ['=', '+', '-', '&', '|']
-op_simples_b = ['!', '<', '>']
+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
+class Selector(Enum):
+ NINGUNO = 0
+ STRING_LIT = 1
+ CHAR_LIT = 2
+ ID_RESERVADA = 3
+ COMMENT = 4
+
+class Control(Enum):
+ SIGUIENTE = 0
+ REPETIR = 1
+ ERROR = 2
+
class Lexer:
tabla = TablaLex()
- selector = ''
+ selector = Selector.NINGUNO
recol_string = ''
recol_caracter = ''
recol_comentario = ''
@@ -17,52 +29,54 @@ class Lexer:
def inicio_lexer(self, data):
for c in data + "\n":
- r = self.procesar_caracter(c)
+ r = self.procesar(c)
if r == 2: return
- while r != 0:
+ while r != Control.SIGUIENTE:
print ('r = ' + str(r))
- r = self.procesar_caracter(c)
- if r == 2: return
+ r = self.procesar(c)
+ if r == Control.ERROR: return
# Imprimir tabla de símbolos
print (str(self.tabla))
- # c => caracter
- # return 0 => siguiente caracter
- # return 1 => repetir caracter
- # return 2 => error
- def procesar_caracter(self, c):
+ def procesar(self, c):
if c != "\t" and c != "\n":
- print (c + ' (' + self.selector + ')')
+ print (c + ' (' + str(self.selector) + ')')
- if self.selector == '':
- # Entradas a tokens
+ if self.selector == Selector.NINGUNO:
+ # Entrada a string
if c == '"':
- self.selector = 'STRING_LIT'
- return 0
+ self.selector = Selector.STRING_LIT
+ return Control.SIGUIENTE
+ # Entrada a caracter
elif c == '\'':
- self.selector = 'CHAR_LIT'
- return 0
+ self.selector = Selector.CHAR_LIT
+ return Control.SIGUIENTE
+ # Entrada a id o palabra reservada
elif c.isalpha() or c == '_':
- self.selector = 'ID/RESERVADA'
+ self.selector = Selector.ID_RESERVADA
+ # 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 0
+ return Control.SIGUIENTE
+ # Entrada a operador (simple)
elif c in op_simples_b:
self.recol_operador = c
- return 0
+ 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 == '')):
self.tabla.insertar(LexToken(c, None, None, 1))
- return 0
+ return Control.SIGUIENTE
# Apertura de comentario
if self.recol_comentario == '/' and c == '*':
- self.selector = 'COMMENT'
+ self.selector = Selector.COMMENT
self.recol_comentario = ''
- return 0
+ return Control.SIGUIENTE
# Apertura de operador compuesto
if len(self.recol_operador) > 0:
@@ -71,90 +85,107 @@ class Lexer:
# Operador compuesto
self.tabla.insertar(LexToken(rc, None, None, 1))
self.recol_operador = ''
- return 0
+ return Control.SIGUIENTE
else:
# Operador simple
self.tabla.insertar(LexToken(self.recol_operador, None, None, 1))
if c in op_simples:
self.tabla.insertar(LexToken(c, None, None, 1))
self.recol_operador = ''
- return 0
+ return Control.SIGUIENTE
# Cadenas de texto
- if self.selector == 'STRING_LIT':
- if c == '"':
- self.tabla.insertar(LexToken('STRING_LIT', None, self.recol_string, 1))
- self.selector = ''
- self.recol_string = ''
- else:
- self.recol_string += c
-
+ if self.selector == Selector.STRING_LIT:
+ return self.procesar_cadena(c)
+
# Caracteres
- if self.selector == 'CHAR_LIT':
- if len(self.recol_caracter) > 1:
- print ('Error: más de un caracter en una literal de caracter')
- return 2
- if c == '\'':
- if len(self.recol_caracter) == 0:
- print ('Error: literal de caracter vacía')
- return 2
- self.tabla.insertar(LexToken('CHAR_LIT', None, self.recol_caracter, 1))
- self.selector = ''
- self.recol_caracter = ''
- else:
- self.recol_caracter += c
+ if self.selector == Selector.CHAR_LIT:
+ return self.procesar_caracter(c)
# Comentarios
- if self.selector == 'COMMENT':
- if c == '*':
- self.recol_comentario = c
- elif self.recol_comentario == '*':
- if c == '/':
- self.selector = ''
- self.recol_comentario = ''
- else:
- self.recol_comentario = ''
+ if self.selector == Selector.COMMENT:
+ return self.procesar_comentario(c)
# Identificador o palabra reservada
- if self.selector == 'ID/RESERVADA':
- if c.isalnum() or c == '_':
- self.recol_ident += c
+ if self.selector == Selector.ID_RESERVADA:
+ return self.procesar_identificador(c)
+
+ return Control.SIGUIENTE
+
+ def procesar_cadena(self, c):
+ if c == '"':
+ self.tabla.insertar(LexToken('STRING_LIT', None, self.recol_string, 1))
+ 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.tabla.insertar(LexToken('CHAR_LIT', None, self.recol_caracter, 1))
+ 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:
- if self.recol_ident == 'booleano':
- self.tabla.insertar(LexToken('BOOLEAN', None, None, 1))
- elif self.recol_ident == 'detener':
- self.tabla.insertar(LexToken('BREAK', None, None, 1))
- elif self.recol_ident == 'byte':
- self.tabla.insertar(LexToken('BYTE', None, None, 1))
- elif self.recol_ident == 'caracter':
- self.tabla.insertar(LexToken('CHAR', None, None, 1))
- elif self.recol_ident == 'doble':
- self.tabla.insertar(LexToken('DOUBLE', None, None, 1))
- elif self.recol_ident == 'sino':
- self.tabla.insertar(LexToken('ELSE', None, None, 1))
- elif self.recol_ident == 'porcada':
- self.tabla.insertar(LexToken('FOR', None, None, 1))
- elif self.recol_ident == 'si':
- self.tabla.insertar(LexToken('IF', None, None, 1))
- elif self.recol_ident == 'entero':
- self.tabla.insertar(LexToken('INT', None, None, 1))
- elif self.recol_ident == 'imprimir':
- self.tabla.insertar(LexToken('PRINT', None, None, 1))
- elif self.recol_ident == 'leer':
- self.tabla.insertar(LexToken('READ', None, None, 1))
- elif self.recol_ident == 'retorna':
- self.tabla.insertar(LexToken('RETURN', None, None, 1))
- elif self.recol_ident == 'vacio':
- self.tabla.insertar(LexToken('VOID', None, None, 1))
- elif self.recol_ident == 'mientras':
- self.tabla.insertar(LexToken('WHILE', None, None, 1))
- elif self.recol_ident == 'verdadero':
- self.tabla.insertar(LexToken('BOOLEAN_LIT', None, True, 1))
- elif self.recol_ident == 'falso':
- self.tabla.insertar(LexToken('BOOLEAN_LIT', None, False, 1))
- else:
- self.tabla.insertar(LexToken('IDENT', self.recol_ident, None, 1))
- self.recol_ident = ''
- self.selector = ''
- return 1
- return 0
+ 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 == 'booleano':
+ self.tabla.insertar(LexToken('BOOLEAN', None, None, 1))
+ elif self.recol_ident == 'detener':
+ self.tabla.insertar(LexToken('BREAK', None, None, 1))
+ elif self.recol_ident == 'byte':
+ self.tabla.insertar(LexToken('BYTE', None, None, 1))
+ elif self.recol_ident == 'caracter':
+ self.tabla.insertar(LexToken('CHAR', None, None, 1))
+ elif self.recol_ident == 'doble':
+ self.tabla.insertar(LexToken('DOUBLE', None, None, 1))
+ elif self.recol_ident == 'sino':
+ self.tabla.insertar(LexToken('ELSE', None, None, 1))
+ elif self.recol_ident == 'porcada':
+ self.tabla.insertar(LexToken('FOR', None, None, 1))
+ elif self.recol_ident == 'si':
+ self.tabla.insertar(LexToken('IF', None, None, 1))
+ elif self.recol_ident == 'entero':
+ self.tabla.insertar(LexToken('INT', None, None, 1))
+ elif self.recol_ident == 'imprimir':
+ self.tabla.insertar(LexToken('PRINT', None, None, 1))
+ elif self.recol_ident == 'leer':
+ self.tabla.insertar(LexToken('READ', None, None, 1))
+ elif self.recol_ident == 'retorna':
+ self.tabla.insertar(LexToken('RETURN', None, None, 1))
+ elif self.recol_ident == 'vacio':
+ self.tabla.insertar(LexToken('VOID', None, None, 1))
+ elif self.recol_ident == 'mientras':
+ self.tabla.insertar(LexToken('WHILE', None, None, 1))
+ elif self.recol_ident == 'verdadero':
+ self.tabla.insertar(LexToken('BOOLEAN_LIT', None, True, 1))
+ elif self.recol_ident == 'falso':
+ self.tabla.insertar(LexToken('BOOLEAN_LIT', None, False, 1))
+ else:
+ self.tabla.insertar(LexToken('IDENT', self.recol_ident, None, 1))
+ self.recol_ident = ''
+ self.selector = Selector.NINGUNO
+ return Control.REPETIR
+ return Control.SIGUIENTE