diff --git a/src/internal.h b/src/internal.h
index 6a7aba9b6d315a9d4a863a98e04fca7f424c0b20..edb0c21751be9a5e356674f50d59ee53d6d70260 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -225,6 +225,15 @@ long long h_read_bits(HInputStream* state, int count, char signed_p);
 HParseResult* h_do_parse(const HParser* parser, HParseState *state);
 void put_cached(HParseState *ps, const HParser *p, HParseResult *cached);
 
+static inline
+HParser *h_new_parser(HAllocator *mm__, const HParserVtable *vt, void *env) {
+  HParser *p = h_new(HParser, 1);
+  memset(p, 0, sizeof(HParser));
+  p->vtable = vt;
+  p->env = env;
+  return p;
+}
+
 HCFChoice *h_desugar(HAllocator *mm__, const HParser *parser);
 
 HCountedArray *h_carray_new_sized(HArena * arena, size_t size);
diff --git a/src/parsers/action.c b/src/parsers/action.c
index ea409d76148aea9e27af4fdea774a7b0e9d6e395..d6bcc0c984b26acdac12bbb42bad6f28647bc999 100644
--- a/src/parsers/action.c
+++ b/src/parsers/action.c
@@ -56,11 +56,8 @@ const HParser* h_action(const HParser* p, const HAction a) {
 }
 
 const HParser* h_action__m(HAllocator* mm__, const HParser* p, const HAction a) {
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &action_vt;
   HParseAction *env = h_new(HParseAction, 1);
   env->p = p;
   env->action = a;
-  res->env = (void*)env;
-  return res;
+  return h_new_parser(mm__, &action_vt, env);
 }
diff --git a/src/parsers/and.c b/src/parsers/and.c
index 650a11a15e75790362713d2d7b268f3e1746df05..f5fadb71790fb57e06265bd6f3a6eb89f9e6a58d 100644
--- a/src/parsers/and.c
+++ b/src/parsers/and.c
@@ -30,8 +30,5 @@ const HParser* h_and(const HParser* p) {
 }
 const HParser* h_and__m(HAllocator* mm__, const HParser* p) {
   // zero-width postive lookahead
-  HParser *res = h_new(HParser, 1);
-  res->env = (void*)p;
-  res->vtable = &and_vt;
-  return res;
+  return h_new_parser(mm__, &and_vt, (void *)p);
 }
diff --git a/src/parsers/attr_bool.c b/src/parsers/attr_bool.c
index 78bd30befdec06149418f22b4e99c08fdd029aff..c365f00da125da188ee616d15251e227d194b60a 100644
--- a/src/parsers/attr_bool.c
+++ b/src/parsers/attr_bool.c
@@ -59,11 +59,8 @@ const HParser* h_attr_bool(const HParser* p, HPredicate pred) {
   return h_attr_bool__m(&system_allocator, p, pred);
 }
 const HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred) { 
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &attr_bool_vt;
   HAttrBool *env = h_new(HAttrBool, 1);
   env->p = p;
   env->pred = pred;
-  res->env = (void*)env;
-  return res;
+  return h_new_parser(mm__, &attr_bool_vt, env);
 }
diff --git a/src/parsers/bits.c b/src/parsers/bits.c
index ee3dde9a6d0835980d546e3859adfef2f7800cc5..54602eaffd742a6fa86b4045b8c6a3e0af763782 100644
--- a/src/parsers/bits.c
+++ b/src/parsers/bits.c
@@ -54,10 +54,7 @@ const HParser* h_bits__m(HAllocator* mm__, size_t len, bool sign) {
   struct bits_env *env = h_new(struct bits_env, 1);
   env->length = len;
   env->signedp = sign;
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &bits_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &bits_vt, env);
 }
 
 #define SIZED_BITS(name_pre, len, signedp) \
