diff --git a/pdf.c b/pdf.c
index 23cf121c93cbf2f07d6ddd74150de47f6180baf8..049e2f1cf7e1f2a527239728e6c1b285ffbb3336 100644
--- a/pdf.c
+++ b/pdf.c
@@ -455,6 +455,32 @@ act_dict_(const HParseResult *p, void *env)
 
 #define act_array_ h_act_flatten
 
+HParsedToken *
+act_longlength(const HParseResult *p, void *env)
+{
+	uint8_t length = H_CAST_UINT(p->ast);
+	uint8_t finallength = 257-length;
+
+	return H_MAKE_UINT(finallength);
+}
+
+HParsedToken *
+act_longrun(const HParseResult *p, void *env)
+{
+	HCountedArray *seq = H_CAST_SEQ(p->ast);
+	HParsedToken **elements = h_seq_elements(p->ast);
+	HParsedToken *res = H_MAKE_SEQ();
+
+	uint8_t length = H_CAST_UINT(elements[0]);
+	uint8_t data = H_CAST_UINT(elements[1]);
+
+	for (size_t len = 0; len < length; ++len)
+	{
+		h_seq_snoc(res, H_MAKE_UINT(data));
+	}
+
+	return res;
+}
 
 /*
  * input grammar
@@ -466,6 +492,8 @@ HParser *p_startxref;
 HParser *p_xref;
 HParser *p_objdef;
 
+HParser *p_rldstring;
+
 /* continuations for h_bind() */
 HParser *kstream(HAllocator *, const HParsedToken *, void *);
 HParser *kxstream(HAllocator *, const HParsedToken *, void *);
@@ -689,6 +717,24 @@ init_parser(struct Env *aux)
 	p_return_1 = h_action(epsilon, act_return_uint, (void *)1);
 }
 
+void
+init_runlengthdecode_parser(struct Env *env)
+{
+	H_RULE(rldeod, h_ch(0x80));
+	H_ARULE(longlength, h_ch_range(0x81, 0xFF));
+	H_RULE(shortlength, h_ch_range(0x1, 0x7F));
+
+	H_RULE(shortdata, h_uint8());
+	H_RULE(longdata, h_uint8());
+
+	H_RULE(shortrun, h_length_value(shortlength, shortdata));
+	H_ARULE(longrun, SEQ(longlength, longdata));
+
+	H_RULE(rldstring, SEQ(CHX(shortrun, longrun), IGN(rldeod)));
+
+	p_rldstring = rldstring;
+}
+
 
 /*
  * lookup and resolution of indirect references