diff --git a/src/parsers/optional.c b/src/parsers/optional.c
index 9c8c991a41527a2147082c1816f07406c7da393f..9ba2f198c9c77a93ace611f383103227f1826b4c 100644
--- a/src/parsers/optional.c
+++ b/src/parsers/optional.c
@@ -22,9 +22,50 @@ static bool opt_isValidCF(void *env) {
   return p->vtable->isValidCF(p->env);
 }
 
+static const HParsedToken* reshape_optional(const HParseResult *p) {
+  assert(p->ast);
+  assert(p->ast->token_type == TT_SEQUENCE);
+  assert(p->ast->seq->used > 0);
+
+  HParsedToken *res = p->ast->seq->elements[0];
+  if(res)
+    return res;
+
+  HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
+  ret->token_type = TT_NONE;
+  return ret;
+}
+
 static HCFChoice* desugar_optional(HAllocator *mm__, void *env) {
   HParser *p = (HParser*) env;
-  return h_desugar(mm__, p);
+
+  /* optional(A) =>
+         S  -> A
+            -> \epsilon
+  */
+
+  HCFChoice *ret = h_new(HCFChoice, 1);
+  HCFChoice *a   = h_desugar(mm__, p);
+  HCFChoice *eps = desugar_epsilon(mm__, NULL);
+
+  ret->type = HCF_CHOICE;
+  ret->seq = h_new(HCFSequence*, 3);  /* enough for 2 productions */
+
+  ret->seq[0] = h_new(HCFSequence, 1);
+  ret->seq[0]->items = h_new(HCFChoice*, 2);
+  ret->seq[0]->items[0] = a;
+  ret->seq[0]->items[1] = NULL;
+
+  ret->seq[1] = h_new(HCFSequence, 1);
+  ret->seq[1]->items = h_new(HCFChoice*, 2);
+  ret->seq[1]->items[0] = eps;
+  ret->seq[1]->items[1] = NULL;
+
+  ret->seq[2] = NULL;
+
+  ret->reshape = reshape_optional;
+
+  return ret;
 }
 
 static bool h_svm_action_optional(HArena *arena, HSVMContext *ctx, void *env) {