diff --git a/src/parsers/butnot.c b/src/parsers/butnot.c
index c0e3b41ee62e87aa9257d625ebc3f9ed36d80dd7..3dec32272ecf1a4e62c88aa3f6556d4c3b4b5cd6 100644
--- a/src/parsers/butnot.c
+++ b/src/parsers/butnot.c
@@ -52,9 +52,8 @@ const HParser* h_butnot(const HParser* p1, const HParser* p2) {
 }
 const HParser* h_butnot__m(HAllocator* mm__, const HParser* p1, const HParser* p2) {
   HTwoParsers *env = h_new(HTwoParsers, 1);
-  env->p1 = p1; env->p2 = p2;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &butnot_vt; ret->env = (void*)env;
-  return ret;
+  env->p1 = p1;
+  env->p2 = p2;
+  return h_new_parser(mm__, &butnot_vt, env);
 }
 
diff --git a/src/parsers/ch.c b/src/parsers/ch.c
index f0e91c199f8175be232c75768f56c93ea1dc790b..82b5e9ac115c96af4e744137864e86d3d86d1ddc 100644
--- a/src/parsers/ch.c
+++ b/src/parsers/ch.c
@@ -31,8 +31,5 @@ const HParser* h_ch(const uint8_t c) {
   return h_ch__m(&system_allocator, c);
 }
 const HParser* h_ch__m(HAllocator* mm__, const uint8_t c) {  
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &ch_vt;
-  ret->env = (void*)(unsigned long)(c);
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &ch_vt, (void *)(uintptr_t)c);
 }
diff --git a/src/parsers/charset.c b/src/parsers/charset.c
index 5a76239fe77ef9b6141ce21bf366f43139b588b2..858d299cde14e4b28e3318f99d031e104d7b1445 100644
--- a/src/parsers/charset.c
+++ b/src/parsers/charset.c
@@ -33,27 +33,21 @@ const HParser* h_ch_range(const uint8_t lower, const uint8_t upper) {
   return h_ch_range__m(&system_allocator, lower, upper);
 }
 const HParser* h_ch_range__m(HAllocator* mm__, const uint8_t lower, const uint8_t upper) {
-  HParser *ret = h_new(HParser, 1);
   HCharset cs = new_charset(mm__);
   for (int i = 0; i < 256; i++)
     charset_set(cs, i, (lower <= i) && (i <= upper));
-  ret->vtable = &charset_vt;
-  ret->env = (void*)cs;
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &charset_vt, cs);
 }
 
 
 static const HParser* h_in_or_not__m(HAllocator* mm__, const uint8_t *options, size_t count, int val) {
-  HParser *ret = h_new(HParser, 1);
   HCharset cs = new_charset(mm__);
   for (size_t i = 0; i < 256; i++)
     charset_set(cs, i, 1-val);
   for (size_t i = 0; i < count; i++)
     charset_set(cs, options[i], val);
 
-  ret->vtable = &charset_vt;
-  ret->env = (void*)cs;
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &charset_vt, cs);
 }
 
 const HParser* h_in(const uint8_t *options, size_t count) {
diff --git a/src/parsers/choice.c b/src/parsers/choice.c
index 88e908bdb3e99591bccd33345fc5474dc50939ce..28394058b9c9e531b02a7e7a5ae1c5e203218a54 100644
--- a/src/parsers/choice.c
+++ b/src/parsers/choice.c
@@ -103,8 +103,6 @@ const HParser* h_choice__mv(HAllocator* mm__, const HParser* p, va_list ap_) {
   va_end(ap);
 
   s->len = len;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &choice_vt; ret->env = (void*)s;
-  return ret;
+  return h_new_parser(mm__, &choice_vt, s);
 }
 
diff --git a/src/parsers/difference.c b/src/parsers/difference.c
index 35287590a9892b16a3efedaca8ca79d0cd3c32ea..9302490793f859f85c69759ab832d899bbe8678d 100644
--- a/src/parsers/difference.c
+++ b/src/parsers/difference.c
@@ -51,8 +51,7 @@ const HParser* h_difference(const HParser* p1, const HParser* p2) {
 }
 const HParser* h_difference__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { 
   HTwoParsers *env = h_new(HTwoParsers, 1);
-  env->p1 = p1; env->p2 = p2;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &difference_vt; ret->env = (void*)env;
-  return ret;
+  env->p1 = p1;
+  env->p2 = p2;
+  return h_new_parser(mm__, &difference_vt, env);
 }
diff --git a/src/parsers/end.c b/src/parsers/end.c
index 2a458e526aa25642c1c48aace62daa203879dc29..05aeaafb3eee5928f84619249f43bb33b8823063 100644
--- a/src/parsers/end.c
+++ b/src/parsers/end.c
@@ -29,8 +29,5 @@ const HParser* h_end_p() {
 }
 
 const HParser* h_end_p__m(HAllocator* mm__) { 
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &end_vt;
-  ret->env = NULL;
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &end_vt, NULL);
 }
