def siguiente_componente_lexico(self): """ Regresa el siguiente componente lexico (Simbolo) encontrado en el codigo fuente. """ caracter = None while True: if self.estado == 0: caracter = self.__siguiente_caracter() if caracter in (' ', '\t', '\n'): self.__avanza_inicio_lexema() if caracter == '\n': self.numero_de_linea += 1 elif caracter is None: return None elif caracter == '<': self.estado = 1 elif caracter == '=': self.estado = 5 elif caracter == '>': self.estado = 6 else: self.estado = self.__fallo() elif self.estado == 1: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 2 elif caracter == '>': self.estado = 3 else: self.estado = 4 elif self.estado == 2: return Simbolo(token=TOKENS['MEI'], lexema=self.__leer_lexema()) elif self.estado == 3: return Simbolo(token=TOKENS['DIF'], lexema=self.__leer_lexema()) elif self.estado == 4: self.__retrocede_indice() return Simbolo(token=TOKENS['MEN'], lexema=self.__leer_lexema()) elif self.estado == 5: return Simbolo(token=TOKENS['IGU'], lexema=self.__leer_lexema()) elif self.estado == 6: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 7 else: self.estado = 8 elif self.estado == 7: return Simbolo(token=TOKENS['MAI'], lexema=self.__leer_lexema()) elif self.estado == 8: self.__retrocede_indice() return Simbolo(token=TOKENS['MAY'], lexema=self.__leer_lexema()) elif self.estado == 9: if caracter.isalpha(): self.estado = 10 else: self.estado = self.__fallo() elif self.estado == 10: caracter = self.__siguiente_caracter() if not caracter.isalnum(): self.estado = 11 elif self.estado == 11: self.__retrocede_indice() lexema = self.__leer_lexema() simbolo = self.__buscar_simbolo(lexema=lexema) if self.zona_de_codigo in (Zonas.DEF_VARIABLES_GLOBALES, Zonas.DEF_VARIABLES_LOCALES,): if simbolo is None: simbolo = Simbolo(token=TOKENS['ID'], lexema=lexema) self.inserta_simbolo(simbolo=simbolo) elif simbolo.token == TOKENS['ID']: self.__errores.agregar( Error( tipo = 'SEMATICO', num_linea = self.num_linea, mensaje = f"La variable; '{lexema}' ya esta defendida en el ambito actual." ) ) else: if simbolo is None: self.__errores.agregar( Error( tipo='SEMETICO', num_linea = self.num_linea, mensaje = f"La variabl: '{lexema}' no esta definida," ) ) return simbolo elif self.estado == 12: if caracter.isdigit(): self.estado = 13 else: self.estado = self.__fallo() elif self.estado == 13: caracter = self.__siguiente_caracter() if caracter == '.': self.estado = 14 elif caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 20 elif self.estado == 14: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 15 else: self.estado = self.__fallo() elif self.estado == 15: caracter = self.__siguiente_caracter() if caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 21 elif self.estado == 16: caracter = self.__siguiente_caracter() if caracter in '+-': self.estado = 17 elif caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 17: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 18: caracter = self.__siguiente_caracter() if caracter.isdigit(): pass else: self.estado = 19 elif self.estado == 19 or self.estado == 21: self.__retrocede_indice() return Simbolo(token=TOKENS['NUMF'], lexema=self.__leer_lexema()) elif self.estado == 20: self.__retrocede_indice() return Simbolo(token=TOKENS['NUM'], lexema=self.__leer_lexema()) elif self.estado == 22: caracter = self.__sync_caracter() if caracter == '"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 23: caracter = self.__siguiente_caracter() if caracter == '\\': self.estado = 24 elif caracter == '"': self.estado = 25 elif caracter is not None: pass else: self.estado = self.__fallo() elif self.estado == 24: caracter = self.__siguiente_caracter() if caracter in r'atrn\"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 25: return Simbolo(token=TOKENS['CONST_STRING'], lexema=self.__leer_lexema()) elif self.estado == 26: caracter = self.__sync_caracter() if caracter == "'": self.estado = 27 else: self.estado = self.__fallo() elif self.estado == 27: caracter = self.__siguiente_caracter() if caracter == "\\": self.estado = 28 elif caracter is not None: self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 28: caracter = self.__siguiente_caracter() if caracter in r"atrn\'": self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 29: caracter = self.__siguiente_caracter() if caracter == "'": self.estado = 30 else: self.estado = self.__fallo() elif self.estado == 30: return Simbolo(token=TOKENS['CONST_CHAR'], lexema=self.__leer_lexema()) elif self.estado == 31: caracter = self.__sync_caracter() if caracter == '/': self.estado = 32 else: self.estado = self.__fallo() elif self.estado == 32: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 33 else: self.estado = self.__fallo() elif self.estado == 33: caracter = self.__siguiente_caracter() if caracter == '\n' or caracter is None: if caracter == '\n': self.numero_de_linea += 1 self.estado = 34 else: pass elif self.estado == 34: self.__retrocede_indice() self.__leer_lexema() elif self.estado == 35: caracter = self.__sync_caracter() if caracter == '/': self.estado = 36 else: self.estado = self.__fallo() elif self.estado == 36: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 37 else: self.estado = self.__fallo() elif self.estado == 37: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 38 elif caracter == '\n': self.numero_de_linea += 1 else: pass elif self.estado == 38: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 39 else: self.estado = 37 elif self.estado == 39: self.__leer_lexema() else: caracter = self.__sync_caracter() if caracter in SIMBOLOS_PERMITIDOS: return Simbolo(token=ord(caracter), lexema=self.__leer_lexema()) else: self.estado = 0 self.__errores.agregar( Error( tipo='LEXICO', num_linea=self.numero_de_linea, mensaje=f"Simbolo no permitido: '{self.__leer_lexema()}'" ) ) def __leer_lexema(self): """ Regresa la secuencia de caracteres entre el inicio_lexema y el indice, despues mueve el inicio_lexema a la siguiente posicion. """ self.lexema = self.codigo[self.inicio_lexema: self.indice + 1] self.__avanza_inicio_lexema() self.inicio = 0 self.estado = 0 return self.lexema def __retrocede_indice(self): """ Retrocede el indice una posicion hacia atras. Equivale al asterisco en los estados de aceptacion. """ self.indice -= 1 def __sync_caracter(self): """ Si un automata falla en un estado intermedio, establece el indice en la posicion de inicio_lexema y regresa el caracter en esa posicion. """ self.indice = self.inicio_lexema return self.codigo[self.indice] def __fallo(self): """ Regresa el valor del estado inicial del siguiente automata a probar cuando el automata anterior fallo. """ if self.inicio == 0: self.inicio = 9 elif self.inicio == 9: self.inicio = 12 elif self.inicio == 12: self.inicio = 22 elif self.inicio == 22: self.inicio = 26 elif self.inicio == 26: self.inicio = 31 elif self.inicio == 31: self.inicio = 35 elif self.inicio == 35: self.inicio = 40 return self.inicio def marca_posicion(self, posicion = None): if hasattr (self, posicion): setattr(self, posicion, len(self.tabla_de_simbolos))
def siguiente_componente_lexico(self): """ Regresa el siguiente componente lexico (Simbolo) encontrado en el codigo fuente. """ caracter = None while True: if self.estado == 0: caracter = self.__siguiente_caracter() if caracter in (' ', '\t', '\n'): self.__avanza_inicio_lexema() if caracter == '\n': self.numero_de_linea += 1 elif caracter is None: return None elif caracter == '<': self.estado = 1 elif caracter == '=': self.estado = 5 elif caracter == '>': self.estado = 6 else: self.estado = self.__fallo() elif self.estado == 1: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 2 elif caracter == '>': self.estado = 3 else: self.estado = 4 elif self.estado == 2: return Simbolo(token=TOKENS['MEI'], lexema=self.__leer_lexema()) elif self.estado == 3: return Simbolo(token=TOKENS['DIF'], lexema=self.__leer_lexema()) elif self.estado == 4: self.__retrocede_indice() return Simbolo(token=TOKENS['MEN'], lexema=self.__leer_lexema()) elif self.estado == 5: return Simbolo(token=TOKENS['IGU'], lexema=self.__leer_lexema()) elif self.estado == 6: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 7 else: self.estado = 8 elif self.estado == 7: return Simbolo(token=TOKENS['MAI'], lexema=self.__leer_lexema()) elif self.estado == 8: self.__retrocede_indice() return Simbolo(token=TOKENS['MAY'], lexema=self.__leer_lexema()) elif self.estado == 9: if caracter.isalpha(): self.estado = 10 else: self.estado = self.__fallo() elif self.estado == 10: caracter = self.__siguiente_caracter() if not caracter.isalnum(): self.estado = 11 elif self.estado == 11: self.__retrocede_indice() lexema = self.__leer_lexema() simbolo = self.__buscar_simbolo(lexema=lexema) if self.zona_de_codigo in ( Zonas.DEF_VARIABLES_GLOBALES, Zonas.DEF_VARIABLES_LOCALES, ): if simbolo is None: simbolo = Simbolo(token=TOKENS['ID'], lexema=lexema, tipo=self.tipo_de_dato_actual) if simbolo.tipo == TIPOS['void']: self.__errores.agregar( Error( tipo='SEMANTICO', num_linea=self.numero_de_linea, mensaje= f"No es posible definir una variable de tipo 'void'." )) self.inserta_simbolo(simbolo=simbolo) elif simbolo.token == TOKENS['ID']: self.__errores.agregar( Error( tipo='SEMANTICO', num_linea=self.numero_de_linea, mensaje= f"La variable: '{lexema}' ya esta definida en el ambito actual." )) elif self.zona_de_codigo == Zonas.DEF_FUNCION: if simbolo is None: simbolo = Simbolo(token=TOKENS['ID'], lexema=lexema, tipo=self.tipo_de_dato_actual) self.inserta_funcion(simbolo=simbolo) else: self.__errores.agregar( Error( tipo='SEMANTICO', num_linea=self.numero_de_linea, mensaje= f"Ya existe una variable o funcion llamada: '{lexema}'." )) else: if simbolo is None: self.__errores.agregar( Error( tipo='SEMANTICO', num_linea=self.numero_de_linea, mensaje= f"La variable: '{lexema}' no esta definida.")) return simbolo elif self.estado == 12: if caracter.isdigit(): self.estado = 13 else: self.estado = self.__fallo() elif self.estado == 13: caracter = self.__siguiente_caracter() if caracter == '.': self.estado = 14 elif caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 20 elif self.estado == 14: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 15 else: self.estado = self.__fallo() elif self.estado == 15: caracter = self.__siguiente_caracter() if caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 21 elif self.estado == 16: caracter = self.__siguiente_caracter() if caracter in '+-': self.estado = 17 elif caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 17: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 18: caracter = self.__siguiente_caracter() if caracter.isdigit(): pass else: self.estado = 19 elif self.estado == 19 or self.estado == 21: self.__retrocede_indice() return Simbolo(token=TOKENS['NUMF'], lexema=self.__leer_lexema()) elif self.estado == 20: self.__retrocede_indice() return Simbolo(token=TOKENS['NUM'], lexema=self.__leer_lexema()) elif self.estado == 22: caracter = self.__sync_caracter() if caracter == '"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 23: caracter = self.__siguiente_caracter() if caracter == '\\': self.estado = 24 elif caracter == '"': self.estado = 25 elif caracter is not None: pass else: self.estado = self.__fallo() elif self.estado == 24: caracter = self.__siguiente_caracter() if caracter in r'atrn\"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 25: return Simbolo(token=TOKENS['CONST_STRING'], lexema=self.__leer_lexema()) elif self.estado == 26: caracter = self.__sync_caracter() if caracter == "'": self.estado = 27 else: self.estado = self.__fallo() elif self.estado == 27: caracter = self.__siguiente_caracter() if caracter == "\\": self.estado = 28 elif caracter is not None: self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 28: caracter = self.__siguiente_caracter() if caracter in r"atrn\'": self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 29: caracter = self.__siguiente_caracter() if caracter == "'": self.estado = 30 else: self.estado = self.__fallo() elif self.estado == 30: return Simbolo(token=TOKENS['CONST_CHAR'], lexema=self.__leer_lexema()) elif self.estado == 31: caracter = self.__sync_caracter() if caracter == '/': self.estado = 32 else: self.estado = self.__fallo() elif self.estado == 32: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 33 else: self.estado = self.__fallo() elif self.estado == 33: caracter = self.__siguiente_caracter() if caracter == '\n' or caracter is None: if caracter == '\n': self.numero_de_linea += 1 self.estado = 34 else: pass elif self.estado == 34: self.__retrocede_indice() self.__leer_lexema() elif self.estado == 35: caracter = self.__sync_caracter() if caracter == '/': self.estado = 36 else: self.estado = self.__fallo() elif self.estado == 36: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 37 else: self.estado = self.__fallo() elif self.estado == 37: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 38 elif caracter == '\n': self.numero_de_linea += 1 else: pass elif self.estado == 38: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 39 else: self.estado = 37 elif self.estado == 39: self.__leer_lexema() else: caracter = self.__sync_caracter() if caracter in SIMBOLOS_PERMITIDOS: return Simbolo(token=ord(caracter), lexema=self.__leer_lexema()) else: self.estado = 0 self.__errores.agregar( Error( tipo='LEXICO', num_linea=self.numero_de_linea, mensaje= f"Simbolo no permitido: '{self.__leer_lexema()}'"))
def __agregar_error(self, tipo='SINTACTICO', mensaje=None): self.errores.agregar( Error(tipo=tipo, num_linea=self.numero_de_linea, mensaje=mensaje))
def siguiente_componente_lexico(self): """ Regresa el siguiente componente lexico (Simbolo) encontrado en el codigo fuente. """ caracter = None while True: if self.estado == 0: caracter = self.__siguiente_caracter() if caracter in (' ', '\t', '\n'): self.__avanza_inicio_lexema() if caracter == '\n': self.numero_de_linea += 1 elif caracter is None: return None elif caracter == '<': self.estado = 1 elif caracter == '=': self.estado = 5 elif caracter == '>': self.estado = 6 else: self.estado = self.__fallo() elif self.estado == 1: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 2 elif caracter == '>': self.estado = 3 else: self.estado = 4 elif self.estado == 2: return Simbolo(token=TOKENS['MEI'], lexema=self.__leer_lexema()) elif self.estado == 3: return Simbolo(token=TOKENS['DIF'], lexema=self.__leer_lexema()) elif self.estado == 4: self.__retrocede_indice() return Simbolo(token=TOKENS['MEN'], lexema=self.__leer_lexema()) elif self.estado == 5: return Simbolo(token=TOKENS['IGU'], lexema=self.__leer_lexema()) elif self.estado == 6: caracter = self.__siguiente_caracter() if caracter == '=': self.estado = 7 else: self.estado = 8 elif self.estado == 7: return Simbolo(token=TOKENS['MAI'], lexema=self.__leer_lexema()) elif self.estado == 8: self.__retrocede_indice() return Simbolo(token=TOKENS['MAY'], lexema=self.__leer_lexema()) elif self.estado == 9: if caracter.isalpha(): self.estado = 10 else: self.estado = self.__fallo() elif self.estado == 10: caracter = self.__siguiente_caracter() if not caracter.isalnum(): self.estado = 11 elif self.estado == 11: self.__retrocede_indice() lexema = self.__leer_lexema() simbolo = self.__buscar_simbolo(lexema=lexema) if simbolo is None: simbolo = Simbolo(token=TOKENS['ID'], lexema=lexema) self.inserta_simbolo(simbolo=simbolo) return simbolo elif self.estado == 12: if caracter.isdigit(): self.estado = 13 else: self.estado = self.__fallo() elif self.estado == 13: caracter = self.__siguiente_caracter() if caracter == '.': self.estado = 14 elif caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 20 elif self.estado == 14: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 15 else: self.estado = self.__fallo() elif self.estado == 15: caracter = self.__siguiente_caracter() if caracter in 'Ee': self.estado = 16 elif caracter.isdigit(): pass else: self.estado = 21 elif self.estado == 16: caracter = self.__siguiente_caracter() if caracter in '+-': self.estado = 17 elif caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 17: caracter = self.__siguiente_caracter() if caracter.isdigit(): self.estado = 18 else: self.estado = self.__fallo() elif self.estado == 18: caracter = self.__siguiente_caracter() if caracter.isdigit(): pass else: self.estado = 19 elif self.estado == 19 or self.estado == 21: self.__retrocede_indice() return Simbolo(token=TOKENS['NUMF'], lexema=self.__leer_lexema()) elif self.estado == 20: self.__retrocede_indice() return Simbolo(token=TOKENS['NUM'], lexema=self.__leer_lexema()) elif self.estado == 22: caracter = self.__sync_caracter() if caracter == '"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 23: caracter = self.__siguiente_caracter() if caracter == '\\': self.estado = 24 elif caracter == '"': self.estado = 25 elif caracter is not None: pass else: self.estado = self.__fallo() elif self.estado == 24: caracter = self.__siguiente_caracter() if caracter in r'atrn\"': self.estado = 23 else: self.estado = self.__fallo() elif self.estado == 25: return Simbolo(token=TOKENS['CONST_STRING'], lexema=self.__leer_lexema()) elif self.estado == 26: caracter = self.__sync_caracter() if caracter == "'": self.estado = 27 else: self.estado = self.__fallo() elif self.estado == 27: caracter = self.__siguiente_caracter() if caracter == "\\": self.estado = 28 elif caracter is not None: self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 28: caracter = self.__siguiente_caracter() if caracter in r"atrn\'": self.estado = 29 else: self.estado = self.__fallo() elif self.estado == 29: caracter = self.__siguiente_caracter() if caracter == "'": self.estado = 30 else: self.estado = self.__fallo() elif self.estado == 30: return Simbolo(token=TOKENS['CONST_CHAR'], lexema=self.__leer_lexema()) elif self.estado == 31: caracter = self.__sync_caracter() if caracter == '/': self.estado = 32 else: self.estado = self.__fallo() elif self.estado == 32: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 33 else: self.estado = self.__fallo() elif self.estado == 33: caracter = self.__siguiente_caracter() if caracter == '\n' or caracter is None: if caracter == '\n': self.numero_de_linea += 1 self.estado = 34 else: pass elif self.estado == 34: self.__retrocede_indice() self.__leer_lexema() elif self.estado == 35: caracter = self.__sync_caracter() if caracter == '/': self.estado = 36 else: self.estado = self.__fallo() elif self.estado == 36: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 37 else: self.estado = self.__fallo() elif self.estado == 37: caracter = self.__siguiente_caracter() if caracter == '*': self.estado = 38 elif caracter == '\n': self.numero_de_linea += 1 else: pass elif self.estado == 38: caracter = self.__siguiente_caracter() if caracter == '/': self.estado = 39 else: self.estado = 37 elif self.estado == 39: self.__leer_lexema() else: caracter = self.__sync_caracter() if caracter in SIMBOLOS_PERMITIDOS: return Simbolo(token=ord(caracter), lexema=self.__leer_lexema()) else: self.estado = 0 self.__errores.agregar( Error( tipo='LEXICO', num_linea=self.numero_de_linea, mensaje= f"Simbolo no permitido: '{self.__leer_lexema()}'"))