Index: src/dgp/grammar.cc
===================================================================
--- src/dgp/grammar.cc	(revision 5f4d9c3b32eea7b6643a751aa75bdb05b7d41576)
+++ src/dgp/grammar.cc	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
@@ -1,37 +1,61 @@
 
-#include <stdio.h>
+#include <cstdio>
 
 #include "grammar.hh"
 
-bool (*constraint[MAXCONSTRS])(int head, int dep);
-
-
-int chk_type(const char* s, int lineno) // SIDE EFECTS!
-{
-  if(Role::index(s)>0) return 1;
-
-  fprintf(stderr,"%8d: Invalid type '%s'. Line ignored.\n",lineno,s);
-  return 0;
-}
-
-int chk_cat(const char* s, int lineno)
-{
-  if(Cat::index(s)>0) return 1;
-
-  fprintf(stderr,"%8d: Invalid category '%s'. Line ignored.\n",lineno,s);
-  return 0;
-}
+//bool (*constraint[MAXCONSTRS])(int head, int dep);
+
+//====================================================================================================
+//inline !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+bool chk_type(const char* s) { return Role::index(s)>0; } // PRZENIEŠÆ DO Role
+//----------------------------------------------------------------------------------------------------
+//inline !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+bool chk_long(const char* s) { return LongRel::index(s)>0; } // jw
+//----------------------------------------------------------------------------------------------------
+//inline !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+bool chk_cat(const char* s) { return Cat::index(s)>0; } //jw
+//----------------------------------------------------------------------------------------------------
+//inline !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+bool chk_flag(const char* s) { return Flag::index(s)>0; } //jw
+//====================================================================================================
+
+void grammar_error(int lineno, string s="Grammar error.")
+{
+  fprintf(stderr,"%8d: %s Line ignored.\n",lineno,s.c_str());
+}
+
+//====================================================================================================
 
 void Grammar::add_category(const char* s)
 {
   Cat::add(s);
-  if(Cat::count()>cats_sz)
+
+  if(connect.size() <= Cat::count())
   {
-    cats_sz += 16;
-    connect.resize(cats_sz);
-    for(int i=0; i<cats_sz; ++i)
-      connect[i].resize(cats_sz);
-    obl.resize(cats_sz);
+    connect.resize(Cat::count()+RESIZE_DELTA);
+    for(int i=0; i<connect.size(); ++i)
+      if(connect[i].size() <= Cat::count()) connect[i].resize(Cat::count()+RESIZE_DELTA);
   }
+  if(connect1.size() <= Cat::count())
+  {
+    connect1.resize(Cat::count()+RESIZE_DELTA);
+    for(int i=0; i<=connect1.size(); ++i)
+      if(connect1[i].size() <= Cat::count()) connect1[i].resize(Cat::count()+RESIZE_DELTA);
+  }
+
+  if(longrel.size() <= Cat::count())
+  {
+    longrel.resize(Cat::count()+RESIZE_DELTA);
+    for(int i=0; i<longrel.size(); ++i)
+      if(longrel[i].size() <= Cat::count()) longrel[i].resize(Cat::count()+RESIZE_DELTA);
+  }
+
+  if(uptrigger.size() <= Cat::count())
+    uptrigger.resize(Cat::count()+RESIZE_DELTA);
+  if(dntrigger.size() <= Cat::count())
+    dntrigger.resize(Cat::count()+RESIZE_DELTA);
+  
+  if(obl.size() <= Cat::count()) obl.resize(Cat::count()+RESIZE_DELTA);
+  if(set.size() <= Cat::count()) set.resize(Cat::count()+RESIZE_DELTA);
 }
 
