// Path: app/src/main/java/com/annimon/hotarufx/exceptions/ParseException.java
// public class ParseException extends RuntimeException {
// 
//     public ParseException() {
//         super();
//     }
// 
//     public ParseException(String string) {
//         super(string);
//     }
// 
//     public ParseException(String string, SourcePosition pos) {
//         super(string + " at " + pos.toString());
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java
// public enum HotaruTokenId {
// 
//     NUMBER(Category.NUMBER),
//     WORD(Category.IDENTIFIER),
//     TEXT(Category.STRING),
// 
//     TRUE(Category.KEYWORD),
//     FALSE(Category.KEYWORD),
//     MS(Category.KEYWORD),
//     SEC(Category.KEYWORD),
// 
//     EQ(Category.OPERATOR),
//     PLUS(Category.OPERATOR),
//     MINUS(Category.OPERATOR),
//     LPAREN(Category.OPERATOR),
//     RPAREN(Category.OPERATOR),
//     LBRACE(Category.OPERATOR),
//     RBRACE(Category.OPERATOR),
//     LBRACKET(Category.OPERATOR),
//     RBRACKET(Category.OPERATOR),
//     COLON(Category.OPERATOR),
//     COMMA(Category.OPERATOR),
//     DOT(Category.OPERATOR),
//     AT(Category.OPERATOR),
// 
//     SINGLE_LINE_COMMENT(Category.COMMENT),
//     MULTI_LINE_COMMENT(Category.COMMENT),
// 
//     WS(Category.WHITESPACE),
//     EOF(Category.WHITESPACE);
// 
//     private enum Category {
//         NUMBER, IDENTIFIER, STRING, KEYWORD, OPERATOR, COMMENT, WHITESPACE
//     }
// 
//     private final Category category;
// 
//     HotaruTokenId(Category category) {
//         this.category = category;
//     }
// 
//     public String getPrimaryCategory() {
//         return category.name().toLowerCase();
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/SourcePosition.java
// public class SourcePosition {
// 
//     private final int position;
//     private final int row;
//     private final int column;
// 
//     public SourcePosition(int position, int row, int column) {
//         this.position = position;
//         this.row = row;
//         this.column = column;
//     }
// 
//     public int getPosition() {
//         return position;
//     }
// 
//     public int getRow() {
//         return row;
//     }
// 
//     public int getColumn() {
//         return column;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         SourcePosition that = (SourcePosition) o;
//         return position == that.position &&
//                 row == that.row &&
//                 column == that.column;
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(position, row, column);
//     }
// 
//     @Override
//     public String toString() {
//         return "[" + row + ", " + column + "]";
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/Token.java
// public class Token {
// 
//     private final HotaruTokenId type;
//     private final String text;
//     private final int length;
//     private final SourcePosition position;
// 
//     public Token(HotaruTokenId type, String text, int length, SourcePosition position) {
//         this.type = type;
//         this.text = text;
//         this.length = length;
//         this.position = position;
//     }
// 
//     public HotaruTokenId getType() {
//         return type;
//     }
// 
//     public String getText() {
//         return text;
//     }
// 
//     public int getLength() {
//         return length;
//     }
// 
//     public SourcePosition getPosition() {
//         return position;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         Token token = (Token) o;
//         return length == token.length &&
//                 type == token.type &&
//                 Objects.equals(text, token.text) &&
//                 Objects.equals(position, token.position);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(type, text, length, position);
//     }
// 
//     @Override
//     public String toString() {
//         return type.name() + " " + position + " " + text;
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/parser/ast/BlockNode.java
// public class BlockNode extends ASTNode {
// 
//     public final List<Node> statements = new ArrayList<>();
// 
//     public void add(Node node) {
//         statements.add(node);
//     }
// 
//     @Override
//     public <R, T> R accept(ResultVisitor<R, T> visitor, T t) {
//         return visitor.visit(this, t);
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/parser/ast/Node.java
// public interface Node {
// 
//     <R, T> R accept(ResultVisitor<R, T> visitor, T input);
// }


import com.annimon.hotarufx.exceptions.ParseException;
import com.annimon.hotarufx.lexer.HotaruTokenId;
import com.annimon.hotarufx.lexer.SourcePosition;
import com.annimon.hotarufx.lexer.Token;
import com.annimon.hotarufx.parser.ast.BlockNode;
import com.annimon.hotarufx.parser.ast.Node;
import java.util.List;
package com.annimon.hotarufx.parser;


public abstract class Parser {

    private static final Token EOF = new Token(HotaruTokenId.EOF, "",
            0, new SourcePosition(-1, -1, -1));

