Index: src/dgp/cmdline_dgp.ggo
===================================================================
--- src/dgp/cmdline_dgp.ggo	(revision 5f4d9c3b32eea7b6643a751aa75bdb05b7d41576)
+++ src/dgp/cmdline_dgp.ggo	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -11,8 +11,10 @@
 				flag off
 
+option  "time"		-	"Print parse time."
+				flag off
+
 option	"info"		-	"Print info. 
-h - heads         d - dependents
-s - sets
-c - constraints	  n - node/arc counts	t - parse time
-"
+				       h - heads         d - dependents
+				       s - sets
+				       c - constraints	  n - node/arc counts"
 string no default="h"
Index: src/dgp/dgp1.cc
===================================================================
--- src/dgp/dgp1.cc	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
+++ src/dgp/dgp1.cc	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -303,11 +303,31 @@
 //====================================================================================================
 
-bool check_boubbles_at_target(list<Boubble*> boubbles, int node)
-{
-  for(list<Boubble*>::iterator b = boubbles.begin(); b != boubbles.end(); b++)
-    if( (*b)->is_at_target() && !grammar.check_longrel(sgraph.cat((*b)->src()), sgraph.cat(node), (*b)->rel()))
-      return false;
+// sprawdza czy te, spo¶ród b±bli, które dotar³y do celu node
+// daj± wynik prawdziwy, dodatkowo - usuwa je z listy boubbles
+
+bool check_boubbles_at_target(list<Boubble*>& boubbles, int node)
+{
+  list<Boubble*>::iterator last; // ostatnio sprawdzany b±bel
+  bool remove=false;             // czy usun±æ ostatnio sprawdzany b±bel
+
+  for(list<Boubble*>::iterator b = boubbles.begin(); b != boubbles.end(); b = remove ? boubbles.erase(b) : ++b )
+    if( (*b)->is_at_target() )
+      if( grammar.check_longrel(sgraph.cat((*b)->src()), sgraph.cat(node), (*b)->rel()) )
+	remove=true;
+      else
+	return false;
+    else
+      remove=false;
+      
   return true;
 }
+
+// bool check_boubbles_at_target(list<Boubble*> boubbles, int node)
+// {
+//   for(list<Boubble*>::iterator b = boubbles.begin(); b != boubbles.end(); ++b )
+//     if( (*b)->is_at_target() && !grammar.check_longrel(sgraph.cat((*b)->src()), sgraph.cat(node), (*b)->rel()) )
+//       return false;
+//   return true;
+// }
 
 //====================================================================================================
Index: src/dgp/grammar.cc
===================================================================
--- src/dgp/grammar.cc	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
+++ src/dgp/grammar.cc	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -187,4 +187,6 @@
   Prop::add("INIT");
   Prop::add("FIN");
+  Prop::add("LEFT");
+  Prop::add("RIGHT");
 
   //<<< TU?
Index: src/dgp/grammar.hh
===================================================================
--- src/dgp/grammar.hh	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
+++ src/dgp/grammar.hh	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -192,15 +192,15 @@
 //----------------------------------------------------------------------------------------------------
 
-inline
-bool Grammar::check_constr(NodeProp& hprop, NodeProp& dprop, int dir, Role role)    // dir: 0-left 1-right
-{
-  return 
-    !hprop.forbidden[role] &&
-    ( dir==1 || !right[role] ) &&
-    ( dir==0 || !left[role]  ) &&
-    ( dir==1 || (hprop.attached&init).none() ) &&
-    ( dir==0 || (hprop.attached&fin).none() )
-    ;
-}
+// inline
+// bool Grammar::check_constr(NodeProp& hprop, NodeProp& dprop, int dir, Role role)    // dir: 0-left 1-right
+// {
+//   return 
+//     !hprop.forbidden[role] &&
+//     ( dir==1 || !right[role] ) &&
+//     ( dir==0 || !left[role]  ) &&
+//     ( dir==1 || (hprop.attached&init).none() ) &&
+//     ( dir==0 || (hprop.attached&fin).none() )
+//     ;
+// }
 
 //----------------------------------------------------------------------------------------------------
@@ -211,6 +211,6 @@
   return 
     !hprop.forbidden[link.role] &&
-    ( dir==1 || !right[link.role] ) &&
-    ( dir==0 || !left[link.role]  ) &&
+    ( dir==1 || (!right[link.role] && !link.props[Prop("RIGHT")]) ) &&  // ZREZYGNOWAÆ Z TABLICY right[<role>]
+    ( dir==0 || (!left[link.role] && !link.props[Prop("LEFT")]) ) &&
     ( dir!=0 || !hprop.init_attached ) &&
     ( dir!=1 || !hprop.fin_attached )
Index: src/dgp/main.cc
===================================================================
--- src/dgp/main.cc	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
+++ src/dgp/main.cc	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -6,4 +6,7 @@
  * Author:	Tomasz Obrebski
  */
+
+#include <ctime>
+#include <sys/time.h>
 
 #include "global.hh"
@@ -16,4 +19,6 @@
 
 #define MAXSEGMENTS 500
+
+#define MICROSECONDSELAPSED(A,B) ((B.tv_sec - A.tv_sec)*1000000 + (B.tv_usec - A.tv_usec))
 
 char segment[MAXSEGMENTS][MAXLINE];
@@ -30,4 +35,6 @@
 FILE* debugf=stdout;
 unsigned int info=0U;
+
+bool printtimeinfo=false;
 
 void output();
@@ -53,4 +60,6 @@
   if(args.debug_given) debug=true;
 
+  if(args.time_given) printtimeinfo=true;
+
   for(char* c=args.info_arg; *c!='\0' ; ++c)
     switch(*c)
@@ -70,5 +79,5 @@
   // exit(0);
 
-
+  struct timeval starttime,afterinput,afterparse,endtime;
 
   mgraph.clear();
@@ -78,4 +87,5 @@
   while (fgets(line, MAXLINE+1, inputf))
   {
+    gettimeofday(&starttime,NULL);
     line[strlen(line)-1] = '\0';
     strcpy(segment[segcount],line);
@@ -90,6 +100,17 @@
     if(strcmp(segtype,"EOS")==0)
     {
+      gettimeofday(&afterinput,NULL);
       dgp1(); // parametry!!! MGraph, SGraph, Grammar
+      gettimeofday(&afterparse,NULL);
       output();
+      gettimeofday(&endtime,NULL);
+
+      if(printtimeinfo)
+	{
+	  fprintf(stderr,"### INPUT  TIME: %10.2fms\n", (float)MICROSECONDSELAPSED(starttime,afterinput)/1000 );
+	  fprintf(stderr,"### PARSE  TIME: %10.2fms\n", (float)MICROSECONDSELAPSED(afterinput,afterparse)/1000 );
+	  fprintf(stderr,"### OUTPUT TIME: %10.2fms\n", (float)MICROSECONDSELAPSED(afterparse,endtime)/1000 );
+	  fprintf(stderr,"### TOTAL  TIME: %10.2fms\n", (float)MICROSECONDSELAPSED(starttime,endtime)/1000 );
+	}
       
       mgraph.clear();
Index: src/dgp/sgraph.cc
===================================================================
--- src/dgp/sgraph.cc	(revision e7de6cc88c605c4f810cbc852e843294b4b0e8ac)
+++ src/dgp/sgraph.cc	(revision a15e59b825ae3aa1d5f3555afaf4cdbf22beda62)
@@ -148,5 +148,5 @@
       if(node.prop.forbidden[i]) buf+=sprintf(buf,"%s!%s",(cont++)?",":"",i.str());
     for(Role i=1; i<=Role::count(); ++i)
-      if(node.prop.required[i]) buf+=sprintf(buf,"%s&%s",(cont++)?",":"",i.str());
+      if(node.prop.required[i]) buf+=sprintf(buf,"%s-%s",(cont++)?",":"",i.str());
     for(Role i=1; i<=Role::count(); ++i)
       if(node.prop.attached[i]) buf+=sprintf(buf,"%s+%s",(cont++)?",":"",i.str());
