from .structs import * from .exceptions import ParseError def parseExpression(token, prev, tokens): idx = 0 args = [] prev = token while tokens[idx].type_ != TokenType.CLOSE_PAREN: token = tokens[idx] if token.type_ == TokenType.EOF: raise ParseError("uneven parens: not enough closing!", token.line) inc = 1 if token.type_ == TokenType.OPEN_PAREN: expr, inc = parseExpression(token, prev, tokens[idx+1:]) args.append(expr) elif token.type_ in (TokenType.STRING, TokenType.TRUE, TokenType.FALSE, TokenType.INT, TokenType.FLOAT): expr, inc = parseLiteral(token, prev, tokens[idx+1:]) args.append(expr) elif token.type_ == TokenType.COLON: expr, inc = parseType(token, prev, tokens[idx+1:]) args.append(expr) else: expr, inc = parseSymbol(token, prev, tokens[idx+1:]) args.append(expr) idx += inc prev = token return Expr(args), idx + 2 # parens def parseSymbol(token, prev, tokens): return Symbol(token.text, token.line), 1 def parseLiteral(token, prev, tokens): if token.type_ == TokenType.STRING: return String(token.value), 1 elif token.type_ == TokenType.INT: return Int(token.value), 1 elif token.type_ == TokenType.FLOAT: return Float(token.value), 1 elif token.type_ in (TokenType.TRUE, TokenType.FALSE): return Bool(token.value), 1 else: return Literal(token.value), 1 def parseType(token, prev, tokens): # if the next token is a symbol, combine for a type if tokens[0].type_ == TokenType.SYMBOL: return Type(f":{tokens[0].text}"), 2 elif tokens[0].type_ == TokenType.OPEN_BRACKET: # only format currently supported: # [ ] if tokens[1].type_ != TokenType.COLON: raise ParseError("invalid type definition (expecting colon)", tokens[1].line) typ, counter = parseType(tokens[1], tokens[0], tokens[2:]) if tokens[1+counter].type_ != TokenType.CLOSE_BRACKET: raise ParseError("invalid type definition (expecting close bracket)", tokens[1+counter].line) return Type(f":[]", typ), counter + 3 else: raise ParseError("invalid type definition!", tokens[0].line) def parse(tokens): idx = 0 prev = None exprs = [] while tokens[idx].type_ != TokenType.EOF: token = tokens[idx] counter = 1 if token.type_ == TokenType.CLOSE_PAREN: raise ParseError("uneven parens: too many closing!", token.line) elif token.type_ == TokenType.OPEN_PAREN: expr, counter = parseExpression(token, prev, tokens[idx+1:]) exprs.append(expr) elif token.type_ in (TokenType.FALSE, TokenType.TRUE, TokenType.STRING, TokenType.INT, TokenType.FLOAT): lit, counter = parseLiteral(token, prev, tokens[idx+1:]) exprs.append(lit) elif token.type_ == TokenType.COLON: typ, counter = parseType(token, prev, tokens[idx+1:]) exprs.append(typ) else: sym, counter = parseSymbol(token, prev, tokens[idx+1:]) exprs.append(sym) idx += counter prev = token return exprs