diff --git a/src/backends/glr.c b/src/backends/glr.c
index 9828c2b30fc2a53eab1d2de5fd77b6f0893b6065..5619b26a4558b7ffbfe5b0ac33689e4625848cc2 100644
--- a/src/backends/glr.c
+++ b/src/backends/glr.c
@@ -174,9 +174,9 @@ static bool glr_step(HParseResult **result, HSlist *engines,
     HSlistNode *x;
     for(x=engines->head; x; x=x->next) {
       HLREngine *eng = x->elem;
-      if(eng->state == engine->state) {
-        x->elem = lrengine_merge(eng, engine);
-        break;
+      if(eng->state == engine->state && eng->input.index == engine->input.index) {
+    	x->elem = lrengine_merge(eng, engine);
+    	break;
       }
     }
     if(!x)  // no merge happened
diff --git a/src/t_regression.c b/src/t_regression.c
index 2c28b99efe6a36e69e5831044dadcbcc381f4d18..3bf763600962bdcdad6208863ba27f92966195f3 100644
--- a/src/t_regression.c
+++ b/src/t_regression.c
@@ -1,5 +1,6 @@
 #include <glib.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include "glue.h"
 #include "hammer.h"
 #include "test_suite.h"
@@ -472,6 +473,141 @@ static void test_issue83() {
   g_check_cmp_int(r, ==, 0);
 }
 
+/*
+ * This is Meg's cut-down bug 60 test case
+ */
+
+static void test_bug60() {
+    /* There is probably an even smaller example that shows the issue */
+
+	  HParser *zed = NULL;
+	  HParser *alpha = NULL;
+	  HParser *vchar = NULL;
+	  HParser *why = NULL;
+	  HParser *plural_zed = NULL;
+	  HParser *plural_zed_zed = NULL;
+	  HParser *a_to_zed = NULL;
+	  HParser *alphas = NULL;
+	  HParser *rule = NULL;
+	  HParser *rulelist = NULL;
+	  HParser *p = NULL;
+	  HParseResult *r = NULL;
+	  int n;
+
+	  zed =  h_ch('z');
+
+	  vchar = h_ch_range(0x79, 0x7a); /* allows y and z */
+
+	  alpha = h_ch('a');
+
+	  why = h_ch('y');
+
+	  plural_zed = h_sequence(
+	      why,
+	      h_many(h_choice(alpha, vchar, NULL)),
+	      NULL);
+	  plural_zed_zed = h_choice(plural_zed, zed, NULL);
+	  alphas = h_choice(alpha, h_sequence(plural_zed_zed, alpha, NULL), NULL);
+
+	  a_to_zed = h_sequence(
+	      zed,
+	      h_many(h_sequence(h_many1(alphas), zed, NULL)),
+	      NULL);
+	  rule = h_sequence(a_to_zed, plural_zed_zed, NULL);
+	  rulelist = h_many1(h_choice(
+	      rule,
+	      h_sequence(h_many(alphas), plural_zed_zed, NULL),
+	      NULL));
+
+	  p = rulelist;
+
+	  g_check_parse_ok(p, PB_GLR, "ayzza", 5);
+	  g_check_parse_match(p, PB_GLR, "ayzza", 5, "(((u0x61) (u0x79 (u0x7a u0x7a u0x61))))");
+
+}
+
+/*
+ * This is the original bug60 test case; cut down from an ABNF parser
+ */
+
+#define BUG60_ABNF_SCAN_UP_TO 64
+
+static void test_bug60_abnf() {
+  HParser *newline = NULL;
+  HParser *alpha = NULL;
+  HParser *sp = NULL;
+  HParser *vchar = NULL;
+  HParser *equal = NULL;
+  HParser *semicolon = NULL;
+  HParser *comment = NULL;
+  HParser *c_nl = NULL;
+  HParser *c_sp = NULL;
+  HParser *defined_as = NULL;
+  HParser *alphas = NULL;
+  HParser *rule = NULL;
+  HParser *rulelist = NULL;
+  HParser *p = NULL;
+  int i, j, r, s_size;
+  char *s = NULL;
+  const char *test_string_template = "x = y z%s;%s\n\n";
+  char buf_1[BUG60_ABNF_SCAN_UP_TO+1];
+  char buf_2[2*BUG60_ABNF_SCAN_UP_TO+1];
+
+  newline = h_ch('\n');
+  alpha = h_choice(h_ch_range('A', 'Z'), h_ch_range('a', 'z'), NULL);
+  sp = h_ch(' ');
+  vchar = h_ch_range(0x21, 0x7e);
+  equal = h_ch('=');
+  semicolon = h_ch(';');
+  comment = h_sequence(
+    semicolon,
+    h_many(h_choice(sp, vchar, NULL)),
+    newline,
+    NULL);
+  c_nl = h_choice(comment, newline, NULL);
+  c_sp = h_choice(sp, h_sequence(c_nl, sp, NULL), NULL);
+  defined_as = h_sequence(h_many(c_sp), equal, h_many(c_sp), NULL);
+  alphas = h_sequence(
+    alpha,
+    h_many(h_sequence(h_many1(c_sp), alpha, NULL)),
+    h_many(c_sp),
+    NULL);
+  rule = h_sequence(alpha, defined_as, alphas, c_nl, NULL);
+  rulelist = h_many1(h_choice(
+    rule,
+    h_sequence(h_many(c_sp), c_nl, NULL),
+    NULL));
+
+  p = rulelist;
+  g_check_compilable(p, PB_GLR, 1);
+
+  /* Have a buffer for the string */
+  s_size = strlen(test_string_template) + 3*BUG60_ABNF_SCAN_UP_TO + 1;
+  s = malloc(s_size);
+  g_check_cmp_ptr(s, !=, NULL);
+
+  /*
+   * Try to parse all the different strings according to the template up to
+   * the scan limit.
+   *
+   * Correct behavior: it parses for all values of i, j.
+   * Bugged behavior: when i % 3 != 0, parse failures begin to occur at
+   * j == (i / 3) + (i % 3).
+   */
+  for (i = 0; i < BUG60_ABNF_SCAN_UP_TO; ++i) {
+    memset(buf_1, ' ', i);
+    buf_1[i] = 0;
+    for (j = 0; j < 2*BUG60_ABNF_SCAN_UP_TO; ++j) {
+      memset(buf_2, 'x', j);
+      buf_2[j] = 0;
+      snprintf(s, s_size, test_string_template, buf_1, buf_2);
+      g_check_parse_ok_no_compile(p, s, strlen(s));
+    }
+  }
+
+  free(s);
+}
+
 void register_regression_tests(void) {
   g_test_add_func("/core/regression/bug118", test_bug118);
   g_test_add_func("/core/regression/seq_index_path", test_seq_index_path);
@@ -488,4 +624,6 @@ void register_regression_tests(void) {
   g_test_add_func("/core/regression/issue87", test_issue87);
   g_test_add_func("/core/regression/issue92", test_issue92);
   g_test_add_func("/core/regression/issue83", test_issue83);
+  g_test_add_func("/core/regression/bug60", test_bug60);
+  g_test_add_func("/core/regression/bug60_abnf", test_bug60_abnf);
 }
diff --git a/src/test_suite.h b/src/test_suite.h
index 6f95e077650e86d4c5ef1e0f01f2ee2b20ab31d2..775c8818a1f79cb2fb50275a55c0e8e1f8a235fe 100644
--- a/src/test_suite.h
+++ b/src/test_suite.h
@@ -109,24 +109,36 @@
   } while(0)
 
 #define g_check_compilable(lang, backend, params) do {	\
-    if (!h_compile(lang, backend, params)) {		\
-      g_test_message("Language is not %s(%s)", #backend, params);	\
+    int r = h_compile((HParser *)(lang), (HParserBackend)(backend), (void *)(params)); \
+    if (r != 0) {		\
+      g_test_message("Language is not %s(%s)", #backend, #params);	\
       g_test_fail();					\
     }							\
   } while(0)
 
-  
+#define print_arena_stats(arena) do {					\
+    if (g_test_verbose()) {						\
+      HArenaStats stats;						\
+      h_allocator_stats(arena, &stats);					\
+      g_test_message("Parse used %zd bytes, wasted %zd bytes. "		\
+                     "Inefficiency: %5f%%",				\
+                     stats.used, stats.wasted,				\
+                     stats.wasted * 100. / (stats.used+stats.wasted));	\
+    }									\
+  } while(0)
+
 #define g_check_parse_failed__m(mm__, parser, backend, input, inp_len) do { \
     int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend)backend, NULL); \
     if(skip != 0) {	\
-      g_test_message("Compile failed");					\
+      g_test_message("Compile failed on line %d", __LINE__);					\
       g_test_fail();							\
       break;	\
     }	\
-    HParseResult *result = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
-    if (NULL != result) {						\
-      h_parse_result_free(result);					\
-      g_test_message("Check failed: shouldn't have succeeded, but did"); \
+    HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
+    if (NULL != res) {						\
+      print_arena_stats(res->arena); \
+      h_parse_result_free(res);					\
+      g_test_message("Check failed: parse shouldn't have succeeded, but did on line %d", __LINE__); \
       g_test_fail();							\
     }									\
   } while(0)
@@ -134,25 +146,27 @@
 #define g_check_parse_failed(p, be, input, len)				\
     g_check_parse_failed__m(&system_allocator, p, be, input, len)
 
-#define print_arena_stats(arena) do {					\
-    if (g_test_verbose()) {						\
-      HArenaStats stats;						\
-      h_allocator_stats(arena, &stats);					\
-      g_test_message("Parse used %zd bytes, wasted %zd bytes. "		\
-                     "Inefficiency: %5f%%",				\
-                     stats.used, stats.wasted,				\
-                     stats.wasted * 100. / (stats.used+stats.wasted));	\
+#define g_check_parse_failed_no_compile__m(mm__, parser, input, inp_len) do { \
+    HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
+    if (NULL != res) {						\
+      print_arena_stats(res->arena); \
+      h_parse_result_free(res);					\
+      g_test_message("Check failed: shouldn't have succeeded, but did on ;ine %d", __LINE__); \
+      g_test_fail();							\
     }									\
   } while(0)
 
-#define g_check_parse_ok(parser, backend, input, inp_len) do {		\
-    int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
+#define g_check_parse_failed_no_compile(p, input, len)				\
+    g_check_parse_failed__m(&system_allocator, p, input, len)
+
+#define g_check_parse_ok__m(mm__, parser, backend, input, inp_len) do {		\
+    int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend) backend, NULL); \
     if(skip) {								\
       g_test_message("Compile failed");					\
       g_test_fail();							\
       break;								\
     }									\
