def get_number(self): result = self.character self.advance() while self.character != None and self.character.isdigit(): result += self.character self.advance() if self.character == '.': result += '.' self.advance() if self.character == None or not self.character.isdigit(): self.gen_position() error.highlight(self.position) print("Error: expected digit after the dot") exit() while self.character != None and self.character.isdigit(): result += self.character self.advance() return result
def parse_stmts(self): if self.token.type != TokenType.LEFT_ROUND_BRACKET: return self.parse_stmt() result = StmtsNode([self.advance()], []) self.skip_newlines() if self.token.type != TokenType.RIGHT_ROUND_BRACKET: result.nodes.append(self.parse_stmt()) while self.token.type == TokenType.NEWLINE: self.skip_newlines() if self.token.type == TokenType.RIGHT_ROUND_BRACKET: break result.nodes.append(self.parse_stmt()) if self.token.type != TokenType.RIGHT_ROUND_BRACKET: error.highlight(self.token.position) print( "Error: expected a `)` or a newline while parsing statements") exit() result.tokens.append(self.advance()) return result
def parse_array(self): if self.token.type != TokenType.LEFT_SQUARE_BRACKET: error.highlight(self.token.position) print("Error: expected a `[` while parsing an array") exit() result = ArrayNode([self.advance()], []) self.skip_newlines() if self.token.type != TokenType.RIGHT_SQUARE_BRACKET: result.nodes.append(self.parse_expr()) while self.token.type in [TokenType.COMMA, TokenType.NEWLINE]: self.advance() self.skip_newlines() if self.token.type == TokenType.RIGHT_SQUARE_BRACKET: break result.nodes.append(self.parse_expr()) if self.token.type != TokenType.RIGHT_SQUARE_BRACKET: error.highlight(self.token.position) print("Error: expected a `]` while parsing an array") exit() result.nodes.append(self.advance()) return result
def parse_type_struct(self): if self.token.type != TokenType.LEFT_CURLY_BRACKET: error.highlight(self.token.position) print("Error: expected a `{` while parsing struct type") exit() result = StructTypeNode([self.advance()], []) self.skip_newlines() if self.token.type != TokenType.RIGHT_CURLY_BRACKET: result.fields.append(self.parse_anon_field()) while self.token.type in [TokenType.COMMA, TokenType.NEWLINE]: self.advance() self.skip_newlines() if self.token.type == TokenType.RIGHT_CURLY_BRACKET: break result.fields.append(self.parse_anon_field()) if self.token.type != TokenType.RIGHT_CURLY_BRACKET: error.highlight(self.token.position) print("Error: expected a `}` while parsing struct type") exit() result.tokens.append(self.advance()) return result
def parse_oper1(self): result = self.parse_oper0() while self.token.type in [ TokenType.ASTERISK, TokenType.SLASH, TokenType.PERCENT, TokenType.SHIFT_LEFT, TokenType.SHIFT_RIGHT ]: if self.token.type == TokenType.ASTERISK: result = MulNode([self.advance()], [result, self.parse_oper0()]) elif self.token.type == TokenType.SLASH: result = DivNode([self.advance()], [result, self.parse_oper0()]) elif self.token.type == TokenType.PERCENT: result = ModNode([self.advance()], [result, self.parse_oper0()]) elif self.token.type == TokenType.SHIFT_LEFT: result = ShlNode([self.advance()], [result, self.parse_oper0()]) elif self.token.type == TokenType.SHIFT_RIGHT: result = ShrNode([self.advance()], [result, self.parse_oper0()]) else: error.highlight(self.token.position) print("Error: internal error") exit() return result
def parse_while(self): if self.token.type != TokenType.WHILE: error.highlight(self.token.position) print("Error: expected a `while` while parsing an while statement") exit() return WhileNode( [self.advance()], [self.parse_expr(), self.parse_stmts()])
def parse_type_array(self): if self.token.type != TokenType.LEFT_SQUARE_BRACKET: error.highlight(self.token.position) print("Error: expected a `[` while parsing array type") exit() result = ArrayTypeNode([self.advance()], self.parse_type()) if self.token.type != TokenType.RIGHT_SQUARE_BRACKET: error.highlight(self.token.position) print("Error: expected a `]` while parsing array type") exit() result.tokens.append(self.advance()) return result
def parse_oper2(self): result = self.parse_oper1() while self.token.type in [TokenType.PLUS, TokenType.MINUS]: if self.token.type == TokenType.PLUS: result = AddNode([self.advance()], [result, self.parse_oper1()]) elif self.token.type == TokenType.MINUS: result = SubNode([self.advance()], [result, self.parse_oper1()]) else: error.highlight(self.token.position) print("Error: internal error") exit() return result
def parse_if(self): if self.token.type != TokenType.IF: error.highlight(self.token.position) print("Error: expected a `if` while parsing an if statement") exit() result = IfNode( [self.advance()], [self.parse_expr(), self.parse_stmts()]) if self.token.type != TokenType.ELSE: return result result.tokens.append(self.advance()) result.nodes.append(self.parse_stmts()) return result
def parse_prgrm(self): result = PrgrmNode([], []) self.skip_newlines() if self.token.type != TokenType.EOF: result.nodes.append(self.parse_stmt()) while self.token.type == TokenType.NEWLINE: self.skip_newlines() if self.token.type == TokenType.EOF: break result.nodes.append(self.parse_stmt()) if self.token.type != TokenType.EOF: error.highlight(self.token.position) print("Error: expected EOF while parsing program") exit() return result
def parse_oper3(self): result = self.parse_oper2() while self.token.type in [ TokenType.BITWISE_OR, TokenType.BITWISE_AND, TokenType.BITWISE_XOR ]: if self.token.type == TokenType.BITWISE_OR: result = BitOrNode([self.advance()], [result, self.parse_oper2()]) elif self.token.type == TokenType.BITWISE_AND: result = BitAndNode([self.advance()], [result, self.parse_oper2()]) elif self.token.type == TokenType.BITWISE_XOR: result = BitXorNode([self.advance()], [result, self.parse_oper2()]) else: error.highlight(self.token.position) print("Error: internal error") exit() return result
def parse_factor(self): if self.token.type == TokenType.NUMBER: result = NumNode([self.advance()]) elif self.token.type == TokenType.IDENTIFIER: result = IdenNode([self.advance()]) elif self.token.type == TokenType.LEFT_SQUARE_BRACKET: result = self.parse_array() elif self.token.type == TokenType.LEFT_CURLY_BRACKET: result = self.parse_struct() elif self.token.type == TokenType.LEFT_ROUND_BRACKET: result = self.parse_stmts() elif self.token.type in [ TokenType.VAR, TokenType.CON, TokenType.IF, TokenType.WHILE ]: result = self.parse_stmt() else: error.highlight(self.token.position) print("Error: expected a number or identifier") exit() # call or index while self.token.type in [ TokenType.LEFT_SQUARE_BRACKET, TokenType.LEFT_CURLY_BRACKET ]: if self.token.type == TokenType.LEFT_SQUARE_BRACKET: result = IndexNode([self.advance()], [result]) result.nodes.append(self.parse_expr()) if self.token.type != TokenType.RIGHT_SQUARE_BRACKET: error.highlight(self.token.position) print("Error: expected `]` while parsing index") exit() result.tokens.append(self.advance()) elif self.token.type == TokenType.LEFT_CURLY_BRACKET: result = CallNode([], [result, self.parse_struct()]) return result
def parse_decl_func(self): if self.token.type != TokenType.FUNC: error.highlight(self.token.position) print("Error: expected a `func` while parsing a func decleration") exit() result = DeclFuncNode([self.advance()], [None, None, None]) if self.token.type != TokenType.IDENTIFIER: error.highlight(self.token.position) print( "Error: expected an identifier while parsing a func decleration" ) exit() result.tokens.append(self.advance()) if self.token.type in [ TokenType.TYPE_IDENTIFIER, TokenType.LEFT_CURLY_BRACKET ]: result.nodes[0] = self.parse_type() if self.token.type == TokenType.TO: result.tokens.append(self.advance()) if not self.token.type in [ TokenType.TYPE_IDENTIFIER, TokenType.LEFT_CURLY_BRACKET ]: error.highlight(self.token.position) print( "Error: expected a type while parsing a func decleration") exit() result.nodes[1] = self.parse_type() result.nodes[2] = self.parse_stmts() return result
def parse_con(self): if self.token.type != TokenType.CON: error.highlight(self.token.position) print("Error: expected a `con` while parsing a con statemnt") exit() result = ConNode([self.advance()], []) if self.token.type != TokenType.IDENTIFIER: error.highlight(self.token.position) print("Error: expected an identifier while parsing a con statemnt") exit() result.tokens.append(self.advance()) if self.token.type != TokenType.SET: error.highlight(self.token.position) print("Error: expected a `=` while parsing a con statemnt") exit() result.tokens.append(self.advance()) result.nodes.append(self.parse_expr()) return result
def get_token(self): if self.character == None: return self.gen_token('', TokenType.EOF) while self.character in [' ', '\t']: self.advance() if self.character == '#': while self.character != '\n': self.advance() self.position = Position(self.source, self.pos, None, self.col, None, self.line, None) if self.character.isdigit(): return self.gen_token(self.get_number(), TokenType.NUMBER) if self.character.isalpha() and self.character.islower(): identifier = self.get_identifier() return self.gen_token( identifier, { "func": TokenType.FUNC, "struct": TokenType.STRUCT, "enum": TokenType.ENUM, "con": TokenType.CON, "var": TokenType.VAR, "if": TokenType.IF, "else": TokenType.ELSE, "while": TokenType.WHILE, # types "u8": TokenType.TYPE_IDENTIFIER, "u16": TokenType.TYPE_IDENTIFIER, "u32": TokenType.TYPE_IDENTIFIER, "u64": TokenType.TYPE_IDENTIFIER, "i8": TokenType.TYPE_IDENTIFIER, "i16": TokenType.TYPE_IDENTIFIER, "i32": TokenType.TYPE_IDENTIFIER, "i64": TokenType.TYPE_IDENTIFIER, "f16": TokenType.TYPE_IDENTIFIER, "f32": TokenType.TYPE_IDENTIFIER, "f64": TokenType.TYPE_IDENTIFIER, "f80": TokenType.TYPE_IDENTIFIER, "uint": TokenType.TYPE_IDENTIFIER, "int": TokenType.TYPE_IDENTIFIER }.get(identifier, TokenType.IDENTIFIER)) if self.character.isalpha() and self.character.isupper(): return self.gen_token(self.get_identifier(), TokenType.TYPE_IDENTIFIER) if self.character == '+': self.advance() if self.character == '=': self.advance() return self.gen_token('+=', TokenType.SET_PLUS) return self.gen_token('+', TokenType.PLUS) if self.character == '-': self.advance() if self.character == '=': self.advance() return self.gen_token('-=', TokenType.SET_MINUS) if self.character == '>': self.advance() return self.gen_token('->', TokenType.TO) return self.gen_token('-', TokenType.MINUS) if self.character == '*': self.advance() if self.character == '=': self.advance() return self.gen_token('*=', TokenType.SET_ASTERISK) return self.gen_token('*', TokenType.ASTERISK) if self.character == '/': self.advance() if self.character == '=': self.advance() return self.gen_token('/=', TokenType.SET_SLASH) return self.gen_token('/', TokenType.SLASH) if self.character == '%': self.advance() if self.character == '=': self.advance() return self.gen_token('%=', TokenType.SET_PERCENT) return self.gen_token('%', TokenType.PERCENT) if self.character == '|': self.advance() if self.character == '=': self.advance() return self.gen_token('|=', TokenType.SET_BITWISE_OR) if self.character == '|': self.advance() return self.gen_token('||', TokenType.OR) return self.gen_token('|', TokenType.BITWISE_OR) if self.character == '&': self.advance() if self.character == '=': self.advance() return self.gen_token('&=', TokenType.SET_BITWISE_AND) if self.character == '&': self.advance() return self.gen_token('&&', TokenType.AND) return self.gen_token('&', TokenType.BITWISE_AND) if self.character == '^': self.advance() if self.character == '=': self.advance() return self.gen_token('^=', TokenType.SET_BITWISE_XOR) return self.gen_token('^', TokenType.BITWISE_XOR) if self.character == '=': self.advance() if self.character == '=': self.advance() return self.gen_token('==', TokenType.EQUAL) return self.gen_token('=', TokenType.SET) if self.character == '!': self.advance() if self.character == '=': self.advance() return self.gen_token('!=', TokenType.NOT_EQUAL) return self.gen_token('!', TokenType.NOT) if self.character == '<': self.advance() if self.character == '<': self.advance() if self.character == '=': self.advance() return self.gen_token('<<=', TokenType.SET_SHIFT_LEFT) return self.gen_token('<<', TokenType.SHIFT_LEFT) if self.character == '=': self.advance() return self.gen_token('<=', TokenType.LESS_THAN_OR_EQUAL) return self.gen_token('<', TokenType.LESS_THAN) if self.character == '>': self.advance() if self.character == '>': self.advance() if self.character == '=': self.advance() return self.gen_token('>>=', TokenType.SET_SHIFT_RIGHT) return self.gen_token('>>', TokenType.SHIFT_RIGHT) if self.character == '=': self.advance() return self.gen_token('>=', TokenType.GREATER_THAN_OR_EQUAL) return self.gen_token('>', TokenType.GREATER_THAN) if self.character == '(': self.advance() return self.gen_token('(', TokenType.LEFT_ROUND_BRACKET) if self.character == ')': self.advance() return self.gen_token(')', TokenType.RIGHT_ROUND_BRACKET) if self.character == '[': self.advance() return self.gen_token('[', TokenType.LEFT_SQUARE_BRACKET) if self.character == ']': self.advance() return self.gen_token(']', TokenType.RIGHT_SQUARE_BRACKET) if self.character == '{': self.advance() return self.gen_token('{', TokenType.LEFT_CURLY_BRACKET) if self.character == '}': self.advance() return self.gen_token('}', TokenType.RIGHT_CURLY_BRACKET) if self.character == ',': self.advance() return self.gen_token(',', TokenType.COMMA) if self.character == '.': self.advance() return self.gen_token('.', TokenType.DOT) if self.character == ':': self.advance() return self.gen_token(':', TokenType.COMMA) if self.character == '\n': self.advance() return self.gen_token('', TokenType.NEWLINE) self.position.pos_end = self.pos self.position.col_end = self.col self.position.line_end = self.line error.highlight(self.position) print("Error: invalid character") exit()