defparseIf(tokens: List[Token]): (Expr, List[Token]) = val (condExpr, condCont) = parseExpr(tokens.drop(1)) if condCont.head != ThenToken then throwIllegalStateException("Expected `then` in if expression") else val (thenExpr, thenCont) = parseExpr(condCont.drop(1)) if thenCont.head != ElseToken then throwIllegalStateException("Expected `else` in if expression") else val (elseExpr, elseCont) = parseExpr(thenCont.drop(1)) (If(condExpr, thenExpr, elseExpr), elseCont)
defparseExprOfLevel(level: Int, tokens: List[Token]): (Expr, List[Token]) = val (factorExp, afterFactor) = if level < (binOps.size - 1) then parseExprOfLevel(level + 1, tokens) else parseTerm(tokens) if afterFactor.isEmpty then (factorExp, afterFactor) else val (subOpt, afterSub) = parseExprSubOfLevel(level, afterFactor) subOpt match caseSome(o, right) => o match case binary: ArithOp => (BinArith(binary, factorExp, right), afterSub) case logical: LogicalOp => (BinLogic(logical, factorExp, right), afterSub) caseNone => (factorExp, afterFactor)
defparseExprSubOfLevel(level: Int, tokens: List[Token]): (Option[(Op, Expr)], List[Token]) = if tokens.isEmpty then throwIllegalStateException("expect a complement of expr") else tokens.head match caseOperToken(o: Op) if binOps(level).contains(o) => val (factorExp, after) = if level < (binOps.size - 1) then parseExprOfLevel(level + 1, tokens.drop(1)) else parseTerm(tokens.drop(1)) if after.isEmpty then (Some(o, factorExp), after) else val (nextSubOpt, nextAfter) = parseExprSubOfLevel(level, after) nextSubOpt match caseSome(innerOp, rightExp) => innerOp match case binary: ArithOp => (Some(o, BinArith(binary, factorExp, rightExp)), nextAfter) case logical: LogicalOp => (Some(o, BinLogic(logical, factorExp, rightExp)), nextAfter) case _ => (Some(o, factorExp), after) case _ => (None, tokens)