-    HParseResult *res = h_parse(parser, (const uint8_t*)input, inp_len); \
+    HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
     if (!res) {								\
       g_test_message("Parse failed on line %d", __LINE__);		\
       g_test_fail();							\
@@ -162,14 +176,31 @@
     }									\
   } while(0)
 
-#define g_check_parse_match(parser, backend, input, inp_len, result) do { \
-    int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
+#define g_check_parse_ok(p, be, input, len)				\
+    g_check_parse_ok__m(&system_allocator, p, be, input, len)
+
+#define g_check_parse_ok_no_compile__m(mm__, parser, input, inp_len) do {		\
+    HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
+    if (!res) {								\
+      g_test_message("Parse failed on line %d", __LINE__);		\
+      g_test_fail();							\
+    } else {								\
+      print_arena_stats(res->arena);					\
+      h_parse_result_free(res);						\
+    }									\
+  } while(0)
+
+#define g_check_parse_ok_no_compile(p, input, len)				\
+    g_check_parse_ok_no_compile__m(&system_allocator, p, input, len)
+
+#define g_check_parse_match__m(mm__, parser, backend, input, inp_len, result) do { \
+    int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend) backend, NULL); \
     if(skip) {								\
       g_test_message("Compile failed");					\
       g_test_fail();							\
       break;								\
     }									\
