diff --git a/src/hammer.c b/src/hammer.c
index 4b177a8f11971ee4d7434cd8340d8fbb89575fc6..1114acb25f41d86fbcd5bbd8773e1a495ea0e8a5 100644
--- a/src/hammer.c
+++ b/src/hammer.c
@@ -344,8 +344,10 @@ typedef struct {
 static parse_result_t* parse_action(void *env, parse_state_t *state) {
   parse_action_t *a = (parse_action_t*)env;
   if (a->p && a->action) {
-    parsed_token_t *tok = a->action(do_parse(a->p, state));
-    return make_result(state, tok);
+    parse_result_t *tmp = do_parse(a->p, state);
+    //parsed_token_t *tok = a->action(do_parse(a->p, state));
+    const parsed_token_t *tok = a->action(tmp);
+    return make_result(state, (parsed_token_t*)tok);
   } else // either the parser's missing or the action's missing
     return NULL;
 }
@@ -1046,21 +1048,35 @@ static void test_whitespace(void) {
 
 #include <ctype.h>
 
-parsed_token_t* upcase(parse_result_t *p) {
+const parsed_token_t* upcase(parse_result_t *p) {
   switch(p->ast->token_type) {
   case TT_SEQUENCE:
-    for (size_t i=0; i<p->ast->seq->used; ++i) {
-      upcase((parse_result_t*)p->ast->seq->elements[i]);
-      return (parsed_token_t*)p->ast;
+    {
+      parsed_token_t *ret = a_new_(p->arena, parsed_token_t, 1);
+      counted_array_t *seq = carray_new_sized(p->arena, p->ast->seq->used);
+      ret->token_type = TT_SEQUENCE;
+      for (size_t i=0; i<p->ast->seq->used; ++i) {
+	if (TT_UINT == ((parsed_token_t*)p->ast->seq->elements[i])->token_type) {
+	  parsed_token_t *tmp = a_new_(p->arena, parsed_token_t, 1);
+	  tmp->token_type = TT_UINT;
+	  tmp->uint = toupper(((parsed_token_t*)p->ast->seq->elements[i])->uint);
+	  carray_append(seq, tmp);
+	} else {
+	  carray_append(seq, p->ast->seq->elements[i]);
+	}
+      }
+      ret->seq = seq;
+      return (const parsed_token_t*)ret;
     }
   case TT_UINT:
     {
-      parsed_token_t *ret = (parsed_token_t*)p->ast;
-      ret->uint = toupper(ret->uint);
-      return ret;
+      parsed_token_t *ret = a_new_(p->arena, parsed_token_t, 1);
+      ret->token_type = TT_UINT;
+      ret->uint = toupper(p->ast->uint);
+      return (const parsed_token_t*)ret;
     }
   default:
-    return (parsed_token_t*)p->ast;
+    return p->ast;
   }
 }
 
@@ -1074,8 +1090,8 @@ static void test_action(void) {
 					    NULL), 
 				   upcase);
 
-  g_check_parse_ok(action_, "ab", 2, "(u0x41, u0x42)");
-  g_check_parse_ok(action_, "AB", 2, "(u0x41, u0x42)");
+  g_check_parse_ok(action_, "ab", 2, "(u0x41 u0x42)");
+  g_check_parse_ok(action_, "AB", 2, "(u0x41 u0x42)");
 }
 
 static void test_not_in(void) {
diff --git a/src/hammer.h b/src/hammer.h
index 95da5e2f6c60d96db04964e6f3e65c573235c64b..a0b93e569bb85a394e248fba9bcf3a939afe9607 100644
--- a/src/hammer.h
+++ b/src/hammer.h
@@ -87,7 +87,7 @@ typedef struct parse_result {
  * say, structs) and stuff values for them into the void* in the 
  * tagged union in parsed_token_t. 
  */
-typedef parsed_token_t* (*action_t)(parse_result_t *p);
+typedef const parsed_token_t* (*action_t)(parse_result_t *p);
 
 /**
  * Type of a boolean attribute-checking function, used in the 
diff --git a/src/pprint.c b/src/pprint.c
index 250ecfbef104842374aaf98308984183d50240ef..ac0d02db611f7fbe1c91d5ca4d3397fc3d738558 100644
--- a/src/pprint.c
+++ b/src/pprint.c
@@ -94,6 +94,10 @@ static inline void append_buf_c(struct result_buf *buf, char v) {
 static void unamb_sub(const parsed_token_t* tok, struct result_buf *buf) {
   char* tmpbuf;
   int len;
+  if (!tok) {
+    append_buf(buf, "NULL", 4);
+    return;
+  }
   switch (tok->token_type) {
   case TT_NONE:
     append_buf(buf, "null", 4);