@@ -39,22 +63,39 @@
 {  
   Role::add(s);
-  if(Role::count()>types_sz)
-  {
-    types_sz += 16;
-    lt.resize(types_sz);
-    gt.resize(types_sz);
-  }
-}
-
-void Grammar::add_flag(const char* s)
-{  
-  Flag::add(s);
-  if(Flag::count()>flags_sz)
-  {
-    flags_sz += 16;
-    pass.resize(flags_sz);
-  }
-}
-
+
+  if(lt.size() <= Role::count()) lt.resize(Role::count()+RESIZE_DELTA);
+  if(gt.size() <= Role::count()) gt.resize(Role::count()+RESIZE_DELTA);
+  if(pass.size() <= Role::count()) pass.resize(Role::count()+RESIZE_DELTA);
+  if(include.size() <= Role::count()) include.resize(Role::count()+RESIZE_DELTA);
+  if(exclude.size() <= Role::count()) exclude.resize(Role::count()+RESIZE_DELTA);
+  for(int i=0; i<uptrigger.size(); i++)
+    if(uptrigger[i].size() <= Role::count()) uptrigger[i].resize(Role::count()+RESIZE_DELTA);
+  for(int i=0; i<dntrigger.size(); i++)
+    if(dntrigger[i].size() <= Role::count()) dntrigger[i].resize(Role::count()+RESIZE_DELTA);
+}
+
+//====================================================================================================
+
+bool Grammar::contains_boubble(const list<Boubble*> boubble_list, Boubble* bp) const
+{
+  for(list<Boubble*>::const_iterator bi = boubble_list.begin(); bi != boubble_list.end(); bi++ )
+    if(**bi == *bp) return true;
+  return false;
+}
+
+//----------------------------------------------------------------------------------------------------
+
+void Grammar::add_triggers(Cat src, Cat dest, LongRel l)
+{
+  for(list<Boubble*>::const_iterator b=boubbles.begin(); b!=boubbles.end(); b++)
+    if((*b)->rel() == l)
+      {
+	list<Boubble*>& boubble_list = ((*b)->dir()==UP) ? uptrigger[src][(*b)->next()] : dntrigger[src][(*b)->next()] ;
+	if(!contains_boubble(boubble_list,*b))
+	  boubble_list.push_back(*b);
+      }
+}
+
+//====================================================================================================
 
 void Grammar::set_lt(Role s, Role t)