-    HParseResult *res = h_parse(parser, (const uint8_t*)input, inp_len); \
+    HParseResult *res = h_parse__m(mm__, (HParser *)(parser), (const uint8_t*)input, inp_len); \
     if (!res) {								\
       g_test_message("Parse failed on line %d", __LINE__);		\
       g_test_fail();							\
@@ -182,6 +213,26 @@
     }									\
   } while(0)
 
+#define g_check_parse_match(parser, backend, input, inp_len, result) \
+    g_check_parse_match__m(&system_allocator, parser, backend, input, inp_len, result)
+
+#define g_check_parse_match_no_compile__m(mm__, parser, input, inp_len, result) do { \
+    HParseResult *res = h_parse__m(mm__, (HParser *)(parser), (const uint8_t*)input, inp_len); \
+    if (!res) {								\
+      g_test_message("Parse failed on line %d", __LINE__);		\
+      g_test_fail();							\
+    } else {								\
+      char* cres = h_write_result_unamb(res->ast);			\
+      g_check_string(cres, ==, result);					\
+      (&system_allocator)->free(&system_allocator, cres);		\
+      print_arena_stats(res->arena);					\
+      h_parse_result_free(res);						\
+    }									\
+  } while(0)
+
+#define g_check_parse_match_no_compile(parser, input, inp_len, result) \
+    g_check_parse_match_no_compile__m(&system_allocator, parser, input, inp_len, result)
+
 #define g_check_parse_chunks_failed__m(mm__, parser, backend, chunk1, c1_len, chunk2, c2_len) do { \
     int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend)backend, NULL); \
     if(skip) {								\
@@ -193,7 +244,7 @@
   } while(0)
 
 #define g_check_parse_chunks_failed___m(mm__, parser, chunk1, c1_len, chunk2, c2_len) do { \
-    HSuspendedParser *s = h_parse_start__m(mm__, parser);		\
+    HSuspendedParser *s = h_parse_start__m(mm__, (HParser *)(parser));		\
     if(!s) {								\
       g_test_message("Chunk-wise parsing not available");		\
       g_test_fail();							\
@@ -226,7 +277,7 @@
   } while(0)
 
 #define g_check_parse_chunks_ok_(parser, chunk1, c1_len, chunk2, c2_len) do {	\
-    HSuspendedParser *s = h_parse_start(parser);			\
+    HSuspendedParser *s = h_parse_start((HParser *)(parser));			\
     if(!s) {								\
       g_test_message("Chunk-wise parsing not available");		\
       g_test_fail();							\
@@ -255,7 +306,7 @@
   } while(0)
 
 #define g_check_parse_chunks_match_(parser, chunk1, c1_len, chunk2, c2_len, result) do { \
-    HSuspendedParser *s = h_parse_start(parser);			\
+    HSuspendedParser *s = h_parse_start((HParser *)(parser));			\
     if(!s) {								\
       g_test_message("Chunk-wise parsing not available");		\
       g_test_fail();							\