#ifndef _PARSER_H
#define _PARSER_H

#include <list.h>

#define TOKEN_MAX    64
#define CMD_ARGS_MAX 64

#define TOKEN_CLASS_OPAREN    0
#define TOKEN_CLASS_CPAREN    1
#define TOKEN_CLASS_WORD      2
#define TOKEN_CLASS_SEMICOLON 3
#define TOKEN_CLASS_REDIR     4

struct token {
  struct list_node_link tokens_link;
  char buffer[TOKEN_MAX];
  int class;
};

#define PREC_NONE   0
#define PREC_LOWEST 1
#define PREC_SEQ    2
#define PREC_REDIR  3

#define AST_NODE_CLASS_CMD      0
#define AST_NODE_CLASS_SUBSHELL 1
#define AST_NODE_CLASS_SEQ      2
#define AST_NODE_CLASS_REDIR    3

struct ast_node;

struct ast_cmd {
  char* name;
  char* args[CMD_ARGS_MAX];
  int arg_count;
};

struct ast_subshell {
  struct ast_node* inner;
};

struct ast_seq {
  struct ast_node* left;
  struct ast_node* right;
};

struct ast_redir {
  struct ast_node* source;
  char* file_path;
};

struct ast_node {
  int class;
  union {
    struct ast_cmd cmd;
    struct ast_subshell subshell;
    struct ast_seq seq;
    struct ast_redir redir;
  } u;
};

struct parser;

typedef struct ast_node* (*nud_func_t) (struct parser* parser, struct token* token);
typedef struct ast_node* (*led_func_t) (struct parser* parser, struct token* token,
                                        struct ast_node* left);

struct parse_rule {
  nud_func_t nud;
  led_func_t led;
  int precedence;
};

struct parser {
  struct token* current;
  struct token* next;
};

struct ast_node* word_nud (struct parser* parser, struct token* token);

struct ast_node* oparen_nud (struct parser* parser, struct token* token);

struct ast_node* semicolon_led (struct parser* parser, struct token* token, struct ast_node* left);

struct ast_node* redir_led (struct parser* parser, struct token* token, struct ast_node* left);

void tokenize (struct list_node_link** tokens, const char* text);

void parse_and_execute (struct list_node_link* tokens);

#endif // _PARSER_H
