#ifndef DEF_PARSER_H
#define DEF_PARSER_H

#include <vector>
#include <variant>
#include <stdexcept>
#include "tokenize.h"
using namespace std;

/**
 * Utilisé pour revenir en arrière quand quelque chose n'est pas reconnu
*/
class ParseException : public std::exception {
    const char* what() const noexcept override {
        return "Parse Exception";
    }
};

/**
 * Parse a list of tokens and return the associated AST
*/
Node parse(vector<Token> tokens);

/**
 * Parse something derivated from Prog
*/
ParseReturn parse_prog(vector<Token> tokens);

/**
 * Parse something derivated from Instruction
*/
ParseReturn parse_instruction(vector<Token> tokens);

/**
 * Parse something derivated from Statement
*/
ParseReturn parse_statement(vector<Token> tokens);

/**
 * Parse something derivated from ExprStatement
*/
ParseReturn parse_expr_statement(vector<Token> tokens);

/**
 * Parse something derivated from Expr
*/
ParseReturn parse_expr(vector<Token> tokens);

/**
 * Parse something derivated from Comp
*/
ParseReturn parse_comp(vector<Token> tokens);

/**
 * Parse something derivated from Sum
*/
ParseReturn parse_sum(vector<Token> tokens);

/**
 * Parse something derivated from Term
*/
ParseReturn parse_term(vector<Token> tokens);

/**
 * Parse something derivated from Unary
*/
ParseReturn parse_unary(vector<Token> tokens);

/**
 * Parse something derivated from Val
*/
ParseReturn parse_val(vector<Token> tokens);

/**
 * Parse something derivated from ParIdentifier
 * (An identifier with 0+ parentheses around it)
*/
ParseReturn parse_par_identifier(vector<Token> tokens);

/**
 * Prints a tree for debugging it
*/
void _debug_print_tree(const Node& node, int depth = 0, const string& prefix = "");

#endif