diff --git a/src/parsers/ignore.c b/src/parsers/ignore.c
index 6ae2803dd21d8f58aef7606d8a01ba5c56f2784b..33bccd0154c000f1bea5316b7bde3d5fd5513828 100644
--- a/src/parsers/ignore.c
+++ b/src/parsers/ignore.c
@@ -36,8 +36,5 @@ const HParser* h_ignore(const HParser* p) {
   return h_ignore__m(&system_allocator, p);
 }
 const HParser* h_ignore__m(HAllocator* mm__, const HParser* p) {
-  HParser* ret = h_new(HParser, 1);
-  ret->vtable = &ignore_vt;
-  ret->env = (void*)p;
-  return ret;
+  return h_new_parser(mm__, &ignore_vt, (void *)p);
 }
diff --git a/src/parsers/ignoreseq.c b/src/parsers/ignoreseq.c
index 2adffc6c7d40abcc801db587a930d1184a1e876d..822920b1b1ad18450addb04aa7f63ba4ebd2f332 100644
--- a/src/parsers/ignoreseq.c
+++ b/src/parsers/ignoreseq.c
@@ -81,10 +81,7 @@ static const HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const H
   seq->len = 2;
   seq->which = which;
 
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &ignoreseq_vt;
-  ret->env = (void*)seq;
-  return ret;
+  return h_new_parser(mm__, &ignoreseq_vt, seq);
 }
 
 const HParser* h_left(const HParser* p, const HParser* q) {
@@ -114,8 +111,5 @@ const HParser* h_middle__m(HAllocator* mm__, const HParser* p, const HParser* x,
   seq->len = 3;
   seq->which = 1;
 
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &ignoreseq_vt;
-  ret->env = (void*)seq;
-  return ret;
+  return h_new_parser(mm__, &ignoreseq_vt, seq);
 }
diff --git a/src/parsers/indirect.c b/src/parsers/indirect.c
index c6935489042953122d9069625131ed2f34b4c64e..77227d2c501d49db84599106d41a066b05aab940 100644
--- a/src/parsers/indirect.c
+++ b/src/parsers/indirect.c
@@ -32,8 +32,5 @@ HParser* h_indirect() {
   return h_indirect__m(&system_allocator);
 }
 HParser* h_indirect__m(HAllocator* mm__) {
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &indirect_vt;
-  res->env = NULL;
-  return res;
+  return h_new_parser(mm__, &indirect_vt, NULL);
 }
diff --git a/src/parsers/int_range.c b/src/parsers/int_range.c
index 64450da371d77dc6c92e1e736ab5244c923484ed..50149b2e5e271368501b9355a33d0b7ef94bc4d4 100644
--- a/src/parsers/int_range.c
+++ b/src/parsers/int_range.c
@@ -143,8 +143,5 @@ const HParser* h_int_range__m(HAllocator* mm__, const HParser *p, const int64_t
   r_env->p = p;
   r_env->lower = lower;
   r_env->upper = upper;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &int_range_vt;
-  ret->env = (void*)r_env;
-  return ret;
+  return h_new_parser(mm__, &int_range_vt, r_env);
 }
diff --git a/src/parsers/many.c b/src/parsers/many.c
index f4829ebc4b20094b3b8fc1565d1fa5e6ec959324..2ce89f13071fccb3bf00a7e933fbb6257753f696 100644
--- a/src/parsers/many.c
+++ b/src/parsers/many.c
@@ -123,75 +123,60 @@ const HParser* h_many(const HParser* p) {
   return h_many__m(&system_allocator, p);
 }
 const HParser* h_many__m(HAllocator* mm__, const HParser* p) {
-  HParser *res = h_new(HParser, 1);
   HRepeat *env = h_new(HRepeat, 1);
   env->p = p;
   env->sep = h_epsilon_p__m(mm__);
   env->count = 0;
   env->min_p = true;
-  res->vtable = &many_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &many_vt, env);
 }
 
 const HParser* h_many1(const HParser* p) {
   return h_many1__m(&system_allocator, p);
 }
 const HParser* h_many1__m(HAllocator* mm__, const HParser* p) {
-  HParser *res = h_new(HParser, 1);
   HRepeat *env = h_new(HRepeat, 1);
   env->p = p;
   env->sep = h_epsilon_p__m(mm__);
   env->count = 1;
   env->min_p = true;
-  res->vtable = &many_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &many_vt, env);
 }
 
 const HParser* h_repeat_n(const HParser* p, const size_t n) {
   return h_repeat_n__m(&system_allocator, p, n);
 }
 const HParser* h_repeat_n__m(HAllocator* mm__, const HParser* p, const size_t n) {
-  HParser *res = h_new(HParser, 1);
   HRepeat *env = h_new(HRepeat, 1);
   env->p = p;
   env->sep = h_epsilon_p__m(mm__);
   env->count = n;
   env->min_p = false;
-  res->vtable = &many_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &many_vt, env);
 }
 
 const HParser* h_sepBy(const HParser* p, const HParser* sep) {
   return h_sepBy__m(&system_allocator, p, sep);
 }
 const HParser* h_sepBy__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
