def if_expr_cases(self, case_keyword): res = ParseResult() cases = [] else_case = None if not self.current_tok.matches(TT_KEYWORD, case_keyword): return res.failure( InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + case_keyword + "'")) res.register_advancement() self.advance() condition = res.register(self.expr()) if res.error: return res if not self.current_tok.matches(TT_KEYWORD, 'tonce'): return res.failure( InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "tonce'")) res.register_advancement() self.advance() if self.current_tok.type == TT_NEWLINE: res.register_advancement() self.advance() statements = res.register(self.statements()) if res.error: return res cases.append((condition, statements, True)) if self.current_tok.matches(TT_KEYWORD, 'hastaaca'): res.register_advancement() self.advance() else: all_cases = res.register(self.if_expr_b_or_c()) if res.error: return res new_cases, else_case = all_cases cases.extend(new_cases) else: expr = res.register(self.statement()) if res.error: return res cases.append((condition, expr, False)) all_cases = res.register(self.if_expr_b_or_c()) if res.error: return res new_cases, else_case = all_cases cases.extend(new_cases) return res.success((cases, else_case))
def expr(self): res = ParseResult() if self.current_tok.matches(TT_KEYWORD, "che") or self.current_tok.matches( TT_KEYWORD, "digamos"): res.register_advancement() self.advance() if self.current_tok.type != TT_IDENTIFIER: return res.failure( InvalidSyntaxError(self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["identifierExpected"])) var_name = [self.current_tok] res.register_advancement() self.advance() while self.current_tok.type == TT_COMMA: self.advance() if self.current_tok.type != TT_IDENTIFIER: return res.failure( InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["identifierExpected"])) var_name.append(self.current_tok) self.advance() if self.current_tok.type != TT_EQ: return res.failure( InvalidSyntaxError(self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["equalExpected"])) res.register_advancement() self.advance() expr = res.register(self.expr()) if res.error: return res return res.success(VarAssignNode(var_name, expr)) node = res.register( self.bin_op(self.comp_expr, ((TT_KEYWORD, "y"), (TT_KEYWORD, "o")))) if res.error: return res.failure( InvalidSyntaxError(self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"])) return res.success(node)
def statement(self): res = ParseResult() pos_start = self.current_tok.pos_start.copy() if self.current_tok.matches(TT_KEYWORD, 'tirame'): res.register_advancement() self.advance() expr = res.try_register(self.expr()) if not expr: self.reverse(res.to_reverse_count) return res.success(ReturnNode(expr, pos_start, self.current_tok.pos_start.copy())) if self.current_tok.matches(TT_KEYWORD, 'segui'): res.register_advancement() self.advance() return res.success(ContinueNode(pos_start, self.current_tok.pos_start.copy())) if self.current_tok.matches(TT_KEYWORD, 'piquete'): res.register_advancement() self.advance() return res.success(BreakNode(pos_start, self.current_tok.pos_start.copy())) expr = res.register(self.expr()) if res.error: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) return res.success(expr)
def if_expr_c(self): res = ParseResult() else_case = None # si tenemo un else hacemo eto if self.current_tok.matches(TT_KEYWORD, 'alosumo'): res.register_advancement() self.advance() if self.current_tok.type == TT_NEWLINE: res.register_advancement() self.advance() statements = res.register(self.statements()) if res.error: return res else_case = (statements, True) if self.current_tok.matches(TT_KEYWORD, 'hastaaca'): res.register_advancement() self.advance() else: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "hastaaca'" )) else: expr = res.register(self.statement()) if res.error: return res else_case = (expr, False) # si no tenemo else le mandamo al none return res.success(else_case)
def while_expr(self): res = ParseResult() if not self.current_tok.matches(TT_KEYWORD, "mientras"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "mientras'" )) res.register_advancement() self.advance() condition = res.register(self.expr()) if res.error: return res if not self.current_tok.matches (TT_KEYWORD, "tonce"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "tonce'" )) res.register_advancement() self.advance() if self.current_tok.type == TT_NEWLINE: res.register_advancement() self.advance() body = res.register(self.statements()) if res.error: return res if not self.current_tok.matches(TT_KEYWORD, "hastaaca"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "hastaaca'" )) res.register_advancement() self.advance() return res.success(WhileNode(condition, body, True)) body = res.register(self.statement()) if res.error: return res return res.success(WhileNode(condition, body, False))
def parse(self): res = self.statements() if not res.error and self.current_tok.type != TT_EOF: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) return res
def list_expr(self): res = ParseResult() element_nodes = [] pos_start = self.current_tok.pos_start.copy() if self.current_tok.type != TT_LSQUARE: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "['" )) res.register_advancement() self.advance() # si cierra el corchet termina las cuestione if self.current_tok.type == TT_RSQUARE: res.register_advancement() self.advance() # si no lo cierra las sigue else: element_nodes.append(res.register(self.expr())) if res.error: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) while self.current_tok.type == TT_COMMA: res.register_advancement() self.advance() element_nodes.append(res.register(self.expr())) if res.error: return res #si tiene mas de una cuestion y no cierra el corchet tamo complicado if self.current_tok.type != TT_RSQUARE: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + ")' o ','" )) res.register_advancement() self.advance() return res.success(ListNode( element_nodes, pos_start, self.current_tok.pos_end.copy() ))
def comp_expr(self): res = ParseResult() if self.current_tok.matches(TT_KEYWORD, "no"): op_tok = self.current_tok res.register_advancement() self.advance() node = res.register(self.comp_expr()) if res.error: return res return res.success(UnaryOpNode(op_tok, node)) node = res.register(self.bin_op(self.arith_expr, (TT_EE,TT_NE,TT_LT,TT_GT,TT_LTE,TT_GTE,TT_MM))) if res.error: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) return res.success(node)
def call(self): res = ParseResult() atom = res.register(self.atom()) if res.error: return res # Si es una lista le manda a una lista if self.current_tok.type == TT_LSQUARE: res.register_advancement() self.advance() listIndex = res.register(self.expr()) if res.error: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) if self.current_tok.type != TT_RSQUARE: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "]'" )) res.register_advancement() self.advance() return res.success(CallListNode(atom, listIndex)) # Si es una funcion le manda a la funcion if self.current_tok.type == TT_LPAREN: res.register_advancement() self.advance() arg_nodes = [] if self.current_tok.type == TT_RPAREN: res.register_advancement() self.advance() else: arg_nodes.append(res.register(self.expr())) if res.error: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["exprExpected"] )) while self.current_tok.type == TT_COMMA: res.register_advancement() self.advance() arg_nodes.append(res.register(self.expr())) if res.error: return res if self.current_tok.type != TT_RPAREN: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + ")' o ','" )) res.register_advancement() self.advance() return res.success(CallNode(atom, arg_nodes)) return res.success(atom)
def func_def(self): res = ParseResult() # si no le pones la keyword de funcion tamo complicado if not self.current_tok.matches(TT_KEYWORD, 'definime'): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "FUN'" )) res.register_advancement() self.advance() # si tiene nombre le hace un dni con su nombre if self.current_tok.type == TT_IDENTIFIER: var_name_tok = self.current_tok res.register_advancement() self.advance() if self.current_tok.type != TT_LPAREN: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "('" )) # si no tiene nombre la hace anonimu' ah re jakier else: var_name_tok = None if self.current_tok.type != TT_LPAREN: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "('" )) res.register_advancement() self.advance() arg_name_toks = [] # aca agarra los argumento. si tiene un identifaier le manda fruta y sino no duh if self.current_tok.type == TT_IDENTIFIER: arg_name_toks.append(self.current_tok) res.register_advancement() self.advance() while self.current_tok.type == TT_COMMA: res.register_advancement() self.advance() if self.current_tok.type != TT_IDENTIFIER: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "nombre de variable'" )) arg_name_toks.append(self.current_tok) res.register_advancement() self.advance() if self.current_tok.type != TT_RPAREN: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + ",' o ')'" )) # si no tiene identifaier osea que no tiene argumentos # se fija si cierra parentesis. si no lo cierra rompe todo else: if self.current_tok.type != TT_RPAREN: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "nombre de variable' o ')'" )) res.register_advancement() self.advance() # si tiene arrow se fija por una cuestion sola if self.current_tok.type == TT_ARROW: res.register_advancement() self.advance() body = res.register(self.expr()) if res.error: return res return res.success(FuncDefNode( var_name_tok, arg_name_toks, body, True )) # si no tiene arrow tiene que tener una niu lain if self.current_tok.type != TT_NEWLINE: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "=>' o nueva linea (\\n)" )) #si tiene niu lain le manda hasta un hastaaca we re claro era el tipo res.register_advancement() self.advance() body = res.register(self.statements()) if res.error: return res # y si no tiene un hastaaca rompe todo... # Me estoy dando cuenta que rompe todo en cualquier momento if not self.current_tok.matches(TT_KEYWORD, "hastaaca"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "hastaaca'" )) res.register_advancement() self.advance() return res.success(FuncDefNode( var_name_tok, arg_name_toks, body, False ))
def for_expr(self): res = ParseResult() if not self.current_tok.matches(TT_KEYWORD, "agarra"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "agarra'" )) res.register_advancement() self.advance() if self.current_tok.type != TT_IDENTIFIER: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "nombre de variable'" )) var_name = self.current_tok res.register_advancement() self.advance() if self.current_tok.type != TT_EQ: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "es o seigual'" )) res.register_advancement() self.advance() start_value = res.register(self.expr()) if res.error: return res if not self.current_tok.matches(TT_KEYWORD, "hasta"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "to'" )) res.register_advancement() self.advance() end_value = res.register(self.expr()) if res.error: return res if self.current_tok.matches(TT_KEYWORD, "de"): res.register_advancement() self.advance() step_value = res.register(self.expr()) if res.error: return res else: step_value = None if not self.current_tok.matches(TT_KEYWORD, "tonce"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "tonce'" )) res.register_advancement() self.advance() if self.current_tok.type == TT_NEWLINE: res.register_advancement() self.advance() body = res.register(self.statements()) if res.error: return res if not self.current_tok.matches(TT_KEYWORD, "hastaaca"): return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["languajeSyntaxError"] + "hastaaca'" )) res.register_advancement() self.advance() return res.success(ForNode(var_name, start_value, end_value, step_value, body, True)) body = res.register(self.statement()) if res.error: return res return res.success(ForNode(var_name, start_value, end_value, step_value, body, False))
def atom(self): res = ParseResult() tok = self.current_tok # Che, es un numerin? if tok.type in (TT_INT, TT_FLOAT): res.register_advancement() self.advance() return res.success(NumberNode(tok)) # Che, es un estrin? if tok.type == TT_STRING: res.register_advancement() self.advance() return res.success(StringNode(tok)) # Che, es una variable elif tok.type == TT_IDENTIFIER: res.register_advancement() self.advance() return res.success(VarAccessNode(tok)) # Che, es un parentesi? elif tok.type == TT_LPAREN: # si tiene un parentesi le da las prioridade res.register_advancement() self.advance() expr = res.register(self.expr()) if res.error: return res if self.current_tok.type == TT_RPAREN: res.register_advancement() self.advance() return res.success(expr) else: return res.failure(InvalidSyntaxError( self.current_tok.pos_start, self.current_tok.pos_end, detailsMessages["closeParentesisExpected"] )) # Che, es una lista? elif tok.type == TT_LSQUARE: list_expr = res.register(self.list_expr()) if res.error:return res return res.success(list_expr) # Che, es un ponele? elif tok.matches(TT_KEYWORD, "ponele"): if_expr = res.register(self.if_expr()) if res.error: return res return res.success(if_expr) # Che, es un for? elif tok.matches(TT_KEYWORD, "agarra"): for_expr = res.register(self.for_expr()) if res.error: return res return res.success(for_expr) # Che, es un while? elif tok.matches(TT_KEYWORD, "mientras"): while_expr = res.register(self.while_expr()) if res.error: return res return res.success(while_expr) # Che, es una funcion? elif tok.matches(TT_KEYWORD, "definime"): func_def = res.register(self.func_def()) if res.error: return res return res.success(func_def) # Che, es una niu lain? elif tok.type == TT_NEWLINE: self.advance() statement = res.register(self.statement()) if res.error: return res return res.success(statement) # Si llega acá hiciste macanas bro return res.failure(InvalidSyntaxError( tok.pos_start, tok.pos_end, detailsMessages["intOrFloatExpected"] ))
def make_tokens(self): tokens = [] # aca se fija que onda con lo que tiene while self.current_char != None: if self.current_char in " \t": self.advance() if self.current_char == "#": self.skip_comment() elif self.current_char in DIGITS + ".": tok, err = self.make_number() if err: return [], err tokens.append(tok) elif self.current_char == "(": tokens.append(Token(TT_LPAREN, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char == ")": tokens.append(Token(TT_RPAREN, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char in ";\n": tokens.append(Token(TT_NEWLINE, pos_start=self.pos)) self.advance() elif self.current_char == "[": tokens.append(Token(TT_LSQUARE, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char == "]": tokens.append(Token(TT_RSQUARE, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char == "%": tokens.append(Token(TT_MOD, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char == '"': tokens.append(self.make_string()) elif self.current_char == ",": tokens.append(Token(TT_COMMA, pos_start=self.pos, pos_end=self.pos)) self.advance() elif self.current_char == "=": pos_start = self.pos.copy() self.advance() if self.current_char == ">": tokens.append(Token(TT_ARROW, pos_start=pos_start, pos_end=self.pos)) self.advance() else: return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + ">'" ) elif self.current_char in LETTERS: op, err = self.make_operator() if err: return [], err for opTok in op: tokens.append(opTok) else: char = self.current_char if char != " ": pos_start = self.pos.copy() self.advance() return [], IllegalCharError(pos_start, self.pos, char) #pa los que no saben escribir else: self.advance() # end of file, lo que va al final vite tokens.append(Token(TT_EOF, pos_start=self.pos)) return tokens, None
def make_operator(self, next_str=None): op_str = "" pos_start = self.pos.copy() if next_str == None: while self.current_char != None and self.current_char in LETTERS: op_str += self.current_char self.advance() else: op_str = next_str # Aca diferencia las cosas, es un quilombo if op_str.lower() == "ma": return [Token(TT_PLUS, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "meno": return [Token(TT_MINUS, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "moduleame": return [Token(TT_MOD, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "por": return [Token(TT_MUL, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "dividido": return [Token(TT_DIV, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "ala": return [Token(TT_POW, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "anda": if self.take_str().lower() == "por": return [Token(TT_EE, pos_start=pos_start, pos_end=self.pos)] , None else: return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "por'" ) elif op_str.lower() == "seigual": return [Token(TT_EQ, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "son": return [Token(TT_EQ, pos_start=pos_start, pos_end=self.pos)] , None elif op_str.lower() == "no": tok, error = self.make_not_equals() if error: return [], error return tok, None elif op_str.lower() == "es": tok, error, next_str = self.make_equals() if error: return [], error if next_str != None: secToks, secErr = self.make_operator(next_str) if secErr: return [], secErr for secTok in secToks: tok.append(secTok) return tok, None else: tok_type = TT_KEYWORD if op_str.lower() in KEYWORDS else TT_IDENTIFIER # esto se fija las keywords que tienen mas de una palabra if op_str.lower() == "ponele": if self.take_str().lower() != "que": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "que'" ) elif op_str.lower() == "digamos": if self.take_str().lower() != "que": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "que'" ) elif op_str.lower() == "agarra": if self.take_str().lower() != "por": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "por'" ) elif op_str.lower() == "de": if self.take_str().lower() != "a": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "a'" ) elif op_str.lower() == "segui": if self.take_str().lower() != "de": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "segui de largo'" ) if self.take_str().lower() != "largo": return [], InvalidSyntaxError( pos_start, self.pos, detailsMessages["languajeSyntaxError"] + "segui de largo'" ) return [Token(tok_type, op_str, pos_start, self.pos)], None