@@ -85,6 +126,69 @@
 
 
+void Grammar::compute_triggers()
+{
+  //init uptrigger array
+  uptrigger.resize(Cat::count());
+  for(int i=0; i<uptrigger.size(); i++)
+    uptrigger[i].resize(Role::count());
+  //init dntrigger array
+  dntrigger.resize(Cat::count());
+  for(int i=0; i<dntrigger.size(); i++)
+    dntrigger[i].resize(Role::count());
+
+  // for(int c=0; c<Cat::count(); c++)
+  //   for(int r=0; r<Role::count(); r++)
+  //     for(list<Boubble>::const_iterator b=boubbles.begin(); b!=boubbles.end; b++)
+  // 	if(b->dir()==UP && )
+}
+
+//====================================================================================================
+
+list<Boubble*> Grammar::trigger_boubbles(Cat c, Role r, Dir d)
+{
+  list<Boubble*> boubble_list = (d == UP) ? uptrigger[c][r] : dntrigger[c][r];
+  list<Boubble*> ret;
+  for(list<Boubble*>::iterator b = boubble_list.begin(); b != boubble_list.end(); ++b)
+    ret.push_back((*b)->step(r,d));
+  return ret;  
+}
+
+//====================================================================================================
+
+Flag parse_flags(const char* s, const char* v)
+{
+  char buf[16][17];
+  int n=sscanf(s,"%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]%[A-Z]%[+-]",
+	       buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15],buf[16]);
+  for(int i=2; i<=n; i+=2)
+    if(strcmp(buf[i-1],v)==0)
+      return Flag(buf[i-2]);
+  return Flag("NULL");
+}
+
+
+PropSet parse_props(const char* s)
+{
+  PropSet ret;
+  char buf[8][17];
+  int n=sscanf(s,"&%[A-Z]&%[A-Z]&%[A-Z]&%[A-Z]&%[A-Z]&%[A-Z]&%[A-Z]&%[A-Z]",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
+  for(int i=1; i<=n; i++)
+    ret.set(Prop(buf[i-1]));
+  return ret; 
+  
+}
+
+
 bool Grammar::read(FILE* f)
 {
+
+  //>>> TU?
+
+  Prop::add("INIT");
+  Prop::add("FIN");
+
+  //<<< TU?
+
+
   int lineno=0;
   char line[MAXLINE]; // line has the structure: key [arg1 [arg2 [arg3]]]
@@ -93,59 +197,262 @@
   char arg2[MAXLINE];
   char arg3[MAXLINE];
+  char arg4[MAXLINE];
 
   while(fgets(line,MAXLINE,f))
-  {
-    lineno++;
-    int fields=sscanf(line,"%s %s %s %s",key,arg1,arg2,arg3);
-
-    if(fields<1 || key[0]=='#') continue; // skip empty lines and comments
-
-    if     (strcmp(key,"CAT")==0 && fields>=2)
     {
-      add_category(arg1);
+      lineno++;
+      int fields=sscanf(line,"%s %s %s %s %s",key,arg1,arg2,arg3,arg4);
+      
+       if(fields<1 || key[0]=='#') continue; // skip empty lines and comments
+
+      if(fields>1 && arg1[0] == '#') fields=1;
+      if(fields>2 && arg2[0] == '#') fields=2;
+      if(fields>3 && arg3[0] == '#') fields=3;
+      if(fields>4 && arg4[0] == '#') fields=4;
+      
+      if     (strcmp(key,"CAT")==0 && fields==2)
+	{
+	  add_category(arg1);
+	}
+      else if(strcmp(key,"ROLE")==0 && fields==2)
+	{
+	  add_type(arg1);
+	}
+      else if(strcmp(key,"SGL")==0 && fields==2)
+	{  
+	  if(chk_type(arg1))
+	    set_sgl(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"LEFT")==0 && fields==2)
+	{ 
+	  if(chk_type(arg1))
+	    set_left(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"RIGHT")==0 && fields==2)
+	{
+	  if(chk_type(arg1))
+	    set_right(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"INITR")==0 && fields==2)
+	{
+	  if(chk_type(arg1))
+	    set_init(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"FINR")==0 && fields==2)
+	{
+	  if(chk_type(arg1))
+	    set_fin(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"INITF")==0 && fields==2)
+	{
+	  if(chk_flag(arg1))
+	    set_initf(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"FINF")==0 && fields==2)
+	{
+	  if(chk_flag(arg1))
+	    set_finf(arg1);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"REQ")==0 && fields==3)
+	{
+	  if( chk_cat(arg1) && chk_type(arg2) )
+	    set_obl(arg1,arg2);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"CONSTRE")==0 && fields==3)
+	{
+	  if( chk_type(arg1) && chk_type(arg2) )
+	    set_exclude(arg1,arg2);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"CONSTRI")==0 && fields==3)
+	{
+	  if( chk_type(arg1) && chk_type(arg2) )
+	    set_include(arg1,arg2);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"LONG")==0 &&  fields ==3)
+	{
+	    add_long(arg1,arg2);
+	}
+      else if(strcmp(key,"LINK")==0 && fields==4)
+	{ 
+	  char cat1[MAXLINE],flags1[MAXLINE],cat2[MAXLINE],flags2[MAXLINE],type[MAXLINE],props[MAXLINE];
+
+	  if(sscanf(arg1,"%[^;];%s",cat1,flags1)==1) *flags1='\0'; 
+	  if(sscanf(arg2,"%[^;];%s",cat2,flags2)==1) *flags2='\0'; 
+	  if(sscanf(arg3,"%[^&]%s",type,props)==1) *props='\0';
+	  
+	  //	  printf("line=%s\n\tcat1=%s flags1=%s cat2=%s flags2=%s type=%s props=%s\n",line,cat1,flags1,cat2,flags2,type,props);
+
+	  if( chk_cat(cat1) && chk_cat(cat2) && chk_type(type) )
+	    set_connect(cat1,parse_flags(flags1,"+"),parse_flags(flags1,"-"),cat2,parse_flags(flags2,"+"),parse_flags(flags2,"-"),type,parse_props(props));
+	  else if( chk_cat(cat1) && chk_cat(cat2) && chk_long(type) )
+	    {
+	      set_longrel(cat1,cat2,type);
+	      add_triggers(cat1,cat2,type);
+	    }
+	  else
+	      grammar_error(lineno);
+	}
+      // else if(strcmp(key,"LINK")==0 && fields==5)
+      // 	{ 
+      // 	  if( chk_cat(arg1) && chk_cat(arg2) && chk_type(arg4) )
+      // 	    set_connect(arg1,arg2,arg3,arg4);
+      // 	  else
+      // 	      grammar_error(lineno);
+      // 	}
+      // FLAG DECLARATION
+      else if(strcmp(key,"FLAG")==0 && fields==2)
+	{ 
+	  add_flag(arg1);
+	}
+      else if(strcmp(key,"SET")==0 && fields==3)
+	{
+	  if( chk_cat(arg1) && chk_flag(arg2) )
+	    set_set(arg1,arg2);
+	  else
+	    grammar_error(lineno);
+	}
+      else if(strcmp(key,"PASS")==0 && fields==3)
+	{
+	  if( chk_type(arg1) && chk_flag(arg2) )
+	    set_pass(arg1,arg2);
+	  else
+	    grammar_error(lineno);
+	}
+      
+      else fprintf(stderr,"Statement not recognized in line %d. Ignored.\n", lineno);
     }
