def tokenizar(self): """ Tokeniza o código da classe Lexer e returna uma fila de tokens. Essa fila é a implementada inter- namente na classe 'deque' do python, então em vez de um método 'dequeue()' temos um 'popleft()' de funcionalidade equivalente. """ tokens = [] while self.caracter_atual != None: if self.caracter_atual in ' \t\n\r\b\v\f': self.avancar() elif self.caracter_atual == '#': token = self.make_preprocessor() tokens.append(token) self.avancar() elif self.caracter_atual == '.': if self.lookahead() not in digitos: self.avancar() tokens.append(Token(TokenTipo.TOKEN_STRUCT_REF)) elif self.caracter_atual in digitos + '.': token = self.make_numbers() tokens.append(token) elif self.caracter_atual in list( operadores_unicos.keys()) + operadores_duplos: token = self.make_operador() if token != None: tokens.append(token) self.avancar() elif self.caracter_atual in alfabeto + '_': token = self.parse_word() tokens.append(token) elif self.caracter_atual == '"': self.avancar() token = self.parse_string() tokens.append(token) elif self.caracter_atual == "'": self.avancar() token = self.parse_char() tokens.append(token) elif self.caracter_atual in list(separadores.keys()): token = self.make_separador() tokens.append(token) self.avancar() elif self.caracter_atual not in alfabeto_completo: message = 'Caracter fora do alfabeto reconhecido ' + str( self.posicao) self.avancar() message += '\nlinha:\n\n' + self.contexto raise Exception(message) else: message = 'Erro durante analise léxica: "' + self.caracter_atual + '" Caracter não identificado.\n\nposição: ' + str( self.posicao) self.avancar() message += '\nlinha:\n\n' + self.contexto raise Exception(message) tokens.append(Token(TokenTipo.TOKEN_EOF)) return deque(tokens)
def parse_word(self): """ Captura uma palavra do tipo identificador ou keyword """ token_str = '' while self.caracter_atual != None and self.caracter_atual in alfanumu: token_str += self.caracter_atual self.avancar() if token_str in keywords: return Token(TokenTipo.TOKEN_KEYWORD, valor=token_str) else: return Token(TokenTipo.TOKEN_IDENT, valor=token_str)
def parse_char(self): """ Captura um token do tipo char """ token_str = '' while self.caracter_atual not in (None, "'"): token_str += self.caracter_atual self.avancar() if self.caracter_atual == "'": self.avancar() return Token(TokenTipo.TOKEN_CHAR, valor=token_str)
def parse_string(self): """ Captura um token do tipo string """ token_str = '' while self.caracter_atual not in (None, '"'): token_str += self.caracter_atual self.avancar() if self.caracter_atual == '"': self.avancar() return Token(TokenTipo.TOKEN_STR, valor=token_str)
def make_numbers(self): """ Captura um token do tipo número, seja ele inteiro ( decimal, binário, octal ou hexadecimal) ou real ( no- tação científica ou não). """ numero_final = '' while self.caracter_atual != None and self.caracter_atual not in separadores: numero_final += self.caracter_atual self.avancar() if numero_final.startswith('0b') or numero_final.startswith('0B'): return Token(TokenTipo.TOKEN_BIN, numero_final) if numero_final.startswith('0x') or numero_final.startswith('0X'): return Token(TokenTipo.TOKEN_HEXA, numero_final) if numero_final.startswith('0') and len(numero_final) > 1: return Token(TokenTipo.TOKEN_OCT, numero_final) if '.' in numero_final: return Token(TokenTipo.TOKEN_REAL, numero_final) return Token(TokenTipo.TOKEN_INT, numero_final)
def make_preprocessor(self): """ Captura um token do tipo preprocessador (define, include e pragma) """ token_str = '' token_tipo = None while self.caracter_atual not in (None, ' '): token_str += self.caracter_atual self.avancar() if token_str == '#define': token_tipo = TokenTipo.TOKEN_DEFINE elif token_str == '#include': token_tipo = TokenTipo.TOKEN_INCLUDE elif token_str == '#pragma': token_tipo = TokenTipo.TOKEN_PRAGMA token_data = '' while self.caracter_atual not in (None, '\n'): token_data += self.caracter_atual self.avancar() return Token(token_tipo, token_data)
def make_operador(self): """ Captura um token do tipo Operador, atentando para os operadores duplos (>>, <<, || etc.). """ if self.caracter_atual in list(operadores_unicos.keys()): return Token(operadores_unicos[self.caracter_atual]) if self.caracter_atual == '+': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_SOMA_IG) if self.lookahead() == '+': self.avancar() return Token(TokenTipo.TOKEN_SOMA_UM) return Token(TokenTipo.TOKEN_SOMA) if self.caracter_atual == '-': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_SUB_IG) if self.lookahead() == '-': self.avancar() return Token(TokenTipo.TOKEN_SUB_UM) if self.lookahead() == '>': self.avancar() return Token(TokenTipo.TOKEN_STRUCT_REF) return Token(TokenTipo.TOKEN_SUB) if self.caracter_atual == '>': if self.lookahead() == '>': self.avancar() if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_SHIFT_R_IG) return Token(TokenTipo.TOKEN_SHIFT_R) if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_MAIOR_IG) return Token(TokenTipo.TOKEN_MAIOR) if self.caracter_atual == '<': if self.lookahead() == '<': self.avancar() if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_SHIFT_L_IG) return Token(TokenTipo.TOKEN_SHIFT_L) if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_MENOR_IG) return Token(TokenTipo.TOKEN_MENOR) if self.caracter_atual == '|': if self.lookahead() == '|': self.avancar() return Token(TokenTipo.TOKEN_OR) if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_OR_IG) return Token(TokenTipo.TOKEN_ORB) if self.caracter_atual == '!': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_NOT_IG) return Token(TokenTipo.TOKEN_NOT) if self.caracter_atual == '&': if self.lookahead() == '&': self.avancar() return Token(TokenTipo.TOKEN_AND) if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_AND_IG) return Token(TokenTipo.TOKEN_AMPERSAND) if self.caracter_atual == '=': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_IGUAL) return Token(TokenTipo.TOKEN_ATRIB) if self.caracter_atual == '*': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_MULT_IG) return Token(TokenTipo.TOKEN_ASTERISCO) if self.caracter_atual == '%': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_MOD_IG) return Token(TokenTipo.TOKEN_MOD) if self.caracter_atual == '^': if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_XOR_IG) return Token(TokenTipo.TOKEN_XOR) if self.caracter_atual == '/': if self.lookahead() == '/': self.avancar_ate(chars=['\n', None]) if self.lookahead() == '=': self.avancar() return Token(TokenTipo.TOKEN_DIV_IG) if self.lookahead() == '*': self.avancar(2) while self.lookahead() not in ['/', None]: self.avancar_ate(chars=['*', None]) self.avancar() else: return Token(TokenTipo.TOKEN_DIV)
def make_separador(self): """ Captura um token do tipo Separador """ return Token(separadores[self.caracter_atual])