-  HParser *res = h_new(HParser, 1);
   HRepeat *env = h_new(HRepeat, 1);
   env->p = p;
   env->sep = sep;
   env->count = 0;
   env->min_p = true;
-  res->vtable = &many_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &many_vt, env);
 }
 
 const HParser* h_sepBy1(const HParser* p, const HParser* sep) {
   return h_sepBy1__m(&system_allocator, p, sep);
 }
 const HParser* h_sepBy1__m(HAllocator* mm__, const HParser* p, const HParser* sep) {
-  HParser *res = h_new(HParser, 1);
   HRepeat *env = h_new(HRepeat, 1);
   env->p = p;
   env->sep = sep;
   env->count = 1;
   env->min_p = true;
-  res->vtable = &many_vt;
-  res->env = env;
-  return res;
+  return h_new_parser(mm__, &many_vt, env);
 }
 
 typedef struct {
@@ -232,11 +217,8 @@ const HParser* h_length_value(const HParser* length, const HParser* value) {
   return h_length_value__m(&system_allocator, length, value);
 }
 const HParser* h_length_value__m(HAllocator* mm__, const HParser* length, const HParser* value) {
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &length_value_vt;
   HLenVal *env = h_new(HLenVal, 1);
   env->length = length;
   env->value = value;
-  res->env = (void*)env;
-  return res;
+  return h_new_parser(mm__, &length_value_vt, env);
 }
diff --git a/src/parsers/not.c b/src/parsers/not.c
index b0d5a8e1bee95aa2b2b1e212bc02b8ff55ef8f1a..523b92a60d6c9ecc9bc46c0119dbee81554cd61c 100644
--- a/src/parsers/not.c
+++ b/src/parsers/not.c
@@ -26,8 +26,5 @@ const HParser* h_not(const HParser* p) {
   return h_not__m(&system_allocator, p);
 }
 const HParser* h_not__m(HAllocator* mm__, const HParser* p) {
-  HParser *res = h_new(HParser, 1);
-  res->vtable = &not_vt;
-  res->env = (void*)p;
-  return res;
+  return h_new_parser(mm__, &not_vt, (void *)p);
 }
diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c
index ebf0daf48e1ac7dafbac741046bcaf69e4a56072..b204acaef409d063e81d4c1ac075db6990b415a7 100644
--- a/src/parsers/nothing.c
+++ b/src/parsers/nothing.c
@@ -26,7 +26,5 @@ const HParser* h_nothing_p() {
   return h_nothing_p__m(&system_allocator);
 }
 const HParser* h_nothing_p__m(HAllocator* mm__) { 
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &nothing_vt; ret->env = NULL;
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &nothing_vt, NULL);
 }
