#ifndef __NLSYS_SYNTAX_H_INCLUDED__
#define __NLSYS_SYNTAX_H_INCLUDED__

typedef struct _syntax *syntax_t;
typedef struct _syntax_label *syntax_label_t;
typedef struct _syntax_block *syntax_block_t;
typedef struct _syntax_ifgoto *syntax_ifgoto_t;
typedef struct _syntax_ifngoto *syntax_ifngoto_t;
typedef struct _syntax_if *syntax_if_t;
typedef struct _syntax_for *syntax_for_t;
typedef struct _syntax_while *syntax_while_t;
typedef struct _syntax_do *syntax_do_t;
typedef struct _syntax_switch *syntax_switch_t;
typedef struct _syntax_goto *syntax_goto_t;
typedef struct _syntax_break *syntax_break_t;
typedef struct _syntax_continue *syntax_continue_t;
typedef struct _syntax_return *syntax_return_t;

#include "type.h"
#include "objlist.h"
#include "defines.h"
#include "symbol.h"
#include "model.h"
#include "struct.h"
#include "union.h"
#include "enum.h"
#include "typedef.h"
#include "value.h"
#include "area.h"

struct _syntax_block {
  defines_t defines;
  objlist_t symbols;
  objlist_t syntaxes;
};

struct _syntax_label {
  c_type_t type; /* LABEL, CASE, DEFAULT */
  char *name;
  int id;
  union {
    struct {
      char *string;
    } label;
    struct {
      long number;
      symbol_t symbol;
    } _case;
  } obj;
};

struct _syntax_ifgoto {
  symbol_t cond;
  syntax_t label;
};

struct _syntax_ifngoto {
  symbol_t cond;
  syntax_t label;
};

struct _syntax_if {
  symbol_t cond;
  syntax_t true;
  syntax_t false;
  struct {
    syntax_t true;
    syntax_t false;
    syntax_t end;
  } label;
};

struct _syntax_for {
  symbol_t init;
  symbol_t cond;
  symbol_t next;
  syntax_t loop;
  struct {
    syntax_t start;
    syntax_t loop;
    syntax_t next;
    syntax_t end;
  } label;
};

struct _syntax_while {
  symbol_t cond;
  syntax_t loop;
  struct {
    syntax_t start;
    syntax_t loop;
    syntax_t end;
  } label;
};

struct _syntax_do {
  syntax_t loop;
  symbol_t cond;
  struct {
    syntax_t start;
    syntax_t next;
    syntax_t end;
  } label;
};

struct _syntax_switch {
  symbol_t value;
  objlist_t conds;
  syntax_t block;
  struct {
    syntax_t end;
  } label;
};

struct _syntax_goto {
  char *string;
  syntax_t label;
};

struct _syntax_break {
  syntax_t label;
};

struct _syntax_continue {
  syntax_t label;
};

struct _syntax_return {
  symbol_t value;
  symbol_t function;
};

struct _syntax {
  struct objentry entry;
  c_type_t type;
  int line;
  union {
    void *p;
    char *word;
    objlist_t words;
    model_t model;
    symbol_t symbol;
    union {
      void *p;
      struct_t _struct;
      union_t _union;
      enum_t _enum;
      typedef_t _typedef;
    } custom;
    struct _syntax_label label;
    struct _syntax_block block;
    struct _syntax_ifgoto ifgoto;
    struct _syntax_ifngoto ifngoto;
    struct _syntax_if _if;
    struct _syntax_for _for;
    struct _syntax_while _while;
    struct _syntax_do _do;
    struct _syntax_switch _switch;
    struct _syntax_goto _goto;
    struct _syntax_break _break;
    struct _syntax_continue _continue;
    struct _syntax_return _return;
  } obj;
};

/*****************************************************************
 * syntax_t
 */

syntax_t syntax_destroy(syntax_t syntax);
syntax_t syntax_create(c_type_t type, int line, int val, void *obj);

syntax_t syntax_create_label(syntax_t syntax, char *name, int line,
			     c_type_t type, long number, char *string);

syntax_t objentry_get_syntax(objentry_t entry);
syntax_t objlist_extract_syntax(objlist_t list, syntax_t syntax);
syntax_t objlist_extract_syntax_next(objlist_t list, syntax_t from);
syntax_t objlist_extract_syntax_prev(objlist_t list, syntax_t from);
syntax_t objlist_extract_syntax_head(objlist_t list);
syntax_t objlist_extract_syntax_tail(objlist_t list);

syntax_t syntax_insert_tail(objlist_t list, c_type_t type, int line,
			    model_t model, long val, void *obj);

void syntax_print_label(syntax_label_t label, int indent);
void syntax_print_block(syntax_block_t block, int indent);
void syntax_print_ifgoto(syntax_ifgoto_t ifgoto, int indent);
void syntax_print_ifngoto(syntax_ifngoto_t ifngoto, int indent);
void syntax_print_if(syntax_if_t _if, int indent);
void syntax_print_for(syntax_for_t _for, int indent);
void syntax_print_while(syntax_while_t _while, int indent);
void syntax_print_do(syntax_do_t _do, int indent);
void syntax_print_return(syntax_return_t _return, int indent);
void syntax_print(syntax_t syntax, int indent);

/*****************************************************************
 * library
 */

int syntax_init_builtin(objlist_t defines_list, objlist_t symbols,
			area_t static_area);
objlist_t syntax_read_structure(objlist_t syntax_list, symbol_t function,
				objlist_t syntaxes, objlist_t defines_list,
				objlist_t symbols, objlist_t labels,
				area_t static_area, area_t stack_area);
objlist_t syntax_list_read_structure(objlist_t syntax_list, symbol_t function,
				     objlist_t syntaxes, objlist_t defines_list,
				     objlist_t symbols, objlist_t labels,
				     area_t static_area, area_t stack_area);
int syntax_list_read_control(syntax_block_t block);
int syntax_custom_normalize(syntax_t syntax, objlist_t syntax_list, objlist_t defines_list);

#endif
