## Expression parsing is in its own module since ## this code is very messy and I don't want it to clutter up the main ## parser logic {.experimental: "codeReordering".} from parser import Parser, peek, prev, advance, match, consume from ../token import Token, TokenKind from ast import ASTNodeKind, ASTNode, printNode proc parseInt(parser: var Parser): ASTNode = let token = parser.peek if parser.match(tkInt): result = ASTNode(kind: ankInt, intVal: token.intVal) proc parseString(parser: var Parser): ASTNode = let token = parser.peek if parser.match(tkString): result = ASTNode(kind: ankString, stringVal: token.stringVal) proc parseLiteralExpr(parser: var Parser): ASTNode = if parser.match(tkInt): result = parser.parseInt() elif parser.match(tkString): result = parser.parseString() elif parser.match(tkLParen): # Parse a grouping let exp = parser.parseInt() discard parser.consume(tkRParen, "Expected ')' after an expression") result = ASTNode(kind: ankGroup, group: exp) proc parseUnary(parser: var Parser): ASTNode = ## Parse a unary expression ## unary = ("-" | "+") int ## | int var token = parser.peek() right: ASTNode if parser.match(tkMinus) or parser.match(tkPlus): # Unary expression right = parser.parseInt() result = ASTNode(kind: ankUnary, unaryOp: token, value: right) else: result = parser.parseLiteralExpr() proc parseFactor(parser: var Parser): ASTNode = ## Parse a factor ## factor = (unary ("*" | "/") unary)* var left: ASTNode right: ASTNode op: Token left = parser.parseUnary() while parser.match(tkStar) or parser.match(tkSlash): op = parser.prev() right = parser.parseUnary() left = ASTNode(kind: ankBinOp, left: left, binOp: op, right: right) return left proc parseTerm(parser: var Parser): ASTNode = ## Parse a term ## term = (factor ("+" | "-") factor)* var left: ASTNode right: ASTNode op: Token left = parser.parseFactor() while parser.match(tkPlus) or parser.match(tkMinus): op = parser.prev() right = parser.parseFactor() left = ASTNode(kind: ankBinOp, left: left, binOp: op, right: right) return left proc parseRelational*(parser: var Parser): ASTNode = ## Parse a relational/comparison expression ## All relational operators have the same precedence in Tsuki ## rel = term (("==" | "!=" | "<" | ">" | "<=" | ">=" )) term var left: ASTNode right: ASTNode op: Token left = parser.parseTerm() # TODO: clean this up? while parser.match(tkDoubleEqual) or parser.match(tkNotEqual) or parser.match(tkLess) or parser.match(tkGreater) or parser.match(tkLTEqual) or parser.match(tkGTEqual): op = parser.prev() discard parser.advance() right = parser.parseTerm() left = ASTNode(kind: ankBinOp, left: left, binOp: op, right: right) return left