diff --git a/src/parsers/optional.c b/src/parsers/optional.c
index b8777d3c8c4f56dc2fcf3cffe400a26b2cb61b9b..27199ab2f5aefceb8cade25e7c2fa1c7d4a0dbd2 100644
--- a/src/parsers/optional.c
+++ b/src/parsers/optional.c
@@ -39,9 +39,6 @@ const HParser* h_optional(const HParser* p) {
 const HParser* h_optional__m(HAllocator* mm__, const HParser* p) {
   // TODO: re-add this
   //assert_message(p->vtable != &ignore_vt, "Thou shalt ignore an option, rather than the other way 'round.");
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &optional_vt;
-  ret->env = (void*)p;
-  return ret;
+  return h_new_parser(mm__, &optional_vt, (void *)p);
 }
 
diff --git a/src/parsers/sequence.c b/src/parsers/sequence.c
index dde2a319c9c927daf8bc45af1033661a560c68e3..e5d1da985e7e26921fb4244e6c10777a92209dcd 100644
--- a/src/parsers/sequence.c
+++ b/src/parsers/sequence.c
@@ -107,7 +107,5 @@ const HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) {
   va_end(ap);
 
   s->len = len;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &sequence_vt; ret->env = (void*)s;
-  return ret;
+  return h_new_parser(mm__, &sequence_vt, s);
 }
diff --git a/src/parsers/token.c b/src/parsers/token.c
index 40779b998fc55d3e4ebc41a1d8cd83fb5067a2f3..610a276a49886ae5350749979a0b6a8da7d25d80 100644
--- a/src/parsers/token.c
+++ b/src/parsers/token.c
@@ -50,8 +50,5 @@ const HParser* h_token(const uint8_t *str, const size_t len) {
 const HParser* h_token__m(HAllocator* mm__, const uint8_t *str, const size_t len) { 
   HToken *t = h_new(HToken, 1);
   t->str = (uint8_t*)str, t->len = len;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &token_vt;
-  ret->env = t;
-  return (const HParser*)ret;
+  return h_new_parser(mm__, &token_vt, t);
 }
diff --git a/src/parsers/whitespace.c b/src/parsers/whitespace.c
index 92e5bd0d55e851645b48dfd97b278b4d1aab8213..29e4ec70ea045ab842a5abb855f3325fd373bc43 100644
--- a/src/parsers/whitespace.c
+++ b/src/parsers/whitespace.c
@@ -60,8 +60,5 @@ const HParser* h_whitespace(const HParser* p) {
   return h_whitespace__m(&system_allocator, p);
 }
 const HParser* h_whitespace__m(HAllocator* mm__, const HParser* p) {
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &whitespace_vt;
-  ret->env = (void*)p;
-  return ret;
+  return h_new_parser(mm__, &whitespace_vt, (void *)p);
 }
diff --git a/src/parsers/xor.c b/src/parsers/xor.c
index c8dbe3d1dc3a62225f42956fc705c07fb4f5d676..006fd9cbc5d3cb80a6f2f028c13bba4ea404fbe8 100644
--- a/src/parsers/xor.c
+++ b/src/parsers/xor.c
@@ -48,8 +48,7 @@ const HParser* h_xor(const HParser* p1, const HParser* p2) {
 }
 const HParser* h_xor__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { 
   HTwoParsers *env = h_new(HTwoParsers, 1);
-  env->p1 = p1; env->p2 = p2;
-  HParser *ret = h_new(HParser, 1);
-  ret->vtable = &xor_vt; ret->env = (void*)env;
-  return ret;
+  env->p1 = p1;
+  env->p2 = p2;
+  return h_new_parser(mm__, &xor_vt, env);
 }