#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#ifndef _SCANNER_H_
#define _SCANNER_H_

typedef enum {
  tag_plus, tag_minus, tag_mul, tag_div,
  tag_less, tag_less_eq, tag_equal, tag_greater, tag_greater_eq,
  tag_and, tag_or,
  tag_number, tag_name, tag_string, tag_symbol,
  tag_open_par, tag_close_par,
  tag_blockopen_par, tag_blockclose_par, 
  tag_semicolon, tag_comma, tag_dot,tag_method_sep,
  tag_return,
  tag_vector,tag_method_vector,tag_call,tag_closure_vector,
  tag_if,tag_then,tag_else,tag_endif,
  tag_pipe,tag_assign,
  tag_while,tag_end,tag_errorhandler,
  tag_eof
}t_tag;

struct t_token_def {
  t_tag tag;
  int index;
  int type;
  union {
    int number;
    char* name;
  } structure;
};

#define TYPE_PARAMETER 1
#define TYPE_VAR       2
#define TYPE_CONSTANT  3
#define TYPE_SPECIAL   4
#define TYPE_SLOT      5
#define TYPE_GLOBAL    6

#define TOKEN_TAG(TOK)    ((TOK)->tag)
#define TOKEN_INDEX(TOK)  ((TOK)->index)
#define TOKEN_TYPE(TOK)   ((TOK)->type)
#define TOKEN_NUMBER(TOK) ((TOK)->structure.number)
#define TOKEN_NAME(TOK)   ((TOK)->structure.name)

typedef struct t_token_def* t_token;


struct t_node_def {
  t_token token;
  union {
    int length;
    struct t_node_def *left;
  } first;
  union {
    struct t_node_def *right;
    struct t_node_def **vector;
  } second;
};

typedef struct t_node_def* t_node;

#define NODE_TAG(NOD)      (TOKEN_TAG((NOD)->token))
#define NODE_TOKEN(NOD)    ((NOD)->token)
#define NODE_LEFT(NOD)     ((NOD)->first.left)
#define NODE_RIGHT(NOD)    ((NOD)->second.right)
#define NODE_LENGTH(NOD)   ((NOD)->first.length)
#define NODE_VECTOR(NOD)   ((NOD)->second.vector)
#define NODE_ENTRY(NOD,N)  ((NODE_VECTOR(NOD))[N])
#define NODE_FILL(NOD)     (TOKEN_NUMBER(NODE_TOKEN(NOD)))
#define NODE_INDEX(NOD)    (TOKEN_INDEX(NODE_TOKEN(NOD)))
#define NODE_TYPE(NOD)     (TOKEN_TYPE(NODE_TOKEN(NOD)))
#define NODE_NUMBER(NOD)   (TOKEN_NUMBER(NODE_TOKEN(NOD)))
#define NODE_NAME(NOD)     (TOKEN_NAME(NODE_TOKEN(NOD)))

#define METHOD_NAME(NOD)         (NODE_ENTRY(NOD,0))
#define METHOD_PARAMETERS(NOD)   (NODE_ENTRY(NOD,1))
#define METHOD_VARS(NOD)         (NODE_ENTRY(NOD,2))
#define METHOD_STATEMENTS(NOD)   (NODE_ENTRY(NOD,3))
#define METHOD_CLASS(NOD)        (NODE_ENTRY(NOD,4))
#define METHOD_ERRORHANDLER(NOD) (NODE_ENTRY(NOD,5))

#define CLOSURE_VARS(NOD)       (NODE_ENTRY(NOD,0))
#define CLOSURE_STATEMENTS(NOD) (NODE_ENTRY(NOD,1))

#define CALL_NAME(NOD) (NODE_ENTRY(NOD,0))
#define CALL_ARGS(NOD) (NODE_ENTRY(NOD,1))

#define IF_TEST(NOD)   (NODE_ENTRY(NOD,0))
#define IF_THEN(NOD)   (NODE_ENTRY(NOD,1))
#define IF_ELSE(NOD)   (NODE_ENTRY(NOD,2))

#define WHILE_TEST(NOD)   (NODE_ENTRY(NOD,0))
#define WHILE_BODY(NOD)   (NODE_ENTRY(NOD,1))

#define DOT_RECEIVER(NOD) (NODE_LEFT(NOD))
#define DOT_CALL(NOD)     (NODE_RIGHT(NOD))

#define ASSIGN_LEFT(NOD)   (NODE_LEFT(NOD))
#define ASSIGN_RIGHT(NOD)  (NODE_RIGHT(NOD))

t_node read_file          (char* file);
void   print_node         (t_node node);

t_node new_vector_node(int length);
void   add(t_node liste,t_node ele);

t_node  pop                (t_node liste);
t_node  top                (t_node liste);
t_node  new_stack          (int length);
void    pop_n              (t_node liste, int n);
void    clear_stack        (t_node node);
void    push               (t_node liste,t_node ele);
void    push_liste         (t_node stack, t_node liste);
void    reverse_push_liste (t_node stack, t_node liste);
int     stack_elements     (t_node node);
t_node  stack_element_n    (t_node node, int i);

char* binary_as_string(t_token token);

void print_token(t_token token);
void print_tag(t_tag tag,t_token);
char* tag_as_string(t_tag tag);
t_node read_file(char* file);

void top_decorate(t_node );
void top_compile(t_node m_node);

#endif

/*eof*/