-    else if(strcmp(key,"ROLE")==0 && fields>=2)
-    {
-      add_type(arg1);
-    }
-    else if(strcmp(key,"SGL")==0 && fields>=2)
-    {  
-      if(chk_type(arg1,lineno))
-        set_sgl(arg1);
-    }
-    else if(strcmp(key,"LEFT")==0 && fields>=2)
-    { 
-      if(chk_type(arg1,lineno))
-        set_left(arg1);
-    }
-    else if(strcmp(key,"RIGHT")==0 && fields>=2)
-    {
-      if(chk_type(arg1,lineno))
-        set_right(arg1);
-    }
-    else if(strcmp(key,"REQ")==0 && fields>=3)
-    {
-      if(chk_cat(arg1,lineno) + chk_type(arg2,lineno) == 2)
-        set_obl(arg1,arg2);
-    }
-    else if(strcmp(key,"LINK")==0 && fields>=4)
-    { 
-      if(chk_cat(arg1,lineno) + chk_cat(arg2,lineno) + chk_type(arg3,lineno) == 3)    
-        set_connect(arg1,arg2,arg3);
-    }
-    // FLAG DECLARATION
-    else if(strcmp(key,"FLAG")==0 && fields>=2)
-    { 
-      add_flag(arg1);
-    }
-
-    else fprintf(stderr,"Invalid line %d. Ignored.\n", lineno);
-  }
-
-//   compute_gt();
-
+  
+  //   compute_gt();
+  
   return true;
   
 }