    private final List<Token> tokens;
    private final int size;
    private final ParseErrors parseErrors;
// Path: app/src/main/java/com/annimon/hotarufx/exceptions/ParseException.java
// public class ParseException extends RuntimeException {
// 
//     public ParseException() {
//         super();
//     }
// 
//     public ParseException(String string) {
//         super(string);
//     }
// 
//     public ParseException(String string, SourcePosition pos) {
//         super(string + " at " + pos.toString());
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/HotaruTokenId.java
// public enum HotaruTokenId {
// 
//     NUMBER(Category.NUMBER),
//     WORD(Category.IDENTIFIER),
//     TEXT(Category.STRING),
// 
//     TRUE(Category.KEYWORD),
//     FALSE(Category.KEYWORD),
//     MS(Category.KEYWORD),
//     SEC(Category.KEYWORD),
// 
//     EQ(Category.OPERATOR),
//     PLUS(Category.OPERATOR),
//     MINUS(Category.OPERATOR),
//     LPAREN(Category.OPERATOR),
//     RPAREN(Category.OPERATOR),
//     LBRACE(Category.OPERATOR),
//     RBRACE(Category.OPERATOR),
//     LBRACKET(Category.OPERATOR),
//     RBRACKET(Category.OPERATOR),
//     COLON(Category.OPERATOR),
//     COMMA(Category.OPERATOR),
//     DOT(Category.OPERATOR),
//     AT(Category.OPERATOR),
// 
//     SINGLE_LINE_COMMENT(Category.COMMENT),
//     MULTI_LINE_COMMENT(Category.COMMENT),
// 
//     WS(Category.WHITESPACE),
//     EOF(Category.WHITESPACE);
// 
//     private enum Category {
//         NUMBER, IDENTIFIER, STRING, KEYWORD, OPERATOR, COMMENT, WHITESPACE
//     }
// 
//     private final Category category;
// 
//     HotaruTokenId(Category category) {
//         this.category = category;
//     }
// 
//     public String getPrimaryCategory() {
//         return category.name().toLowerCase();
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/SourcePosition.java
// public class SourcePosition {
// 
//     private final int position;
//     private final int row;
//     private final int column;
// 
//     public SourcePosition(int position, int row, int column) {
//         this.position = position;
//         this.row = row;
//         this.column = column;
//     }
// 
//     public int getPosition() {
//         return position;
//     }
// 
//     public int getRow() {
//         return row;
//     }
// 
//     public int getColumn() {
//         return column;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         SourcePosition that = (SourcePosition) o;
//         return position == that.position &&
//                 row == that.row &&
//                 column == that.column;
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(position, row, column);
//     }
// 
//     @Override
//     public String toString() {
//         return "[" + row + ", " + column + "]";
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/lexer/Token.java
// public class Token {
// 
//     private final HotaruTokenId type;
//     private final String text;
//     private final int length;
//     private final SourcePosition position;
// 
//     public Token(HotaruTokenId type, String text, int length, SourcePosition position) {
//         this.type = type;
//         this.text = text;
//         this.length = length;
//         this.position = position;
//     }
// 
//     public HotaruTokenId getType() {
//         return type;
//     }
// 
//     public String getText() {
//         return text;
//     }
// 
//     public int getLength() {
//         return length;
//     }
// 
//     public SourcePosition getPosition() {
//         return position;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
//         Token token = (Token) o;
//         return length == token.length &&
//                 type == token.type &&
//                 Objects.equals(text, token.text) &&
//                 Objects.equals(position, token.position);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(type, text, length, position);
//     }
// 
//     @Override
//     public String toString() {
//         return type.name() + " " + position + " " + text;
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/parser/ast/BlockNode.java
// public class BlockNode extends ASTNode {
// 
//     public final List<Node> statements = new ArrayList<>();
// 
//     public void add(Node node) {
//         statements.add(node);
//     }
// 
//     @Override
//     public <R, T> R accept(ResultVisitor<R, T> visitor, T t) {
//         return visitor.visit(this, t);
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/parser/ast/Node.java
// public interface Node {
// 
//     <R, T> R accept(ResultVisitor<R, T> visitor, T input);
// }


// Path: app/src/main/java/com/annimon/hotarufx/parser/Parser.java
import com.annimon.hotarufx.exceptions.ParseException;
import com.annimon.hotarufx.lexer.HotaruTokenId;
import com.annimon.hotarufx.lexer.SourcePosition;
import com.annimon.hotarufx.lexer.Token;
import com.annimon.hotarufx.parser.ast.BlockNode;
import com.annimon.hotarufx.parser.ast.Node;
import java.util.List;

package com.annimon.hotarufx.parser;


public abstract class Parser {

    private static final Token EOF = new Token(HotaruTokenId.EOF, "",
            0, new SourcePosition(-1, -1, -1));

    private final List<Token> tokens;
    private final int size;
    private final ParseErrors parseErrors;
    private Node parsedNode;