diff --git a/src/allocator.c b/src/allocator.c
index 2ff5cacaa0e05da47ac851ef1ff71239ed5cde3b..93c94e1de7d79cf35542faf54e67938f5a0d5a4a 100644
--- a/src/allocator.c
+++ b/src/allocator.c
@@ -267,3 +267,32 @@ void h_allocator_stats(HArena *arena, HArenaStats *stats) {
   stats->arena_li_malloc_bytes = arena->arena_li_malloc_bytes;
 #endif
 }
+
+void* h_arena_realloc(HArena *arena, void* ptr, size_t n) {
+  struct arena_link *link;
+  void* ret;
+  size_t ncopy;
+
+  // XXX this is really wasteful, but maybe better than nothing?
+  //
+  // first, we walk the blocks to find our ptr. since we don't know how large
+  // the original allocation was, we must always make a new one and copy as
+  // much data from the old block as there could have been.
+
+  for (link = arena->head; link; link = link->next) {
+    if (ptr >= (void *)link->rest && ptr <= (void *)link->rest + link->used)
+      break;	/* found it */
+  }
+  assert(link != NULL);
+
+  ncopy = (void *)link->rest + link->used - ptr;
+  if (n < ncopy)
+    ncopy = n;
+
+  ret = h_arena_malloc_noinit(arena, n);
+  assert(ret != NULL);
+  memcpy(ret, ptr, ncopy);
+  h_arena_free(arena, ptr);
+
+  return ret;
+}
diff --git a/src/allocator.h b/src/allocator.h
index 06d1e6f59dd32987979079c4a7b01d09b13547e6..8ebde72308997aa5ac56885d1fa5d45078659170 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -55,6 +55,7 @@ HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for def
 
 void* h_arena_malloc_noinit(HArena *arena, size_t count) ATTR_MALLOC(2);
 void* h_arena_malloc(HArena *arena, size_t count) ATTR_MALLOC(2);
+void* h_arena_realloc(HArena *arena, void* ptr, size_t count);
 void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers.
 void h_delete_arena(HArena *arena);
 void h_arena_set_except(HArena *arena, jmp_buf *except);
diff --git a/src/backends/lalr.c b/src/backends/lalr.c
index 7aa6550fd901f0b84435e01045d63bf17d038b7e..e4c00a2e7413e780c1843e2a0df9adcf89bb2edc 100644
--- a/src/backends/lalr.c
+++ b/src/backends/lalr.c
@@ -2,7 +2,7 @@
 #include "contextfree.h"
 #include "lr.h"
 
-
+static const size_t DEFAULT_K = 1;
 
 /* LALR-via-SLR grammar transformation */
 
@@ -275,6 +275,7 @@ HCFChoice *h_desugar_augmented(HAllocator *mm__, HParser *parser)
 
 int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
 {
+  size_t k = params? (uintptr_t)params : DEFAULT_K;
   // generate (augmented) CFG from parser
   // construct LR(0) DFA
   // build LR(0) table
@@ -335,7 +336,7 @@ int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
           if(match_any_production(table, eg, lhs, item->rhs, state)) {
             // the left-hand symbol's follow set is this production's
             // contribution to the lookahead
-            const HStringMap *fs = h_follow(1, eg->grammar, lhs);
+            const HStringMap *fs = h_follow(k, eg->grammar, lhs);
             assert(fs != NULL);
             assert(fs->epsilon_branch == NULL);
             // NB: there is a case where fs can be empty: when reducing by lhs
diff --git a/src/parsers/bind.c b/src/parsers/bind.c
index 87f42330ee8a5a35ef5a026f1060e5937bdc2d16..eac4974480405263d77d5f8ed432d5e728666787 100644
--- a/src/parsers/bind.c
+++ b/src/parsers/bind.c
@@ -21,8 +21,7 @@ static void *aa_alloc(HAllocator *allocator, size_t size)
 static void *aa_realloc(HAllocator *allocator, void *ptr, size_t size)
 {
     HArena *arena = ((ArenaAllocator *)allocator)->arena;
-    assert(((void)"XXX need realloc for arena allocator", 0));
-    return NULL;
+    return h_arena_realloc(arena, ptr, size);
 }
 
 static void aa_free(HAllocator *allocator, void *ptr)
diff --git a/src/t_regression.c b/src/t_regression.c
index 3bf763600962bdcdad6208863ba27f92966195f3..82dacf3546296d55c4e20d7b582fe36a2b63eff7 100644
--- a/src/t_regression.c
+++ b/src/t_regression.c
@@ -608,6 +608,41 @@ static void test_bug60_abnf() {
   free(s);
 }
 
+static void test_bug95_lalr_k_param() {
+
+/*
+ * The LR backends had been left hardcoded to k = 1 and were ignoring the param value
+ * This example compiles for LALR(k) where k = 2
+ * but does not compile for k = 1
+ * This shows that the parameter is being used rather than ignored.
+ * The default value of k when the param == NULL is set to k = 1
+ */
+  HParser *a = h_ch('a');
+  HParser *b = h_ch('b');
+  HParser *c = h_ch('c');
+  HParser *B = h_indirect();
+  HParser *A = h_sequence (a, B, c, NULL);
+  HParser *B_ = h_choice(B, b, NULL);
+  h_bind_indirect(B, B_);
+
+  HParser *p = A;
+
+  if (h_compile(p, PB_LALR, (void *)1) == 0) {
+    g_test_message("should not compile for lalr(1)");
+    g_test_fail();
+  }
+
+  g_check_compilable(p, PB_LALR, 2);
+
+  g_check_parse_match_no_compile(p, "abc",3, "(u0x61 u0x62 u0x63)");
+
+  /* The next test shows that the default works for compile with param == NULL */
+  /* (default is k = 1) */
+
+  g_check_parse_match(h_sequence(a, b, c, NULL), PB_LALR, "abc",3, "(u0x61 u0x62 u0x63)");
+
+}
+
 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);
@@ -626,4 +661,5 @@ void register_regression_tests(void) {
   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);
+  g_test_add_func("/core/regression/bug95_lalrk_param", test_bug95_lalr_k_param);
 }