diff --git a/pdf.c b/pdf.c
index eb15af47933d4e19ac0f55b6fa93235504322fb3..895f7d03e00a848ddab9c968f2810cb7a5d620e1 100644
--- a/pdf.c
+++ b/pdf.c
@@ -296,8 +296,8 @@ act_ref(const HParseResult *p, void *u)
 {
 	Ref *r = H_ALLOC(Ref);
 
-	r->nr = H_FIELD_UINT(0);
-	r->gen = H_FIELD_UINT(1);
+	r->nr = H_FIELD_UINT(0, 0);
+	r->gen = H_FIELD_UINT(0, 1);
 
 	return H_MAKE(Ref, r);
 }
@@ -394,7 +394,7 @@ act_xrstment(const HParseResult *p, void *u)
 /*
  * return a cross-reference stream in the same form as xref sections.
  *
- * p = (pnat nat (dict [HParseResult: xrefs]))
+ * p = ((pnat nat) (dict [HParseResult: xrefs]))
  * result = (xrefs dict)
  */
 HParsedToken *
@@ -404,8 +404,8 @@ act_xrstm(const HParseResult *p, void *u)
 	HParsedToken *tok;
 	HParseResult *res;
 
-	dict = H_INDEX_TOKEN(p->ast, 2, 0);
-	res = H_FIELD(HParseResult, 2, 1);	// XXX free this
+	dict = H_INDEX_TOKEN(p->ast, 1, 0);
+	res = H_FIELD(HParseResult, 1, 1);	// XXX free this
 	xrefs = res->ast;
 
 	tok = H_MAKE_SEQN(2);
@@ -418,12 +418,12 @@ act_xrstm(const HParseResult *p, void *u)
 /*
  * validate the /Type field on a cross-reference stream.
  *
- * p = pnat nat (dict offs offs)
+ * p = ((pnat nat) (dict offs offs))
  */
 bool
 validate_xrstm(HParseResult *p, void *u)
 {
-	const Dict *tdict = H_FIELD(Dict, 2, 0);
+	const Dict *tdict = H_FIELD(Dict, 1, 0);
 	const HParsedToken *v = dictentry(tdict, "Type");
 
 #if 0
@@ -527,7 +527,7 @@ init_parser(struct Env *aux)
 	H_RULE(empty,	SEQ(epsilon));
 	H_ARULE(nat,	TOK(h_many1(digit)));
 	H_ARULE(pnat,	TOK(SEQ(h_many(zero), pdigit, h_many(digit))));
-	//H_RULE(npair,	SEQ(pnat, wel,ws, nat));
+	H_RULE(npair,	SEQ(pnat, wel,ws, nat));
 
 #define OPT(X)	CHX(X, epsilon)
 
@@ -535,7 +535,7 @@ init_parser(struct Env *aux)
 	 * objects
 	 */
 	
-	H_ARULE(ref,	SEQ(pnat, nat, KW("R")));
+	H_ARULE(ref,	SEQ(npair, KW("R")));
 	H_RULE(null,	KW("null"));
 	H_RULE(boole,	CHX(TOK(LIT("true")), TOK(LIT("false"))));
 
@@ -603,11 +603,11 @@ init_parser(struct Env *aux)
 
 	/* body */
 	H_RULE(indobj,	CHX(stream, obj));
-	H_RULE(objdef,	SEQ(pnat, nat, KW("obj"), ws, indobj, KW("endobj")));
+	H_RULE(objdef,	SEQ(npair, KW("obj"), ws, indobj, KW("endobj")));
 	H_RULE(body,	h_many(objdef));
 
 	/* for object streams */
-	//H_RULE(osidx,	h_many(SEQ(pnat, nat)));
+	//H_RULE(osidx,	MANY_WS(npair));
 
 	/* cross-reference section */
 	H_RULE(xreol,	CHX(SEQ(sp, cr), SEQ(sp, lf), crlf));
@@ -623,7 +623,7 @@ init_parser(struct Env *aux)
 
 	/* cross-reference streams */
 	H_RULE(xstream,	h_bind(stmbeg, kxstream, aux));
-	H_AVRULE(xrstm,	SEQ(pnat, nat, KW("obj"), ws, xstream));
+	H_AVRULE(xrstm,	SEQ(npair, KW("obj"), ws, xstream));
 		// XXX skip however much we consumed and check for "endstream endobj"?
 
 	/* trailer */
@@ -702,9 +702,10 @@ parse_obj(struct Env *aux, size_t nr, size_t gen, size_t offset)
 		return NULL;
 	}
 	assert(res->ast != NULL && res->ast->token_type == TT_SEQUENCE);
+	/* res->ast = ((nr gen) obj) */
 
-	def_nr = H_INDEX_UINT(res->ast, 0);
-	def_gen = H_INDEX_UINT(res->ast, 1);
+	def_nr = H_INDEX_UINT(res->ast, 0, 0);
+	def_gen = H_INDEX_UINT(res->ast, 0, 1);
 	if (def_nr != nr || def_gen != gen) {
 		fprintf(stderr, "%s: object ID mismatch at position %zu "
 		    "(%#zx): sought %zu %zu, found %zu %zu.\n", aux->infile,
@@ -712,7 +713,7 @@ parse_obj(struct Env *aux, size_t nr, size_t gen, size_t offset)
 		return NULL;
 	}
 
-	return H_INDEX_TOKEN(res->ast, 2);
+	return H_INDEX_TOKEN(res->ast, 1);
 }
 
 const HParsedToken *