+
+
+void Grammar::write(ostream& os)
+{
+  for(Cat i=1; i<Cat::count(); ++i)
+    os << "CAT\t" << i.str() << endl;
+
+  for(Role i=1; i<Role::count(); ++i)
+    os << "ROLE\t" << i.str() << endl;
+
+  for(Role i=1; i<Role::count(); ++i)
+    if(sgl.test(i))
+      os << "SGL\t" << i.str() << endl;
+  
+  for(Role i=1; i<Role::count(); ++i)
+    if(left.test(i))
+      os << "LEFT\t" << i.str() << endl;
+
+  for(Role i=1; i<Role::count(); ++i)
+    if(right.test(i))
+      os << "RIGHT\t" << i.str() << endl;
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Role r=1; r<Role::count(); ++r)
+      if(obl[c].test(r))
+	os << "REQ\t" << c.str() << "\t" << r.str() << endl;
+  
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Cat d=1; d<Cat::count(); ++d)
+      for(Links::const_iterator l = connect1[c][d].begin(); l != connect1[c][d].end(); l++)
+	{
+	  os << "LINK\t" << c.str();
+	  if(l->hflagplus||l->hflagminus)
+	    {
+	      os << ";";
+	      if(l->hflagplus) os << (l->hflagplus).str() << "+";
+	      if(l->hflagminus) os << (l->hflagminus).str() << "-"; 
+	    }
+	  os << "\t" << d.str();
+	  if(l->dflagplus||l->dflagminus)
+	    {
+	      os << ";";
+	      if(l->dflagplus) os << (l->dflagplus).str() << "+";
+	      if(l->dflagminus) os << (l->dflagminus).str() << "-"; 
+	    }
+	  os << "\t" << (l->role).str();
+	  for(Prop p=0; p<Prop::count(); ++p)
+	    if(l->props[p])
+	      os << "&" << p.str();
+	  os << endl;
+	}
+
+  for(LongRel i=1; i<LongRel::count(); ++i)
+    os << "LONG\t" << i.str() << endl;
+
+  for(list<Boubble*>::const_iterator b = boubbles.begin(); b != boubbles.end(); b++)
+    os << "BOUBBLE\t" << **b << endl;
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Cat d=1; d<Cat::count(); ++d)
+      for(LongRel l=1; l<LongRel::count(); ++l)
+	if(longrel[c][d].count(l))
+          os << "LLINK\t" << c.str() << "\t" << d.str() << "\t" << l.str() << endl;
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Flag f=1; f<Flag::count(); ++f)
+      if(set[c].test(f))
+	os << "SET\t" << c.str() << "\t" << f.str() << endl;
+
+  for(Role r=1; r<Role::count(); ++r)
+    for(Flag f=1; f<Flag::count(); ++f)
+      if(pass[r].test(f))
+	os << "PASS\t" << r.str() << "\t" << f.str() << endl;
+  
+  for(Role r=1; r<Role::count(); ++r)
+    for(Role t=1; t<Role::count(); ++t)
+      if(include[r].test(t))
+	os << "CONSTRI\t" << r.str() << "\t" << t.str() << endl;
+  
+  for(Role r=1; r<Role::count(); ++r)
+    for(Role t=1; t<Role::count(); ++t)
+      if(exclude[r].test(t))
+	os << "CONSTRE\t" << r.str() << "\t" << t.str() << endl;
+  
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Role r=1; r<Role::count(); ++r)
+      for(list<Boubble*>::const_iterator b=uptrigger[c][r].begin(); b!=uptrigger[c][r].end(); b++)
+	os << "TRIGGER-UP\t" << c.str() << "\t" << r.str() << "\t" << (*b)->rel().str() << endl;
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Role r=1; r<Role::count(); ++r)
+      for(list<Boubble*>::const_iterator b=dntrigger[c][r].begin(); b!=dntrigger[c][r].end(); b++)
+	os << "TRIGGER-DN\t" << c.str() << "\t" << r.str() << "\t" << (*b)->rel().str() << endl;
+
+  for(Flag i=1; i<Flag::count(); ++i)
+    os << "FLAG\t" << i.str() << endl;
+}
+
+
+
+
+
+
+
+
+
+//================================= OLD
 
 void Grammar::write(FILE* f)
@@ -155,5 +462,5 @@
 
   for(Role i=1; i<Role::count(); ++i)
-    fprintf(f,"ROLE\t%s\n",i.str());
+    fprintf(f,"ROLE\t%s (%d)(%d)\n",i.str(),Role::index(i.str()),chk_type(i.str()));
 
   for(Role i=1; i<Role::count(); ++i)
@@ -176,6 +483,24 @@
           fprintf(f,"LINK\t%s\t%s\t%s\n",c.str(),d.str(),t.str());
 
+  for(LongRel i=1; i<LongRel::count(); ++i)
+    fprintf(f,"LONG\t%s\n",i.str());
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Cat d=1; d<Cat::count(); ++d)
+      for(LongRel l=1; l<LongRel::count(); ++l)
+	if(longrel[c][d].count(l))
+          fprintf(f,"LLINK\t%s\t%s\t%s\n",c.str(),d.str(),l.str());
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Role r=1; r<Role::count(); ++r)
+      for(list<Boubble*>::const_iterator b=uptrigger[c][r].begin(); b!=uptrigger[c][r].end(); b++)
+	fprintf(f,"#TRIGGER\t%s\t%s\t%s\n",c.str(),r.str(),(*b)->rel().str());
+
+  for(Cat c=1; c<Cat::count(); ++c)
+    for(Role r=1; r<Role::count(); ++r)
+      for(list<Boubble*>::const_iterator b=dntrigger[c][r].begin(); b!=dntrigger[c][r].end(); b++)
+	fprintf(f,"#TRIGGER\t%s\t%s\t%s\n",c.str(),r.str(),(*b)->rel().str());
+
   for(Flag i=1; i<Flag::count(); ++i)
     fprintf(f,"FLAG\t%s\n",i.str());
 }
-
