diff --git a/lib/modules/LR.pmod/item.pike b/lib/modules/LR.pmod/item.pike
index 4da9b83369cff95ccc47d0af472d95da4906d5d0..ae927a2c57a777fa5a4384f68652de150a65fb7e 100644
--- a/lib/modules/LR.pmod/item.pike
+++ b/lib/modules/LR.pmod/item.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: item.pike,v 1.2 1997/03/30 17:28:20 grubba Exp $
+ * $Id: item.pike,v 1.3 1998/11/12 01:31:21 grubba Exp $
  *
  * An LR(0) item
  *
@@ -8,7 +8,7 @@
 
 //.
 //. File:	item.pike
-//. RCSID:	$Id: item.pike,v 1.2 1997/03/30 17:28:20 grubba Exp $
+//. RCSID:	$Id: item.pike,v 1.3 1998/11/12 01:31:21 grubba Exp $
 //. Author:	Henrik Grubbstr�m (grubba@infovav.se)
 //.
 //. Synopsis:	An LR(0) item
@@ -51,3 +51,17 @@ multiset(object /* (item) */ ) relation = (<>);
 //. + counter
 //.   Depth counter (used when compiling).
 int counter = 0;
+
+//. + item_hash
+//.   Hash used to compare items.
+string item_hash;
+
+//. - make_item_hash
+//.   Calculate the item hash.
+void make_item_hash()
+{
+  r->make_rule_hash();
+  if (!item_hash) {
+    item_hash = r->rule_hash + "�" + offset;
+  }
+}
diff --git a/lib/modules/LR.pmod/kernel.pike b/lib/modules/LR.pmod/kernel.pike
index 57ac9d464a916e0853a0c8668ef56020e8a622dc..ecb005aef87f601b7262d4579ea11d3100f0de23 100644
--- a/lib/modules/LR.pmod/kernel.pike
+++ b/lib/modules/LR.pmod/kernel.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: kernel.pike,v 1.2 1997/03/30 17:28:22 grubba Exp $
+ * $Id: kernel.pike,v 1.3 1998/11/12 01:31:24 grubba Exp $
  *
  * Implements a LR(1) state;
  *
@@ -8,7 +8,7 @@
 
 //.
 //. File:	kernel.pike
-//. RCSID:	$Id: kernel.pike,v 1.2 1997/03/30 17:28:22 grubba Exp $
+//. RCSID:	$Id: kernel.pike,v 1.3 1998/11/12 01:31:24 grubba Exp $
 //. Author:	Henrik Grubbstr�m
 //.
 //. Synopsis:	Implements an LR(1) state.
@@ -39,6 +39,10 @@ mapping(int : multiset(object(item))) symbol_items = ([]);
 //.   object(rule)	REDUCE according to this rule on this symbol.
 mapping(int|string : object /* (kernel) */|object(rule)) action = ([]);
 
+//. + kernel_hash
+//.   Hash value used by equalp
+string kernel_hash;
+
 /*
  * Functions
  */
@@ -61,6 +65,17 @@ void add_item(object(item) i)
       symbol_items[symbol] = (< i >);
     }
   }
+  kernel_hash = 0;
+}
+
+//. - make_kernel_hash
+//.   Computes the kernel hash.
+void make_kernel_hash()
+{
+  if (!kernel_hash) {
+    items->make_item_hash();
+    kernel_hash = sort(items->item_hash) * ":";
+  }
 }
 
 //. - equalp
@@ -74,6 +89,15 @@ int equalp(object /* (kernel) */ state)
     return(0);
   }
 
+  if (!kernel_hash) {
+    make_kernel_hash();
+  }
+  if (!state->kernel_hash) {
+    state->make_kernel_hash();
+  }
+  return(kernel_hash == state->kernel_hash);
+
+
   /* Could probably make it test only kernel items */
 
   foreach (state->items, object(item) i) {
diff --git a/lib/modules/LR.pmod/rule.pike b/lib/modules/LR.pmod/rule.pike
index 97c9fdfc1f8839a2db4e93a522cccf43030289b4..9a3f7f03eda66782ee5b8b8c35e7be9f173513c3 100644
--- a/lib/modules/LR.pmod/rule.pike
+++ b/lib/modules/LR.pmod/rule.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: rule.pike,v 1.2 1997/03/30 17:28:28 grubba Exp $
+ * $Id: rule.pike,v 1.3 1998/11/12 01:31:26 grubba Exp $
  *
  * A BNF-rule.
  *
@@ -8,7 +8,7 @@
 
 //.
 //. File:	rule.pike
-//. RCSID:	$Id: rule.pike,v 1.2 1997/03/30 17:28:28 grubba Exp $
+//. RCSID:	$Id: rule.pike,v 1.3 1998/11/12 01:31:26 grubba Exp $
 //. Author:	Henrik Grubbstr�m (grubba@infovav.se)
 //.
 //. Synopsis:	Implements a BNF rule.
@@ -25,9 +25,11 @@
 //. + nonterminal
 //.   Non-terminal this rule reduces to.
 int nonterminal;
+
 //. + symbols
 //.   The actual rule
 array(string|int) symbols;
+
 //. + action
 //.   Action to do when reducing this rule.
 //.   function - call this function.
@@ -43,6 +45,7 @@ function|string action;
 //. + has_tokens
 //.   This rule contains tokens
 int has_tokens = 0;
+
 //. + num_nonnullables
 //.   This rule has this many non-nullable symbols at the moment.
 int num_nonnullables = 0;
@@ -56,6 +59,19 @@ multiset(string) prefix_tokens = (<>);
 //.   Sequence number of this rule (used for conflict resolving)
 int number = 0;
 
+//. + rule_hash
+//.   Hash value used to compare rules.
+string rule_hash;
+
+//. - make_rule_hash
+//.   Compute the rule_hash.
+void make_rule_hash()
+{
+  if (!rule_hash) {
+    rule_hash = sprintf("%O:%O:%O", nonterminal, symbols, action);
+  }
+}
+
 /*
  * Functions
  */
@@ -83,7 +99,7 @@ int number = 0;
 //.   function - Call this function.
 //.   string - Call this function by name in the object given to the parser.
 //.   The function is called with arguments corresponding to the values of
-//.   the elements of the rule. The return value of the function will be
+//.   the elements of the rule. The return value of the function will become
 //.   the value of this non-terminal. The default rule is to return the first
 //.   argument.
 void create(int nt, array(string|int) r, function|string|void a)