#ifndef _GRAMMAR_HH
#define _GRAMMAR_HH

#include <bitset>
#include <vector>
#include <list>
#include <set>

#include "const.hh"
#include "thesymbols.hh"
#include "sgraph.hh"


class Link
{
  Role role;
  FlagSet hflags;
  FlagSet dflags;
};


class Grammar
{

 public:

  //  enum CONSTR { SGL, OBL, LEFT, RIGHT, INIT, NONINIT, FIN, NONFIN };

  Grammar() : types_sz(0), cats_sz(0), flags_sz(0) {} ;
  
  int types_sz;
  int cats_sz;
  int flags_sz;

  vector< vector< Roles > >    connect;
  RoleSet                      sgl;
  vector< RoleSet >            obl;
  RoleSet                      left;
  RoleSet                      right;
  vector< RoleSet >            lt;
  vector< RoleSet >            gt;


  //  vector< vector< vector<
  vector< FlagSet >            set;
  vector< FlagSet >            pass;

  bool read(FILE* f);
  void write(FILE* f);

  void add_category(const char* s);
  void add_type(const char* s);
  void add_flag(const char* s);

  void set_sgl(Role r)           { sgl.set(r); }
  void set_obl(Cat c, Role r)    { obl[c].set(r); }
  void set_left(Role r)          { left.set(r); }
  void set_right(Role r)         { right.set(r); }
  void set_order(Role r, Role s) { lt[s].set(r); }
  void set_connect(Cat c, Cat d, Role r)   { connect[c][d].insert(r); }
  void set_lt(Role r, Role s);
  void compute_gt();


  bool check_constr(NodeProp& hprop, NodeProp& dprop, int dir, Role role);

};

inline bool Grammar::check_constr(NodeProp& hprop, NodeProp& dprop, int dir, Role role)
{
  return 
    !hprop.forbidden[role] &&
    ( !right[role] || dir==1 ) &&
    ( !left[role] || dir==0 )
    ;
}


#endif
