예제 #1
0
class Lexer():

    #Classe que representa o Lexer:

    #[1] Voce devera se preocupar quando incremetar as linhas e colunas,
    #assim como quando decrementar ou reinicia-las. Lembre-se, ambas
    #comecam em 1.
    #[2] Toda vez que voce encontrar um lexema completo, voce deve retornar
    #um objeto Token(Tag, "lexema", linha, coluna). Cuidado com as
    #palavras reservadas, que ja sao cadastradas na TS. Essa consulta
    #voce devera fazer somente quando encontrar um Identificador.
    #[3] Se o caractere lido nao casar com nenhum caractere esperado,
    #vapresentar a mensagem de erro na linha e coluna correspondente.
    #Obs.: lembre-se de usar o metodo retornaPonteiro() quando necessario.
    #      lembre-se de usar o metodo sinalizaErroLexico() para mostrar
    #      a ocorrencia de um erro lexico.

    def __init__(self, input_file):
        try:
            self.input_file = open(input_file, 'rb')
            self.lookahead = 0
            self.n_line = 1
            self.n_column = 1
            self.ts = TS()
        except IOError:
            print('Erro de abertura do arquivo. Encerrando.')
            sys.exit(0)

    def closeFile(self):
        try:
            self.input_file.close()
        except IOError:
            print('Erro ao fechar arquivo. Encerrando.')
            sys.exit(0)

    def sinalizaErroLexico(self, message):
        print("[Erro Lexico]: ", message, "\n")

    def retornaPonteiro(self):
        if (self.lookahead.decode('ascii') != ''):
            self.input_file.seek(self.input_file.tell() - 1)
            self.n_column -= 1

    def printTS(self):
        self.ts.printTS()

    def proxToken(self):
        estado = 1
        lexema = ""
        c = '\u0000'

        while (True):
            self.lookahead = self.input_file.read(1)
            c = self.lookahead.decode('ascii')

            if (estado == 1):  #--------------Q0
                if (c == ''):
                    return Token(Tag.EOF, "EOF", self.n_line, self.n_column)
                elif (c == ' ' or c == '\t' or c == '\n' or c == '\r'):
                    estado = 1
                    if (c == '\n'):
                        self.n_line += 1
                        self.n_column = 1
                    elif (c == ' ' or '\r'):
                        self.n_column += 1
                    elif (c == '\t'):
                        self.n_column += 3
                elif (c == '#'):  #--------------Q24
                    estado = 24
                    self.n_column += 1
                elif (c == '"'):  #--------------Q21
                    estado = 21
                    self.n_column += 1
                elif (c == '='):  #--------------Q1
                    estado = 2
                    self.n_column += 1
                elif (c == '!'):  #--------------Q3
                    estado = 4
                    self.n_column += 1
                elif (c == '<'):  #--------------Q6
                    estado = 6
                    self.n_column += 1
                elif (c == '>'):  #--------------Q9
                    estado = 9
                    self.n_column += 1
                elif (c.isdigit()):  #--------------Q16
                    lexema += c
                    estado = 16
                    self.n_column += 1
                elif (c.isalpha()):  #--------------Q26
                    lexema += c
                    estado = 26
                    self.n_column += 1
                elif (c == '/'):  #--------------Q15
                    self.n_column += 1
                    token = Token(Tag.OP_DIV, "/", self.n_line, self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '.'):  #--------------Q30
                    self.n_column += 1
                    token = Token(Tag.SIMB_PONTO, ".", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == ']'):  #--------------Q36
                    self.n_column += 1
                    token = Token(Tag.SIMB_FECHA_COLCHETES, "]", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '['):  #--------------Q35
                    self.n_column += 1
                    token = Token(Tag.SIMB_ABRE_COLCHETES, "[", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == ','):  #--------------Q33
                    self.n_column += 1
                    token = Token(Tag.SIMB_VIRGULA, ",", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == ')'):  #--------------Q34
                    self.n_column += 1
                    token = Token(Tag.SIMB_FECHA_PARENTESES, ")", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '('):  #--------------Q32
                    self.n_column += 1
                    token = Token(Tag.SIMB_ABRE_PARENTESES, "(", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == ';'):  #--------------Q31
                    self.n_column += 1
                    token = Token(Tag.SIMB_PONTO_VIRGULA, ";", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == ':'):  #--------------Q29
                    self.n_column += 1
                    token = Token(Tag.SIMB_DOIS_PONTOS, ":", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '*'):  #--------------Q14
                    self.n_column += 1
                    token = Token(Tag.OP_MULT, "*", self.n_line, self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '+'):  #--------------Q13
                    self.n_column += 1
                    token = Token(Tag.OP_SOMA, "+", self.n_line, self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                elif (c == '-'):  #--------------Q12
                    self.n_column += 1
                    token = Token(Tag.OP_UNARIO, "-", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

                else:
                    self.sinalizaErroLexico("Caractere invalido [" + c +
                                            "] na linha " + str(self.n_line) +
                                            " e coluna " + str(self.n_column))
                    return None
            elif (estado == 2):
                if (c == '='):  #--------------Q2
                    self.n_column += 1
                    token = Token(Tag.OP_IGUAL, "==", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                else:  #--------------Q28
                    self.retornaPonteiro()
                    token = Token(Tag.OP_ATRIBUI, "=", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

            elif (estado == 4):
                if (c == '='):  #--------------Q5
                    self.n_column += 1
                    token = Token(Tag.OP_DIFERENTE, "!=", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                else:  #--------------Q4
                    self.retornaPonteiro()
                    token = Token(Tag.OP_UNARIO, "!", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)

                    return token
            elif (estado == 6):
                if (c == '='):  #--------------Q7
                    self.n_column += 1
                    token = Token(Tag.OP_MENOR_IGUAL, "<=", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                else:  #--------------Q8
                    self.retornaPonteiro()
                    token = Token(Tag.OP_MENOR, "<", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)

                    return token
            elif (estado == 9):
                if (c == '='):  #--------------Q10
                    self.n_column += 1
                    token = Token(Tag.OP_MAIOR_IGUAL, ">=", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                else:  #--------------Q11
                    self.retornaPonteiro()
                    token = Token(Tag.OP_MAIOR, ">", self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)

                    return token
            elif (estado == 16):
                if (c.isdigit()):  #--------------Q16
                    lexema += c
                    self.n_column += 1
                elif (c == '.'):  #--------------Q18
                    lexema += c
                    estado = 18
                    self.n_column += 1
                elif (c == '-'):
                    #RECONHECER INT
                    self.n_column += 1
                    token = Token(Tag.CONST_INT, lexema, self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                    #RECONHECER OPERADOR MENOS
                # token = Token(Tag.OP_SUBTRAI, lexema, self.n_line, self.n_column)
                #self.ts.addToken(lexema, token)
                #return token
                else:  #--------------Q17
                    self.retornaPonteiro()
                    token = Token(Tag.CONST_INT, lexema, self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
            elif (estado == 18):  #---RECONHECER DOUBLE
                if (c.isdigit()):  #--------------Q19
                    lexema += c
                    self.n_column += 1
                elif (c == '-'):
                    #RECONHECER DOUBLE
                    token = Token(Tag.CONST_DOUBLE, lexema, self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token
                    #RECONHECER OPERADOR MENOS
                    #token = Token(Tag.OP_SUBTRAI, lexema, self.n_line, self.n_column)
                    #self.ts.addToken(lexema, token)
                    #return token

                else:  #--------------Q20
                    self.retornaPonteiro()
                    token = Token(Tag.CONST_DOUBLE, lexema, self.n_line,
                                  self.n_column)
                    self.ts.addToken(lexema, token)
                    return token

            elif (estado == 21):
                if (c == '"'):  #--------------Q23
                    self.n_column += 1
                    return Token(Tag.CONST_STRING, lexema, self.n_line,
                                 self.n_column)

                elif (c == '\n'):
                    self.sinalizaErroLexico(
                        "Só é permitido String de uma Linha! Erro na linha " +
                        str(self.n_line) + " e coluna " + str(self.n_column))
                    self.n_column = 1
                    self.n_line += 1
                else:  #--------------Q22
                    lexema += c
                    self.n_column += 1
            elif (estado == 24):
                if (c == '\n'):  #--------------Q0
                    self.n_line = self.n_line + 1
                    self.n_column = 1
                else:  #--------------Q25
                    estado = 24
            elif (estado == 26):
                if (c.isalnum()):  #--------------Q26
                    lexema += c
                    self.n_column += 1
                else:  #--------------Q27
                    self.retornaPonteiro()
                    token = self.ts.getToken(lexema)
                    if (token is None):  #--------------VERIFICA TABELA
                        token = Token(Tag.ID, lexema, self.n_line,
                                      self.n_column)
                        self.ts.addToken(lexema, token)
                    else:
                        token.setLinha(self.n_line)
                        token.setColuna(self.n_column)
                    return token
예제 #2
0
class Lexer():
    '''
   Classe que representa o Lexer (AFD):
   
   [1] Voce devera se preocupar quando incremetar as linhas e colunas,
   assim como, quando decrementar ou reinicia-las. Lembre-se, ambas 
   comecam em 1.
   [2] Toda vez que voce encontrar um lexema completo, voce deve retornar
   um objeto Token(Tag, "lexema", linha, coluna). Cuidado com as
   palavras reservadas, que ja sao cadastradas na TS. Essa consulta
   voce devera fazer somente quando encontrar um Identificador.
   [3] Se o caractere lido nao casar com nenhum caractere esperado,
   apresentar a mensagem de erro na linha e coluna correspondente.
   Obs.: lembre-se de usar o metodo retornaPonteiro() quando necessario. 
         lembre-se de usar o metodo sinalizaErroLexico() para mostrar
         a ocorrencia de um erro lexico.
   '''
    def __init__(self, input_file):
        try:
            self._input_file: TextIO = open(input_file, 'rb')
            self._leitor: Generator = self._le_arquivo()
            self._lexema: str = ''
            self._simbolo: str = ''
            self._sep: tuple = (' ', '\t', '\n', '\r')
            self._estado: int = 1
            self._qtd_erros: int = 0
            self.list_tokens: list = []
            self._line_atual = 1
            self._column_atual = 1
            self._line_lexer = 1
            self._column_lexer = 1
            self.ts = TS()
        except IOError:
            print('Erro de abertura do arquivo. Encerrando.')
            sys.exit(0)

    def _closeFile(self):
        try:
            self._input_file.close()
        except IOError:
            print('Erro ao fechar arquivo. Encerrando.')
            sys.exit(0)

    def _checa_modo_panico(self):
        self._qtd_erros += 1

        if self._qtd_erros > 2:
            logging.critical(
                'Limite máximo de erros lexicos suportados foi atingido.')
            raise SyntaxError

    def sinalizaErroLexico(self, message: str = 'Caractere invalido') -> str:
        self._simbolo = self._simbolo if self._simbolo else 'EOF'
        self.list_tokens.append(
            f"""[Erro Lexico]: {message} [ { repr(self._simbolo )} ] na linha { str(self._line_atual)} e coluna {str(self._column_atual)}"""
        )
        self._checa_modo_panico()

    def retornaPonteiro(self):
        self._input_file.seek(self._input_file.tell() - 1)

    def printTS(self):
        self.ts.printTS()

    def printTokens(self):
        for token in self.list_tokens:
            try:
                print(token.toString())
            except:
                print('[Erro Lexico]:', token)

    def _limpa_lexema(self):
        self._lexema = ''
        self._estado = 1

    def _atualiza_linha_lexer(self):
        self._line_lexer = self._line_atual
        self._column_lexer = self._column_atual

    def _le_arquivo(self) -> Generator:
        while True:
            try:
                self._simbolo: str = self._input_file.read(1).decode('ascii')

                # Sinaliza coluna e linha
                self._column_atual += 1
                if self._simbolo == '\n':
                    self._line_atual += 1
                    self._column_atual = 0

                yield self._simbolo.lower()

            except UnicodeDecodeError:
                self.list_tokens.append(
                    f'[Decode Error] Não foi possivel ler o caractere na posição linha {self._line_atual}, coluna {self._column_atual}'
                )
                self._checa_modo_panico()

    def analisa(self):

        while True:
            try:
                self._simbolo: str = next(self._leitor)

                if self._estado == 1:
                    self._atualiza_linha_lexer()

                    list_simbolos: list = [
                        smb.value for smb in self.ts.get_SMB()
                    ]
                    list_operadores: list = [
                        smb.value for smb in self.ts.get_OP()
                    ]
                    list_tokens: list = list_operadores + list_simbolos

                    if self._simbolo in list_tokens and self._simbolo not in (
                            '/', '<'):
                        self.list_tokens.append(
                            Token(Tag(self._simbolo),
                                  Tag(self._simbolo).value, self._line_atual,
                                  self._column_atual))
                        continue

                    if self._simbolo in self._sep:
                        self._estado = 1
                        continue

                    if self._simbolo == '=':
                        self._estado = 2
                        continue

                    if self._simbolo == '!':
                        self._estado = 4
                        continue

                    if self._simbolo == '<':
                        self._estado = 6
                        continue

                    if self._simbolo == '>':
                        self._estado = 9
                        continue

                    if self._simbolo.isdigit():
                        self._lexema += self._simbolo
                        self._estado = 12
                        continue

                    if self._simbolo.isalpha():
                        self._lexema += self._simbolo
                        self._estado = 14
                        continue

                    if self._simbolo == ':':
                        self._estado = 16
                        continue

                    if self._simbolo == '"':
                        self._estado = 17
                        continue

                    if self._simbolo == '/':
                        self._lexema += self._simbolo
                        self._estado = 18
                        continue

                    #EOF
                    if self._simbolo == '':
                        self.list_tokens.append(
                            Token(Tag.EOF, Tag.EOF.value, self._line_atual,
                                  self._column_atual))
                        self._closeFile()
                        break

                    self.sinalizaErroLexico()
                    self._limpa_lexema()
                    continue

                if self._estado == 2:
                    self._limpa_lexema()
                    if self._simbolo == '=':
                        self.list_tokens.append(
                            Token(Tag.OP_EQ, Tag.OP_EQ.value, self._line_lexer,
                                  self._column_lexer))
                        continue

                    self.sinalizaErroLexico()
                    continue

                if self._estado == 4:
                    self._limpa_lexema()
                    if self._simbolo == '=':
                        self.list_tokens.append(
                            Token(Tag.OP_NE, Tag.OP_NE.value, self._line_lexer,
                                  self._column_lexer))
                        continue

                    self.sinalizaErroLexico()
                    continue

                if self._estado == 16:
                    self._limpa_lexema()
                    if self._simbolo == '=':
                        self.list_tokens.append(
                            Token(Tag.OP_ATRIB, Tag.OP_ATRIB.value,
                                  self._line_lexer, self._column_lexer))
                        continue

                    self.sinalizaErroLexico()
                    continue

                if self._estado == 17:
                    if self._simbolo == '"':
                        if not self._lexema:
                            self.sinalizaErroLexico(
                                "Strings vazias não são validas")
                            continue

                        self.list_tokens.append(
                            Token(Tag.KW_CHAR, self._lexema, self._line_lexer,
                                  self._column_lexer))
                        self._limpa_lexema()
                        continue

                    self._lexema += self._simbolo

                    if self._simbolo == '\n':
                        self.sinalizaErroLexico("Era esperado uma aspas dupla")
                    continue

                if self._estado == 18:
                    if self._simbolo not in ['/', '*']:
                        self.list_tokens.append(
                            Token(Tag.OP_DIV, self._lexema, self._line_lexer,
                                  self._column_lexer))
                        self._limpa_lexema()
                        continue

                    self._lexema += self._simbolo
                    if self._lexema == '//':
                        continue

                    if self._lexema == '/*':
                        self._estado = 19
                        continue

                    if self._simbolo == '\n':
                        self._limpa_lexema()
                        continue

                    if not self._lexema.startswith('//'):
                        self.sinalizaErroLexico()
                        continue

                if self._estado == 19:
                    self._lexema += self._simbolo
                    if self._lexema.endswith('*/'):
                        self._limpa_lexema()
                        continue

                    if self._simbolo == '':
                        self.sinalizaErroLexico('Esperado "*/"')

                if self._estado == 6:
                    self._limpa_lexema()
                    if self._simbolo == '=':
                        self.list_tokens.append(
                            Token(Tag.OP_LE, Tag.OP_LE.value, self._line_lexer,
                                  self._column_lexer))
                        continue

                    self.retornaPonteiro()
                    self.list_tokens.append(
                        Token(Tag.OP_LT, Tag.OP_LT.value, self._line_lexer,
                              self._column_lexer))
                    continue

                if self._estado == 9:
                    self._limpa_lexema()
                    if self._simbolo == '=':
                        self.list_tokens.append(
                            Token(Tag.OP_GE, Tag.OP_GE.value, self._line_lexer,
                                  self._column_lexer))
                        continue

                    self.retornaPonteiro()
                    self.list_tokens.append(
                        Token(Tag.OP_GT, Tag.OP_GT.value, self._line_lexer,
                              self._column_lexer))
                    continue

                if self._estado == 12:
                    if self._simbolo.isdigit():
                        self._lexema += self._simbolo
                        continue

                    self.retornaPonteiro()
                    self.list_tokens.append(
                        Token(Tag.NUM, self._lexema, self._line_lexer,
                              self._column_lexer))
                    self._limpa_lexema()

                if self._estado == 14:
                    if self._simbolo.isalnum():
                        self._lexema += self._simbolo
                        continue

                    token = self.ts.getToken(self._lexema)

                    if token:
                        token = Token(token.nome, token.lexema,
                                      self._line_lexer, self._column_lexer)
                    else:
                        token = Token(Tag.ID, self._lexema, self._line_lexer,
                                      self._column_lexer)

                    self.list_tokens.append(token)
                    self.ts.addToken(self._lexema, token)

                    self._limpa_lexema()
                    self.retornaPonteiro()

            except SyntaxError:
                break
예제 #3
0
class Lexer:
    def __init__(self, file):
        try:
            self.file = open(file, 'rb')
            self.lookahead = 0
            self.n_line = 1
            self.n_column = 1
            self.n_columnInicial = 1
            self.n_lineInicial = 1
            self.ts = TS()
            self.c = '\u0000'
        except IOError:
            print('Erro de abertura do arquivo. Encerrando.')
            sys.exit(0)

    def closeFile(self):
        try:
            self.file.close()
        except IOError:
            print('Erro ao fechar arquivo. Encerrando.')
            sys.exit(0)

    def sinalizaErroLexico(self, message):
        print("[Erro Lexico]: ", message, "\n")

    def retornaPonteiro(self):
        if self.lookahead.decode('ascii') != '':
            self.file.seek(self.file.tell() - 1)

    def printTS(self):
        self.ts.printTS()

    def proxToken(self):
        estado = 1
        lexema = ""
        self.c = '\u0000'

        while True:
            self.lookahead = self.file.read(1)
            try:
                self.c = self.lookahead.decode('ascii')
            except:
                self.sinalizaErroLexico("Caractere nao ASCII na linha " +
                                        str(self.n_line) + " e coluna " +
                                        str(self.n_column))
                return None

            if estado == 1:
                self.n_lineInicial = self.n_line
                self.n_columnInicial = self.n_column
                if self.c == '':
                    return Token(Tag.EOF, "EOF", self.n_lineInicial,
                                 self.n_columnInicial)
                elif self.c == ' ' or self.c == '\n' or self.c == '\t' or self.c == '\r':
                    estado = 1
                elif self.c == '+':
                    estado = 2
                elif self.c == '-':
                    estado = 3
                elif self.c == '{':
                    estado = 4
                elif self.c == '}':
                    estado = 5
                elif self.c == '(':
                    estado = 6
                elif self.c == ')':
                    estado = 7
                elif self.c == ',':
                    estado = 8
                elif self.c == ';':
                    estado = 9
                elif self.c == '/':
                    estado = 10
                elif self.c == '*':
                    estado = 13
                elif self.c == '=':
                    estado = 16
                elif self.c == '!':
                    estado = 19
                elif self.c == '>':
                    estado = 21
                elif self.c == '<':
                    estado = 24
                elif self.c == '"':
                    estado = 29
                elif self.c.isalpha():
                    lexema += self.c
                    estado = 26
                elif self.c.isdigit():
                    lexema += self.c
                    estado = 31
                else:
                    self.retornaPonteiro()
                    self.sinalizaErroLexico("Caractere invalido [" + self.c +
                                            "] na linha " +
                                            str(self.n_lineInicial) +
                                            " e coluna " +
                                            str(self.n_columnInicial))
                    return None

            elif estado == 2:
                self.retornaPonteiro()
                return Token(Tag.OP_AD, "+", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 3:
                self.retornaPonteiro()
                return Token(Tag.OP_MIN, "-", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 4:
                self.retornaPonteiro()
                return Token(Tag.SMB_OBC, "{", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 5:
                self.retornaPonteiro()
                return Token(Tag.SMB_CBC, "}", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 6:
                self.retornaPonteiro()
                return Token(Tag.SMB_OPA, "(", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 7:
                self.retornaPonteiro()
                return Token(Tag.SMB_CPA, ")", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 8:
                self.retornaPonteiro()
                return Token(Tag.SMB_COM, ",", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 9:
                self.retornaPonteiro()
                return Token(Tag.SMB_SEM, ";", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 10:
                if self.c == '/':
                    estado = 12
                elif self.c == '*':
                    estado = 35
                else:
                    self.retornaPonteiro()
                    return Token(Tag.OP_DIV, "/", self.n_lineInicial,
                                 self.n_columnInicial)
            elif estado == 12:
                if self.c == '\n' or self.c == "":
                    estado = 1
            elif estado == 13:
                self.retornaPonteiro()
                return Token(Tag.OP_MUL, "*", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 16:
                if self.c == '=':
                    return Token(Tag.OP_EQ, "==", self.n_lineInicial,
                                 self.n_columnInicial)

                self.retornaPonteiro()
                return Token(Tag.OP_ATRIB, "=", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 19:
                if (self.c == '='):
                    return Token(Tag.OP_NE, "!=", self.n_lineInicial,
                                 self.n_columnInicial)

                self.sinalizaErroLexico("Caractere invalido [" + self.c +
                                        "] na linha " +
                                        str(self.n_lineInicial) +
                                        " e coluna " +
                                        str(self.n_columnInicial))
                return None
            elif estado == 21:
                if self.c == '=':
                    return Token(Tag.OP_GE, ">=", self.n_lineInicial,
                                 self.n_columnInicial)

                self.retornaPonteiro()
                return Token(Tag.OP_GT, ">", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 24:
                if self.c == '=':
                    return Token(Tag.OP_LE, "<=", self.n_lineInicial,
                                 self.n_columnInicial)

                self.retornaPonteiro()
                return Token(Tag.OP_LT, "<", self.n_lineInicial,
                             self.n_columnInicial)
            elif estado == 26:
                if self.c.isalnum():
                    lexema += self.c
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken(lexema.lower())
                    if token is None:

                        token = Token(Tag.ID, lexema, self.n_lineInicial,
                                      self.n_columnInicial)
                        self.ts.addToken(lexema, token)

                    else:
                        token.linha = self.n_lineInicial
                        token.coluna = self.n_columnInicial

                    return token
            elif estado == 29:
                if self.c != '"':
                    if self.c == '\r' or self.c == '\n' or self.c == '':
                        self.sinalizaErroLexico("Erro de sintaxe [" + lexema +
                                                "] na linha " +
                                                str(self.n_lineInicial) +
                                                " e coluna " +
                                                str(self.n_columnInicial))
                        lexema = ''
                        estado = 1
                        return None
                    lexema += self.c
                else:
                    estado = 1

                    return Token(Tag.CHAR_CONST, lexema, self.n_lineInicial,
                                 self.n_columnInicial)
            elif estado == 31:
                if self.c.isdigit():
                    lexema += self.c
                elif self.c == '.':
                    lexema += self.c
                else:
                    self.retornaPonteiro()
                    return Token(Tag.NUM_CONST, lexema, self.n_lineInicial,
                                 self.n_columnInicial)
            elif estado == 35:
                if self.c == '*':
                    estado = 36
                elif self.c == "":
                    self.sinalizaErroLexico("Erro de sintaxe na linha " +
                                            str(self.n_lineInicial) +
                                            " e coluna " +
                                            str(self.n_columnInicial))
                    return None
            elif estado == 36:
                if self.c == '/':
                    estado = 1
                elif self.c == '*':
                    estado = 36
                elif self.c == "":
                    self.sinalizaErroLexico("Erro de sintaxe na linha " +
                                            str(self.n_lineInicial) +
                                            " e coluna " +
                                            str(self.n_columnInicial))
                    return None
                else:
                    estado = 35
            if self.c == '\t':
                self.n_column += 3
            else:
                self.n_column += 1
            if self.c == '\n':
                self.n_line += 1
                self.n_column = 1
예제 #4
0
class Lexer:
    def __init__(self, input_file):
        try:
            self.input_file = open(input_file, 'rb')
            self.lookahead = 0
            self.n_line = 1
            self.n_column = 0
            self.ts = TS()
            self.totalErros = 0
        except IOError:
            print('Erro de abertura do arquivo. Encerrando.')
            sys.exit(0)

    def closeFile(self):
        try:
            self.input_file.close()
        except IOError:
            print('Erro ao fechar arquivo. Encerrando.')
            sys.exit(0)

    def sinalizaErroLexico(self, message):
        self.totalErros = self.totalErros + 1
        print("[Erro Lexico]: ", message, "\n")

    def retornaPonteiro(self):
        if self.lookahead.decode('ascii') != '':
            self.input_file.seek(self.input_file.tell() - 1)
        self.n_column = self.n_column - 1

    def printTS(self):
        self.ts.printTS()

    def proxToken(self):
        estado = 1
        lexema = ""
        c = '\u0000'

        while True:
            self.lookahead = self.input_file.read(1)
            c = self.lookahead.decode('ascii') # caractere lido
            self.n_column = self.n_column + 1

            if estado == 1:
                if c == '':
                    return Token(Tag.EOF, "EOF", self.n_line, self.n_column)
                elif c == ' ' or c == '\t' or c == '\n' or c == '\r':
                    estado = 1
                    if c == '\n':
                        self.n_line = self.n_line + 1
                        self.n_column = 0
                elif c == '=':
                    estado = 2
                elif c == '!':
                    estado = 4
                elif c == '<':
                    estado = 6
                elif c == '>':
                    estado = 9
                elif c.isdigit(): # Verificando se é um número
                    lexema += c
                    estado = 12
                elif c.isalpha(): # Verificando se é uma letra
                    lexema += c
                    estado = 14
                elif c == '/':
                    estado = 16
                elif c == '+':
                    return Token(Tag.OP_AD, "+", self.n_line, self.n_column)
                elif c == '*':
                    return Token(Tag.OP_MUL, "*", self.n_line, self.n_column)
                elif c == '-':
                    return Token(Tag.OP_MIN, "-", self.n_line, self.n_column)
                elif c == '{':
                    return Token(Tag.SMB_OBC, "{", self.n_line, self.n_column)
                elif c == '}':
                    return Token(Tag.SMB_CBC, "}", self.n_line, self.n_column)
                elif c == ';':
                    return Token(Tag.SMB_SEM, ";", self.n_line, self.n_column)
                elif c == ',':
                    return Token(Tag.SMB_COM, ",", self.n_line, self.n_column)
                elif c == '(':
                    return Token(Tag.SMB_OPA, "(", self.n_line, self.n_column)
                elif c == ')':
                    return Token(Tag.SMB_CPA, ")", self.n_line, self.n_column)
                elif c == '"':
                    estado = 21
                else:
                    lexema += c
                    self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " + str(self.n_line) + " e coluna " + str(self.n_column))
                    if self.totalErros == 3:
                        return None
                    else:
                        return ''
            elif estado == 2:
                if c == '=':
                    return Token(Tag.OP_EQ, "==", self.n_line, self.n_column)
                else:
                    self.retornaPonteiro()
                    return Token(Tag.OP_ATRIB, "=", self.n_line, self.n_column)
            elif estado == 4:
                if c == '=':
                    return Token(Tag.OP_NE, "!=", self.n_line, self.n_column)

                self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " + str(self.n_line) + " e coluna " + str(self.n_column))
                self.retornaPonteiro()

                if self.totalErros == 3:
                    return None
                else:
                    return ''
            elif estado == 6:
                if c == '=':
                    return Token(Tag.OP_LE, "<=", self.n_line, self.n_column)

                self.retornaPonteiro()
                return Token(Tag.OP_LT, "<", self.n_line, self.n_column)
            elif estado == 9:
                if c == '=':
                    return Token(Tag.OP_GE, ">=", self.n_line, self.n_column)

                self.retornaPonteiro()
                return Token(Tag.OP_GT, ">", self.n_line, self.n_column)
            elif estado == 12:
                if c.isdigit():
                    lexema += c
                elif c == '.':
                    lexema += c
                    estado = 20
                else:
                    self.retornaPonteiro()
                    return Token(Tag.NUM, lexema, self.n_line, self.n_column)
            elif estado == 14:
                if c.isalnum(): # Verificando se é um número ou uma letra
                    lexema += c
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken(lexema)

                    if token is None:
                        token = Token(Tag.ID, lexema, 0, 0)
                        self.ts.addToken(lexema, token)

                    token.setColuna(self.n_column)
                    token.setLinha(self.n_line)
                    return token
            elif estado == 16:
                if c == '/':
                    estado = 17
                elif c == '*':
                    estado = 18
                else:
                    self.retornaPonteiro()
                    return Token(Tag.OP_DIV, '/', self.n_line, self.n_column)
            elif estado == 17:
                if c == '\n':
                    self.n_line = self.n_line + 1
                    self.n_column = 0
                    estado = 1
                elif c == '':
                    return Token(Tag.EOF, "EOF", self.n_line, self.n_column)
            elif estado == 18:
                if c == '*':
                    estado = 19
                elif c == '\n':
                    self.n_line = self.n_line + 1
                    self.n_column = 1
                elif c == '':
                    return Token(Tag.EOF, "EOF", self.n_line, self.n_column - 1)
            elif estado == 19:
                if c == '/':
                    estado = 1
                else:
                    estado = 18
            elif estado == 20:
                if c.isdigit():
                    lexema += c
                else:
                    self.retornaPonteiro()
                    return Token(Tag.NUM_CONST, lexema, self.n_line, self.n_column)
            elif estado == 21:
                if c == '"':
                    return Token(Tag.CHAR_CONST, lexema, self.n_line, self.n_column - 1)
                elif c == '\n':
                    self.n_line = self.n_line + 1
                    self.n_column = 0
                elif c == '':
                    coluna = self.n_column
                    self.n_column = 0
                    return Token(Tag.CHAR_CONST, lexema, self.n_line, coluna)
                lexema += c
예제 #5
0
class Lexer():
    def __init__(self, input_file):
        try:
            self.input_file = open(input_file, 'rb')
            self.lookahead = 0
            self.n_line = 1
            self.n_column = 1
            self.lexemaAnt = ""
            self.ts = TS()
        except IOError:
            print('Erro de abertura do arquivo. Encerrando.')
            sys.exit(0)

    def closeFile(self):
        try:
            self.input_file.close()
        except IOError:
            print('Erro dao fechar arquivo. Encerrando.')
            sys.exit(0)

    def sinalizaErroLexico(self, message):
        print("[Erro Lexico]: ", message, "\n")

    def retornaPonteiro(self):
        if (self.lookahead.decode('ascii') != ''):
            self.input_file.seek(self.input_file.tell() - 1)

    def printTS(self):
        self.ts.printTS()

    def proxToken(self):
        estado = 1
        lexema = ""
        lexemaAnt = None
        negacao = False
        c = '\u0000'

        while (True):
            self.lookahead = self.input_file.read(1)
            c = self.lookahead.decode('ascii')

            if (estado == 1):
                if (c == ''):
                    return Token(Tag.EOF, "EOF", self.n_line, self.n_column)
                elif (c == ' ' or c == '\t' or c == '\r'):
                    estado = 1
                elif (c == '\n'):
                    estado = 1
                    self.n_line += 1
                    self.n_column = 0
                elif (c.isalpha()):
                    lexema += c
                    estado = 2
                elif (c.isdigit()):
                    lexema += c
                    estado = 5
                elif (c == '"'):
                    lexema += c
                    estado = 11
                elif (c == '-'):
                    estado = 15
                elif (c == '!'):
                    estado = 16
                elif (c == "<"):
                    estado = 17
                elif (c == ">"):
                    estado = 20
                elif (c == "="):
                    estado = 23
                elif (c == "/"):
                    estado = 27
                elif (c == "*"):
                    estado = 28
                elif (c == "+"):
                    estado = 29
                elif (c == "#"):
                    estado = 31
                elif (c == ","):
                    estado = 32
                elif (c == "."):
                    estado = 33
                elif (c == ":"):
                    estado = 34
                elif (c == ";"):
                    estado = 35
                elif (c == "("):
                    estado = 36
                elif (c == ")"):
                    estado = 37
                elif (c == "["):
                    estado = 38
                elif (c == "]"):
                    estado = 39
                else:
                    self.sinalizaErroLexico("Caractere invalido [" + c +
                                            "] na linha " + str(self.n_line) +
                                            " e coluna " + str(self.n_column))
                    estado = 1
            elif (estado == 2):
                if (c.isalnum()):
                    lexema += c
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken(lexema)
                    if (token is None):
                        token = Token(Tag.ID, lexema, self.n_line,
                                      self.n_column)
                        self.ts.addToken(lexema, token)
                    self.lexemaAnt = lexema
                    return token
            elif (estado == 5):
                if (c.isdigit() or c == '.'):
                    lexema += c
                else:
                    self.retornaPonteiro()
                    if ('.' in lexema):
                        token = self.ts.getToken(lexema)
                        if (token is None):
                            token = Token(Tag.DOUBLE, lexema, self.n_line,
                                          self.n_column)
                            self.ts.addToken(lexema, token)
                        self.lexemaAnt = lexema
                        return token
                    else:
                        token = self.ts.getToken(lexema)
                        if (token is None):
                            token = Token(Tag.INTEGER, lexema, self.n_line,
                                          self.n_column)
                            self.ts.addToken(lexema, token)
                        self.lexemaAnt = lexema
                        return token
            elif (estado == 11):
                if (c.isalnum() or c.isalpha() or c.isdigit() or c == '"'
                        or c == " " or c == "!" or c == "," or c == "+"
                        or c == "-" or c == "*" or c == "/" or c == "<"
                        or c == "<=" or c == ">" or c == ">=" or c == "="
                        or c == "==" or c == "!" or c == "!=" or c == "("
                        or c == ':'):
                    lexema += c
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken(lexema)
                    if (token is None):
                        token = Token(Tag.STRING, lexema, self.n_line,
                                      self.n_column)
                        # self.ts.addToken(lexema, token)
                    self.lexemaAnt = lexema
                    return token
            elif (estado == 15):
                self.retornaPonteiro()
                if (self.lexemaAnt == ""):
                    return Token(Tag.OP_UNARIO, "-", self.n_line,
                                 self.n_column)
                elif (self.lexemaAnt == "+" or self.lexemaAnt == "-"
                      or self.lexemaAnt == "*" or self.lexemaAnt == "/"
                      or self.lexemaAnt == "<" or self.lexemaAnt == "<="
                      or self.lexemaAnt == ">" or self.lexemaAnt == ">="
                      or self.lexemaAnt == "=" or self.lexemaAnt == "=="
                      or self.lexemaAnt == "!" or self.lexemaAnt == "!="
                      or self.lexemaAnt == "("):
                    return Token(Tag.OP_UNARIO, "-", self.n_line,
                                 self.n_column)
                elif (self.lexemaAnt.isalpha() or self.lexemaAnt.isalnum()):
                    self.lexemaAnt = '-'
                    return Token(Tag.OP_SUBTRACAO, "-", self.n_line,
                                 self.n_column)
                else:
                    self.lexemaAnt = '-'
                    return Token(Tag.OP_SUBTRACAO, "-", self.n_line,
                                 self.n_column)
            elif (estado == 16):
                if (c == '='):
                    token = self.ts.getToken('!=')
                    if (token is None):
                        token = Token(Tag.OP_DIFERENTE, "!=", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('!=', token)
                    self.lexemaAnt = '!='
                    return token
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken('!')
                    if (token is None):
                        token = Token(Tag.OP_UNARIO, "!", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('!', token)
                    self.lexemaAnt = '!'
                    return token
            elif (estado == 17):
                if (c == '='):
                    token = self.ts.getToken('<=')
                    if (token is None):
                        token = Token(Tag.OP_MENOR_IGUAL, "<=", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('<=', token)
                    self.lexemaAnt = '<='
                    return token
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken('<')
                    if (token is None):
                        token = Token(Tag.OP_MENOR, "<", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('<', token)
                    self.lexemaAnt = '<'
                    return token
            elif (estado == 20):
                if (c == '='):
                    token = self.ts.getToken('>=')
                    if (token is None):
                        token = Token(Tag.OP_MAIOR_IGUAL, ">=", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('>=', token)
                    self.lexemaAnt = '>='
                    return token
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken('>')
                    if (token is None):
                        token = Token(Tag.OP_MAIOR, ">", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('>', token)
                    self.lexemaAnt = '>'
                    return token
            elif (estado == 23):
                if (c == '='):
                    token = self.ts.getToken('==')
                    if (token is None):
                        token = Token(Tag.OP_IGUAL, "==", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('==', token)
                    self.lexemaAnt = '=='
                    return token
                else:
                    self.retornaPonteiro()
                    token = self.ts.getToken('=')
                    if (token is None):
                        token = Token(Tag.OP_IGUAL, "=", self.n_line,
                                      self.n_column)
                        # self.ts.addToken('=', token)
                    self.lexemaAnt = '='
                    return token
            elif (estado == 27):
                self.retornaPonteiro()
                token = self.ts.getToken('/')
                if (token is None):
                    token = Token(Tag.OP_DIVISAO, "/", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('/', token)
                self.lexemaAnt = '/'
                return token
            elif (estado == 28):
                self.retornaPonteiro()
                token = self.ts.getToken('*')
                if (token is None):
                    token = Token(Tag.OP_PRODUTO, "*", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('*', token)
                self.lexemaAnt = '*'
                return token
            elif (estado == 29):
                self.retornaPonteiro()
                token = self.ts.getToken('+')
                if (token is None):
                    token = Token(Tag.OP_ADICAO, "+", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('+', token)
                self.lexemaAnt = '+'
                return token
            elif (estado == 31):
                if (c == '\n' or c == ""):
                    estado = 1
                    self.n_line += 1
                    self.n_column = 1
                    self.lexemaAnt = ""
            elif (estado == 32):
                self.retornaPonteiro()
                token = self.ts.getToken(',')
                if (token is None):
                    token = Token(Tag.SIMB_VIRGULA, ",", self.n_line,
                                  self.n_column)
                    # self.ts.addToken(',', token)
                self.lexemaAnt = ','
                return token
            elif (estado == 33):
                self.retornaPonteiro()
                token = self.ts.getToken('.')
                if (token is None):
                    token = Token(Tag.SIMB_PONTO, ".", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('.', token)
                self.lexemaAnt = '.'
                return token
            elif (estado == 34):
                self.retornaPonteiro()
                token = self.ts.getToken(':')
                if (token is None):
                    token = Token(Tag.SIMB_DOIS_PONTOS, ":", self.n_line,
                                  self.n_column)
                    # self.ts.addToken(':', token)
                self.lexemaAnt = ':'
                return token
            elif (estado == 35):
                self.retornaPonteiro()
                token = self.ts.getToken(';')
                if (token is None):
                    token = Token(Tag.SIMB_PONTO_VIRGULA, ";", self.n_line,
                                  self.n_column)
                    # self.ts.addToken(';', token)
                self.lexemaAnt = ';'
                return token
            elif (estado == 36):
                self.retornaPonteiro()
                token = self.ts.getToken('(')
                if (token is None):
                    token = Token(Tag.SIMB_ABRE_PARENT, "(", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('(', token)
                self.lexemaAnt = '('
                return token
            elif (estado == 37):
                self.retornaPonteiro()
                token = self.ts.getToken(')')
                if (token is None):
                    token = Token(Tag.SIMB_FECHA_PARENT, ")", self.n_line,
                                  self.n_column)
                    # self.ts.addToken(')', token)
                self.lexemaAnt = ')'
                return token
            elif (estado == 38):
                self.retornaPonteiro()
                token = self.ts.getToken('[')
                if (token is None):
                    token = Token(Tag.SIMB_ABRE_CHAVE, "[", self.n_line,
                                  self.n_column)
                    # self.ts.addToken('[', token)
                self.lexemaAnt = '['
                return token
            elif (estado == 39):
                self.retornaPonteiro()
                token = self.ts.getToken(']')
                if (token is None):
                    token = Token(Tag.SIMB_FECHA_CHAVE, "]", self.n_line,
                                  self.n_column)
                    # self.ts.addToken(']', token)
                self.lexemaAnt = ']'
                return token

            self.n_column += 1
예제 #6
0
class Lexer():
   '''
   Classe que representa o Lexer:
   
   [1] Voce devera se preocupar quando incremetar as linhas e colunas,
   assim como quando decrementar ou reinicia-las. Lembre-se, ambas 
   comecam em 1.
   [2] Toda vez que voce encontrar um lexema completo, voce deve retornar
   um objeto Token(Tag, "lexema", linha, coluna). Cuidado com as
   palavras reservadas, que ja sao cadastradas na TS. Essa consulta
   voce devera fazer somente quando encontrar um Identificador.
   [3] Se o caractere lido nao casar com nenhum caractere esperado,
   apresentar a mensagem de erro na linha e coluna correspondente.
   Obs.: lembre-se de usar o metodo retornaPonteiro() quando necessario. 
         lembre-se de usar o metodo sinalizaErroLexico() para mostrar
         a ocorrencia de um erro lexico.
   '''
   def __init__(self, input_file):
      try:
         self.input_file = open(input_file, 'rb')
         self.lookahead = 0
         self.n_line = 1
         self.n_column = 1
         self.ts = TS()
      except IOError:
         print('Erro de abertura do arquivo. Encerrando execução!')
         sys.exit(0)

   def closeFile(self):
      try:
         self.input_file.close()
      except IOError:
         print('Erro dao fechar arquivo. Encerrando execução!')
         sys.exit(0)

   def sinalizaErroLexico(self, message):
      print("[Erro Lexico]: ", message, "\n");

   def retornaPonteiro(self):
      if(self.lookahead.decode('ascii') != ''):
         self.input_file.seek(self.input_file.tell()-1)

   def printTS(self):
      self.ts.printTS()

   def proxToken(self):
      estado = 1
      lexema = ""
      c = '\u0000'

      while(True):
         self.lookahead = self.input_file.read(1)
         c = self.lookahead.decode('ascii')

         if(estado == 1):
            if(c == ''):
               return Token(Tag.EOF, "EOF", self.n_line, self.n_column)
            elif(c == ' ' or c == '\t' or c == '\n' or c == '\r'):
               estado = 1
            elif(c == '='):
               estado = 2
            elif(c == '!'):
               estado = 4
            elif(c == '<'):
               estado = 6
            elif(c == '>'):
               estado = 9
            elif(c.isdigit()):
               lexema += c
               estado = 12
            elif(c.isalpha()):
               lexema += c
               estado = 14
            elif(c == '/'):
               #estado = 16
               return Token(Tag.OP_DIVISAO, "/", self.n_line, self.n_column)
            elif (c == '*'):
               #estado = 19
               return Token(Tag.OP_MULTIPLICACAO, "*", self.n_line, self.n_column)
            elif (c == '+'):
               #estado = 20
               return Token(Tag.OP_SOMA, "+", self.n_line, self.n_column)
            elif (c == '-'):
               #estado = 21
               return Token(Tag.OP_SUBTRACAO, "-", self.n_line, self.n_column)
            elif (c == '('):
               #estado = 22
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               return None
         elif(estado == 2):
            if(c == '='):
               #estado = 3
               return Token(Tag.OP_IGUAL, "==", self.n_line, self.n_column)
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               return None
         elif(estado == 4):
            if(c == '='):
               #estado = 5
               return Token(Tag.OP_DIFERENTE, "!=", self.n_line, self.n_column)
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               return None
         elif(estado == 6):
            if(c == '='):
               #estado = 7
               return Token(Tag.OP_MENOR_IGUAL, "<=", self.n_line, self.n_column)
            else:
               #estado = 8
               self.retornaPonteiro()
               return Token(Tag.OP_MENOR, "<", self.n_line, self.n_column)
         elif(estado == 9):
            if(c == '='):
               #estado = 10
               return Token(Tag.OP_MAIOR_IGUAL, ">=", self.n_line, self.n_column)
            else:
               #estado = 11
               self.retornaPonteiro()
               return Token(Tag.OP_MAIOR, ">", self.n_line, self.n_column)
         elif(estado == 12):
            if(c.isdigit()):
               #continua no estado 12
               lexema += c           
            else:
               #estado = 13
               self.retornaPonteiro()
               return Token(Tag.NUM, lexema, self.n_line, self.n_column)
         elif(estado == 14):
            if(c.isalnum()):
               #continua no estado 14
               lexema += c
            else:
               #estado = 15
               self.retornaPonteiro()
               token = self.ts.getToken(lexema)
               if(token is None):
                  token = Token(Tag.ID, lexema, self.n_line, self.n_column)
                  self.ts.addToken(lexema, token)

               return token
         '''
예제 #7
0
class Lexer():
   '''
   Classe que representa o Lexer:
   
   [1] Voce devera se preocupar quando incremetar as linhas e colunas,
   assim como quando decrementar ou reinicia-las. Lembre-se, ambas 
   comecam em 1.
   [2] Toda vez que voce encontrar um lexema completo, voce deve retornar
   um objeto Token(Tag, "lexema", linha, coluna). Cuidado com as
   palavras reservadas, que ja sao cadastradas na TS. Essa consulta
   voce devera fazer somente quando encontrar um Identificador.
   [3] Se o caractere lido nao casar com nenhum caractere esperado,
   apresentar a mensagem de erro na linha e coluna correspondente.
   Obs.: lembre-se de usar o metodo retornaPonteiro() quando necessario. 
         lembre-se de usar o metodo sinalizaErroLexico() para mostrar
         a ocorrencia de um erro lexico.
   '''
   def __init__(self, input_file):
      try:
         self.input_file = open(input_file, 'rb')
         self.lookahead = 0
         self.n_line = 1
         self.n_column = 1
         self.ts = TS()
         
      except IOError:
         print('Erro de abertura do arquivo. Encerrando execução!')
         sys.exit(0)

   def closeFile(self):
      try:
         self.input_file.close()
      except IOError:
         print('Erro dao fechar arquivo. Encerrando execução!')
         sys.exit(0)

   def sinalizaErroLexico(self, message):
      print("\n[Erro Lexico]: ", message, "\n")

   def retornaPonteiro(self):
      if(self.lookahead.decode('ascii') != ''):
         self.input_file.seek(self.input_file.tell()-1)
         self.n_column-=1

   def printTS(self):
      self.ts.printTS()

   def proxToken(self, last_token):
      estado = 1
      lexema = ""
      c = '\u0000'
      token = None
      
      while(True):
         self.lookahead = self.input_file.read(1)
         c = self.lookahead.decode('ascii')

         #Contando Linhas e Colunas
         if(c == '\n'):
            self.n_line += 1
            self.n_column = 1
         elif (c == '\t'):
            self.n_column += 4
         else:
            self.n_column += 1
         
         if(estado == 1):
            if(c == ''):
               self.ts.addToken("EOF", Token(Tag.EOF, "EOF", self.n_line, self.n_column))
               token = Token(Tag.EOF, "EOF", self.n_line, self.n_column)
            elif(c == ' ' or c == '\t' or c == '\n' or c == '\r'):
               estado = 1
            elif(c == '='):
               estado = 2
            elif(c == '!'):
               estado = 4
            elif(c == '<'):
               estado = 6
            elif(c == '>'):
               estado = 9
            elif(c.isdigit()):
               lexema += c
               estado = 12
            elif(c.isalpha()):
               lexema += c
               estado = 14
            elif(c == '\"'):
               estado = 27
            elif(c == '#'):
               estado = 18
            elif(c == '.'):
               #estado = 16
               #self.ts.addToken(".", Token(Tag.KW_PONTO, ".", self.n_line, self.n_column))
               token = Token(Tag.KW_PONTO, ".", self.n_line, self.n_column)
            elif(c == '/'):
               #estado = 16
               #self.ts.addToken("/", Token(Tag.OP_DIVISAO, "/", self.n_line, self.n_column))
               token = Token(Tag.OP_DIVISAO, "/", self.n_line, self.n_column)
            elif (c == ','):
               #estado = 17
               #self.ts.addToken(",", Token(Tag.VG, ",", self.n_line, self.n_column))
               token = Token(Tag.VG, ",", self.n_line, self.n_column)
            elif (c == '*'):
               #estado = 19
               #self.ts.addToken("*", Token(Tag.OP_MULTIPLICACAO, "*", self.n_line, self.n_column))
               token = Token(Tag.OP_MULTIPLICACAO, "*", self.n_line, self.n_column)
            elif (c == '+'):
               #estado = 20
               #self.ts.addToken("+", Token(Tag.OP_SOMA, "+", self.n_line, self.n_column))
               token = Token(Tag.OP_SOMA, "+", self.n_line, self.n_column)
            elif (c == '-'):
               #estado = 21
                  if(last_token.nome != Tag.KW_INTEGER and last_token.nome != Tag.KW_DOUBLE and last_token.nome != Tag.ID):
                     token = Token(Tag.OP_INVERSOR, "-", self.n_line, self.n_column)
                  #self.ts.addToken("-", Token(Tag.OP_SUBTRACAO, "-", self.n_line, self.n_column))
                  else:
                     token = Token(Tag.OP_SUBTRACAO, "-", self.n_line, self.n_column)
            elif (c == '('):
               #estado = 22
               #self.ts.addToken("(", Token(Tag.AP, "(", self.n_line, self.n_column))
               token = Token(Tag.AP, "(", self.n_line, self.n_column)
            elif (c == ')'):
               #estado = 23
               #self.ts.addToken(")", Token(Tag.FP, ")", self.n_line, self.n_column))
               token = Token(Tag.FP, ")", self.n_line, self.n_column)
            elif (c == '['):
               #estado = 24
               #self.ts.addToken("[", Token(Tag.AT, "[", self.n_line, self.n_column))
               token = Token(Tag.AT, "[", self.n_line, self.n_column)
            elif (c == ':'):
               #estado = 25
               #self.ts.addToken(":", Token(Tag.DP, ":", self.n_line, self.n_column))
               token = Token(Tag.DP, ":", self.n_line, self.n_column)
            elif (c == ']'):
               #estado = 26
               #self.ts.addToken("]", Token(Tag.FT, "]", self.n_line, self.n_column))
               token = Token(Tag.FT, "]", self.n_line, self.n_column)
            elif (c == ';'):
               #estado = 28
               #self.ts.addToken(";", Token(Tag.PV, ";", self.n_line, self.n_column))
               token = Token(Tag.PV, ";", self.n_line, self.n_column)
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               token = None
         elif(estado == 2):
            if(c == '='):
               #estado = 3
               #self.ts.addToken("==", Token(Tag.OP_IGUAL, "==", self.n_line, self.n_column))
               token = Token(Tag.OP_IGUAL, "==", self.n_line, self.n_column)
            else:
               #estado = 34
               self.retornaPonteiro()
               #self.ts.addToken("=", Token(Tag.CP, "=", self.n_line, self.n_column))
               token = Token(Tag.CP, "=", self.n_line, self.n_column)
         elif(estado == 4):
            if(c == '='):
               #estado = 5
               #self.ts.addToken("!=", Token(Tag.OP_DIFERENTE, "!=", self.n_line, self.n_column))
               token = Token(Tag.OP_DIFERENTE, "!=", self.n_line, self.n_column)
            else:
               #estado = 29
               self.retornaPonteiro()
               #self.ts.addToken("!", Token(Tag.OP_NEGACAO, "!", self.n_line, self.n_column))
               token = Token(Tag.OP_NEGACAO, "!", self.n_line, self.n_column)
         elif(estado == 6):
            if(c == '='):
               #estado = 7
               #self.ts.addToken("<=", Token(Tag.OP_MENOR_IGUAL, "<=", self.n_line, self.n_column))
               token = Token(Tag.OP_MENOR_IGUAL, "<=", self.n_line, self.n_column)
            else:
               #estado = 8
               self.retornaPonteiro()
               #self.ts.addToken("<", Token(Tag.OP_MENOR, "<", self.n_line, self.n_column))
               token = Token(Tag.OP_MENOR, "<", self.n_line, self.n_column)
         elif(estado == 9):
            if(c == '='):
               #estado = 10
               #self.ts.addToken(">=", Token(Tag.OP_MAIOR_IGUAL, ">=", self.n_line, self.n_column))
               token = Token(Tag.OP_MAIOR_IGUAL, ">=", self.n_line, self.n_column)
            else:
               #estado = 11
               self.retornaPonteiro()
               #self.ts.addToken(">", Token(Tag.OP_MAIOR, ">", self.n_line, self.n_column))
               token = Token(Tag.OP_MAIOR, ">", self.n_line, self.n_column)
         elif(estado == 12):
            if(c.isdigit()):
               #continua no estado 12 (estado = 12)
               lexema += c           
            elif(c == '.'):
               estado = 31
               lexema += c
            else:
               #estado = 13
               self.retornaPonteiro()
               #self.ts.addToken(lexema, Token(Tag.KW_INTEGER, lexema, self.n_line, self.n_column ))
               token = Token(Tag.KW_INTEGER, lexema, self.n_line, self.n_column )
         elif(estado == 14):
            if(c.isalnum() or c == '_'):
               #continua no estado 14
               lexema += c
            else:
               #estado = 15
               self.retornaPonteiro()
               tokenComp = self.ts.getToken(lexema)        
               if(tokenComp is None):
                  tokenComp = Token(Tag.ID, lexema, self.n_line, self.n_column )
                  self.ts.addToken(lexema, tokenComp)
               else:
                  tokenComp = Token(self.ts.getToken(lexema).nome, lexema, self.n_line, self.n_column )
               token = tokenComp
         elif(estado == 18):
            if(c != '\n'):
               estado = 18 
            else:
               estado = 1
         elif(estado == 27):
            if(c != '\"'):
               estado = 30
               lexema += c
            elif(c == '\"'):
               self.sinalizaErroLexico("String vazia na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               #self.ts.addToken(lexema, Token(Tag.KW_STRING, lexema, self.n_line, self.n_column  ))
               estado = 1
               token = None
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               token = None
         elif(estado == 30): 
            if(c == ''):
               self.sinalizaErroLexico("String não finalizada corretamente na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column) +". Finalizando compilação.")
               token = None
               estado = 1
            elif(c != '\"'):
               #estado permanece no 30 (estado = 30)
               lexema += c
            elif(c == '\"' ):
               #estado = 35
               #self.ts.addToken(lexema, Token(Tag.KW_STRING, lexema, self.n_line, self.n_column  ))
               token = Token(Tag.KW_STRING, lexema, self.n_line, self.n_column )
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               token = None
         elif(estado == 31):
            if(c.isdigit()):
               estado = 32
               lexema +=c
            else:
               self.sinalizaErroLexico("Caractere invalido [" + c + "] na linha " +
               str(self.n_line) + " e coluna " + str(self.n_column))
               token = None
         elif(estado == 32):
            if(c.isdigit()):
               #estado permanece no 32 (estado = 32)
               lexema += c
            else:
               #estado = 33
               self.retornaPonteiro()
               #self.ts.addToken(lexema, Token(Tag.KW_DOUBLE, lexema, self.n_line, self.n_column ))
               token = Token(Tag.KW_DOUBLE, lexema, self.n_line, self.n_column )

         if (token is not None):

            return token