import sys from lexer import * from astnodes import * class Parser: def __init__(self, lexer): self.lexer = lexer self.tokenAtual = None self.proximoToken = None self.nextToken() self.nextToken() #Retorna true se o Token **atual** casa com tipo de Token esperado def checkToken(self, tipo): return tipo == self.tokenAtual.kind #Retorna true se o próximo Token **(peek)** casa com tipo de Token esperado def checkPeek(self, tipo): return tipo == self.proximoToken.kind #Tenta fazer o casamento do Token atual. Se conseguir, avança para o próximo Token. Do contrário, gera mensagem de erro. def match(self, tipo): if not self.checkToken(tipo): self.abort("Esperava por token do tipo " + tipo.name + ", mas apareceu " + self.tokenAtual.kind.name) else: self.nextToken() # Avançando com os ponteiros dos tokens (atual e peek) def nextToken(self): self.tokenAtual = self.proximoToken self.proximoToken = self.lexer.getToken() def abort(self, msg): sys.exit("Erro sintático: "+msg) # S' ::= S$ # S ::= (E";")* # E ::= T (("+"|"-") T)* # T ::= F (("*"|"/") F)* # F ::= num | id | "(" E ")" # S' ::= S$ def parse(self): program = self.S() self.match(TokenType.EOF) return program # S ::= (E";")* def S(self): explist = [] while not(self.checkToken(TokenType.EOF)): explist.append(self.E()) self.match(TokenType.SEMICOLON) return explist # E ::= T (("+"|"-") T)* def E(self): #(potencialmente lado esquerdo da soma) node = self.T() while True: if self.checkToken(TokenType.PLUS): self.match(TokenType.PLUS) #lado direito da soma t = self.T() node = SumExpr(node, t) elif self.checkToken(TokenType.MINUS): self.match(TokenType.MINUS) t = self.T() node = SubExpr(node, t) else: break return node # T ::= F (("*"|"/") F)* def T(self): node = self.F() # TODO ajustar aqui while self.checkToken(TokenType.ASTERISK) or self.checkToken(TokenType.SLASH): if self.checkToken(TokenType.ASTERISK): self.match(TokenType.ASTERISK) f = self.F() node = MulExpr(node, f) elif self.checkToken(TokenType.SLASH): self.match(TokenType.SLASH) f = self.F() node = DivExpr(node, f) return node # F ::= num | id | "(" E ")" def F(self): node = None if self.checkToken(TokenType.NUMBER): numero = int(self.tokenAtual.text) node = NumExpr(numero) # print(node) self.match(TokenType.NUMBER) elif self.checkToken(TokenType.IDENT): nome = self.tokenAtual.text node = IdExpr(nome) self.match(TokenType.IDENT) elif self.checkToken(TokenType.L_PAREN): self.match(TokenType.L_PAREN) node = self.E() self.match(TokenType.R_PAREN) else: self.abort('Token inesperado!') return node