// Path: src/main/java/litil/Utils.java
// public class Utils {
//     public static String tab(int depth) {
//         return ntimes(depth, "\t");
//     }
// 
//     public static String ntimes(int count, String s) {
//         StringBuilder res = new StringBuilder("");
//         for (int i = 0; i < count; i++) {
//             res.append(s);
//         }
// 
//         return res.toString();
//     }
// 
//     public static PrintStream indenting(String pkg) {
//         return new PrintStream(System.out) {
//             @Override
//             public void println(String s) {
//                 super.println(s);
//             }
//         };
//     }
// }


import litil.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
    private static final List<String> BOOLS = Arrays.asList("true", "false");
    private static final List<String> KEYWORDS = Arrays.asList("let", "if", "then", "else", "and", "or", "not", "data", "match", "exception", "try", "catch", "throw");
    private int row = 1, col = 0;
    private String currentLine = null;
    private int lastIndentLength = 0;
    private boolean newLine = false;
    private Token eof = null;

    public BaseLexer(Reader reader) {
        this.reader = new BufferedReader(reader);
    }

    public Token pop() throws LexingException {
        if (eof != null) {
            return eof;
        }
        if (currentLine == null) {
            currentLine = readLine();
            if (currentLine == null) {
                eof = new Token(Token.Type.EOF, "$", row, col);
                return eof;
            } else {
                //compute the indent size
                consumeWhite();
                if (col == lastIndentLength) {
                    lastIndentLength = col;
                    return new Token(Token.Type.NEWLINE, "\\n1", row + 1, 1);
                } else if (col > lastIndentLength) {
                    lastIndentLength = col;
                    newLine = true;
// Path: src/main/java/litil/Utils.java
// public class Utils {
//     public static String tab(int depth) {
//         return ntimes(depth, "\t");
//     }
// 
//     public static String ntimes(int count, String s) {
//         StringBuilder res = new StringBuilder("");
//         for (int i = 0; i < count; i++) {
//             res.append(s);
//         }
// 
//         return res.toString();
//     }
// 
//     public static PrintStream indenting(String pkg) {
//         return new PrintStream(System.out) {
//             @Override
//             public void println(String s) {
//                 super.println(s);
//             }
//         };
//     }
// }


// Path: src/main/java/litil/lexer/BaseLexer.java
import litil.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

    private static final List<String> BOOLS = Arrays.asList("true", "false");
    private static final List<String> KEYWORDS = Arrays.asList("let", "if", "then", "else", "and", "or", "not", "data", "match", "exception", "try", "catch", "throw");
    private int row = 1, col = 0;
    private String currentLine = null;
    private int lastIndentLength = 0;
    private boolean newLine = false;
    private Token eof = null;

    public BaseLexer(Reader reader) {
        this.reader = new BufferedReader(reader);
    }

    public Token pop() throws LexingException {
        if (eof != null) {
            return eof;
        }
        if (currentLine == null) {
            currentLine = readLine();
            if (currentLine == null) {
                eof = new Token(Token.Type.EOF, "$", row, col);
                return eof;
            } else {
                //compute the indent size
                consumeWhite();
                if (col == lastIndentLength) {
                    lastIndentLength = col;
                    return new Token(Token.Type.NEWLINE, "\\n1", row + 1, 1);
                } else if (col > lastIndentLength) {
                    lastIndentLength = col;
                    newLine = true;
                    return new Token(Token.Type.INDENT, Utils.ntimes(col, " "), row, 1);