diff --git a/lib/modules/LR.pmod/parser.pike b/lib/modules/LR.pmod/parser.pike
index 003b7deb8bbfccb177df71f25719e87127845cac..1faf7076cd9436b983f2e3aac3520e1c8646c2b1 100644
--- a/lib/modules/LR.pmod/parser.pike
+++ b/lib/modules/LR.pmod/parser.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: parser.pike,v 1.9 1998/11/14 01:20:02 grubba Exp $
+ * $Id: parser.pike,v 1.10 1998/11/14 04:22:06 grubba Exp $
  *
  * A BNF-grammar in Pike.
  * Compiles to a LALR(1) state-machine.
@@ -9,7 +9,7 @@
 
 //.
 //. File:	parser.pike
-//. RCSID:	$Id: parser.pike,v 1.9 1998/11/14 01:20:02 grubba Exp $
+//. RCSID:	$Id: parser.pike,v 1.10 1998/11/14 04:22:06 grubba Exp $
 //. Author:	Henrik Grubbstr�m (grubba@infovav.se)
 //.
 //. Synopsis:	LALR(1) parser and compiler.
@@ -21,7 +21,6 @@
 //. Normal use of this object would be:
 //.
 //. {add_rule, set_priority, set_associativity}*
-//. set_scanner
 //. set_symbol_to_string
 //. compile
 //. {parse}*
@@ -72,6 +71,10 @@ class kernel {
   //.   Contains the items in this state.
   array(object(item)) items = ({});
 
+  //. + item_id_to_items
+  //.   Used to lookup items given rule and offset
+  mapping(int:object(item)) item_id_to_item = ([]);
+
   //. + symbol_items
   //.   Contains the items whose next symbol is this non-terminal.
   mapping(int : multiset(object(item))) symbol_items = ([]);
@@ -96,6 +99,8 @@ class kernel {
     int|string symbol;
   
     items += ({ i });
+    item_id_to_item[i->item_id] = i;
+
     if (i->offset < sizeof(i->r->symbols)) {
       symbol = i->r->symbols[i->offset];
 
@@ -768,16 +773,20 @@ static private int go_through(object(kernel) state, object(rule) r, int offset,
   int index;
   object(item) i, master;
 
+  i = state->item_id_to_item[r->number + offset];
+#if 0
   for (index = 0; index < sizeof(state->items); index++) {
     if ((state->items[index]->r == r) &&
 	(state->items[index]->offset == offset)) {
       /* Found the index for the current rule and offset */
+      i = state->items[index];
       break;
     }
   }
+#endif /* 0 */
 
   /* What to do if not found? */
-  if (index == sizeof(state->items)) {
+  if (!i) {
     werror(sprintf("go_through: item with offset %d in rule\n%s\n"
 		   "not found in state\n%s\n",
 		   offset, rule_to_string(r), state_to_string(state)));
@@ -785,7 +794,6 @@ static private int go_through(object(kernel) state, object(rule) r, int offset,
     return(0);
   }
 
-  i = state->items[index];
   if (i->master_item) {
     master = i->master_item;
   } else {
@@ -1224,38 +1232,59 @@ int compile()
   /* Compute lookback-sets */
   for (int index = 0; index < s_q->tail; index++) {
     array(object(item)) items =  s_q->arr[index]->items;
+    // Set up a lookup table to speedup lookups later.
+    mapping(int:array(object(item))) lookup = ([]);
+    foreach (items, object(item) i) {
+      if (!i->offset) {
+	if (!lookup[i->r->nonterminal]) {
+	  lookup[i->r->nonterminal] = ({ i });
+	} else {
+	  lookup[i->r->nonterminal] += ({ i });
+	}
+      }
+    }
     foreach (items, object(item) transition) {
       int|string symbol;
 
-      if ((transition->offset != sizeof(transition->r->symbols)) &&
-	  (intp(symbol = transition->r->symbols[transition->offset])) &&
-	  (!transition->master_item)) {
-	/* NonTerminal and master item*/
+      if ((!transition->master_item) &&
+	  (transition->offset != sizeof(transition->r->symbols)) &&
+	  (intp(symbol = transition->r->symbols[transition->offset]))) {
+	/* Master item and
+	 * Not a reduction item and
+	 * next symbol is a NonTerminal
+	 */
+	if (!lookup[symbol]) {
+	  // Foo? Shouldn't these always exist since we've made
+	  // a closure earlier?
+	  werror(sprintf("WARNING: No item for symbol <%s>\n"
+			 "in state:\n"
+			 "%s\n",
+			 symbol_to_string(symbol),
+			 state_to_string(s_q->arr[index])));
+	  continue;
+	}
 
 	/* Find items which can reduce to the nonterminal from above */
-	foreach (items, object(item) i2) {
-	  if ((!i2->offset) &&
-	      (i2->r->nonterminal == symbol)) {
-	    if (sizeof(i2->r->symbols)) {
-	      if (go_through(i2->next_state, i2->r, i2->offset+1,
-			     transition)) {
-		/* Nullable */
-		object(item) master = i2;
-		if (i2->master_item) {
-		  master = i2->master_item;
-		}
-		/* Is this a nonterminal transition? */
-		if ((master->offset != sizeof(master->r->symbols)) &&
-		    (intp(master->r->symbols[master->offset]))) {
-		  /* Don't include ourselves */
-		  if (master != transition) {
-		    master->relation[transition] = 1;
-		  }
+	foreach (lookup[symbol], object(item) i) {
+	  if (sizeof(i->r->symbols)) {
+	    if (go_through(i->next_state, i->r, i->offset+1,
+			   transition)) {
+	      /* Nullable */
+	      object(item) master = i;
+	      if (i->master_item) {
+		master = i->master_item;
+	      }
+	      /* Is this a nonterminal transition? */
+	      if ((master->offset != sizeof(master->r->symbols)) &&
+		  (intp(master->r->symbols[master->offset]))) {
+		/* Don't include ourselves */
+		if (master != transition) {
+		  master->relation[transition] = 1;
 		}
 	      }
-	    } else {
-	      i2->relation[transition] = 1;
 	    }
+	  } else {
+	    i->relation[transition] = 1;
 	  }
 	}
       }
@@ -1369,8 +1398,8 @@ int compile()
 //.   Parse the input according to the compiled grammar.
 //.   The last value reduced is returned.
 //. NOTA BENE:
-//.   The parser must have been compiled (with compile()), and a scanner
-//.   been set (with set_scanner()) prior to calling this function.
+//.   The parser must have been compiled (with compile())
+//.   prior to calling this function.
 //. BUGS
 //.   Errors should be throw()n.
 //. > scanner
@@ -1381,7 +1410,7 @@ int compile()
 //. > action_object
 //.   Object used to resolve those actions that have been specified as
 //.   strings.
-mixed parse(function(void:string|array(string|mixed)) scanner,
+mixed parse(object|function(void:string|array(string|mixed)) scanner,
 	    void|object action_object)
 {
   object(Stack.stack) value_stack = Stack.stack();
@@ -1393,7 +1422,8 @@ mixed parse(function(void:string|array(string|mixed)) scanner,
 
   error = 0;	/* No parse error yet */
 
-  if (!scanner || !functionp(scanner)) {
+  if (!functionp(scanner) &&
+      !(objectp(scanner) && functionp(scanner->`()))) {
     werror("parser->parse(): scanner not set!\n");
     error = ERROR_NO_SCANNER;
     return(0);