diff --git a/src/hammer.cxx b/src/hammer.cxx
index dc2b104517e2c6d5c1958477a7184a9780c92091..1cf38c256d2e6cf8bcd47a3f81c7633913c5bc93 100644
--- a/src/hammer.cxx
+++ b/src/hammer.cxx
@@ -116,37 +116,44 @@ namespace hammer {
     return RepeatN<T>(this, n);
   }
 
-  /*
-  Int64 Int64::in_range(const int64_t lower, const int64_t upper) {
-    return IntRange(Int64(), lower, upper);
+  IntRange<IntResult> Int64::in_range(const int64_t lower, const int64_t upper) {
+    Int64 p = Int64();
+    return IntRange<IntResult>(p, lower, upper);
   }
 
-  Int32 Int32::in_range(const int32_t lower, const int32_t upper) {
-    return IntRange(Int32(), lower, upper);
+  IntRange<IntResult> Int32::in_range(const int32_t lower, const int32_t upper) {
+    Int32 p = Int32();
+    return IntRange<IntResult>(p, lower, upper);
   }
 
-  Int16 Int16::in_range(const int16_t lower, const int16_t upper) {
-    return IntRange(Int16(), lower, upper);
+  IntRange<IntResult> Int16::in_range(const int16_t lower, const int16_t upper) {
+    Int16 p = Int16();
+    return IntRange<IntResult>(p, lower, upper);
   }
 
-  Int8 Int8::in_range(const int8_t lower, const int8_t upper) {
-    return IntRange(Int8(), lower, upper);
+  IntRange<IntResult> Int8::in_range(const int8_t lower, const int8_t upper) {
+    Int8 p = Int8();
+    return IntRange<IntResult>(p, lower, upper);
   }
 
-  Uint64 Uint64::in_range(const uint64_t lower, const uint64_t upper) {
-    return IntRange(Uint64(), lower, upper);
+  IntRange<UintResult> Uint64::in_range(const uint64_t lower, const uint64_t upper) {
+    Uint64 p = Uint64();
+    return IntRange<UintResult>(p, lower, upper);
   }
 
-  Uint32 Uint32::in_range(const uint32_t lower, const uint32_t upper) {
-    return IntRange(Uint32(), lower, upper);
+  IntRange<UintResult> Uint32::in_range(const uint32_t lower, const uint32_t upper) {
+    Uint32 p = Uint32();
+    return IntRange<UintResult>(p, lower, upper);
   }
 
-  Uint16 Uint16::in_range(const uint16_t lower, const uint16_t upper) {
-    return IntRange(Uint16(), lower, upper);
+  IntRange<UintResult> Uint16::in_range(const uint16_t lower, const uint16_t upper) {
+    Uint16 p = Uint16();
+    return IntRange<UintResult>(p, lower, upper);
   }
 
-  Uint8 Uint8::in_range(const uint8_t lower, const uint8_t upper) {
-    return IntRange(Uint8(), lower, upper);
+  IntRange<UintResult> Uint8::in_range(const uint8_t lower, const uint8_t upper) {
+    Uint8 p = Uint8();
+    return IntRange<UintResult>(p, lower, upper);
   }
-  */
+  
 }
diff --git a/src/hammer.hxx b/src/hammer.hxx
index 0baee866f0cb4be0cc58a701c1c52588194850bb..287ca21b6a2d3a272a33446b23b2ef1ea4c5c45d 100644
--- a/src/hammer.hxx
+++ b/src/hammer.hxx
@@ -72,6 +72,7 @@ namespace hammer {
   template<class T> class Many1;
   template<class T> class Optional;
   template<class T> class RepeatN;
+  template<class T> class IntRange;
 
   template<typename T>
   class Parser {
@@ -83,9 +84,11 @@ namespace hammer {
     RepeatN<T> many(size_t n);
     Optional<T> optional();
     RepeatN<T> operator[](size_t n);
-    HParser* parser() { return _parser; }
-    HParser* _parser;
+    const HParser* parser() { return _parser; }
+  protected:
+    const HParser* _parser;
     Parser() { }
+    //    Parser(const Parser &p) : _parser(p.parser()) { } // hopefully we don't need a copy constructor...
   };
 
   class Token : public Parser<BytesResult> {
@@ -118,16 +121,6 @@ namespace hammer {
     uint8_t _lower, _upper;
   };
 
-  class IntRange : public Parser<IntResult> {
-  public:
-    IntRange(Parser &p, const int64_t lower, const int64_t upper) : _p(p), _lower(lower), _upper(upper) {
-      _parser = h_int_range(p.parser(), lower, upper);
-    }
-  private:
-    Parser _p;
-    int64_t _lower, _upper;
-  };
-
   class SignedBits : public Parser<IntResult> {
   public:
     SignedBits(size_t len) : _len(len) {
@@ -151,7 +144,7 @@ namespace hammer {
     Int64() {
       _parser = h_int64();
     }
-    Int64 in_range(const int64_t lower, const int64_t upper);
+    IntRange<IntResult> in_range(const int64_t lower, const int64_t upper);
   };
 
   class Int32 : public Parser<IntResult> {
@@ -159,7 +152,7 @@ namespace hammer {
     Int32() {
       _parser = h_int32();
     }
-    Int32 in_range(const int32_t lower, const int32_t upper);
+    IntRange<IntResult> in_range(const int32_t lower, const int32_t upper);
   };
 
   class Int16 : public Parser<IntResult> {
@@ -167,7 +160,7 @@ namespace hammer {
     Int16() { 
       _parser = h_int16();
     }
-    Int16 in_range(const int16_t lower, const int16_t upper);
+    IntRange<IntResult> in_range(const int16_t lower, const int16_t upper);
   };
 
   class Int8 : public Parser<IntResult> {
@@ -175,7 +168,7 @@ namespace hammer {
     Int8() {
       _parser = h_int8();
     }
-    Int8 in_range(const int8_t lower, const int8_t upper);
+    IntRange<IntResult> in_range(const int8_t lower, const int8_t upper);
   };
 
   class Uint64 : public Parser<UintResult> {
@@ -183,7 +176,7 @@ namespace hammer {
     Uint64() {
       _parser = h_uint64(); 
     }
-    Uint64 in_range(const uint64_t lower, const uint64_t upper);
+    IntRange<UintResult> in_range(const uint64_t lower, const uint64_t upper);
   };
 
   class Uint32 : public Parser<UintResult> {
@@ -191,7 +184,7 @@ namespace hammer {
     Uint32() { 
       _parser = h_uint32();
     }
-    Uint32 in_range(const uint32_t lower, const uint32_t upper);
+    IntRange<UintResult> in_range(const uint32_t lower, const uint32_t upper);
   };
 
   class Uint16 : public Parser<UintResult> {
@@ -199,7 +192,7 @@ namespace hammer {
     Uint16() {
       _parser = h_uint16(); 
     }
-    Uint16 in_range(const uint16_t lower, const uint16_t upper);
+    IntRange<UintResult> in_range(const uint16_t lower, const uint16_t upper);
   };
 
   class Uint8 : public Parser<UintResult> {
@@ -207,7 +200,18 @@ namespace hammer {
     Uint8() { 
       _parser = h_uint8();
     } 
-    Uint8 in_range(const uint8_t lower, const uint8_t upper);
+    IntRange<UintResult> in_range(const uint8_t lower, const uint8_t upper);
+  };
+
+  template<class T>
+  class IntRange : public Parser<T> {
+  public:
+    IntRange(Parser<T> &p, const int64_t lower, const int64_t upper) : _p(p), _lower(lower), _upper(upper) {
+      this->_parser = h_int_range(p.parser(), lower, upper);
+    }
+  private:
+    Parser<T> _p;
+    int64_t _lower, _upper;
   };
 
   template<class T>
@@ -299,12 +303,13 @@ namespace hammer {
   };
 
   class Sequence : public Parser<SequenceResult> {
+    friend class Parser;
   public:
     Sequence(list<Parser> &ps) : _ps(ps) { 
       void *parsers[ps.size()];
       size_t i = 0;
       for (list<Parser>::iterator it=ps.begin(); it != ps.end(); ++it, ++i) {
-	parsers[i] = it->parser();
+	parsers[i] = const_cast<HParser*>(it->parser());
       }
       _parser = h_sequence__a(parsers);
     }
@@ -319,7 +324,7 @@ namespace hammer {
       void *parsers[ps.size()];
       size_t i = 0;
       for (list<Parser<SequenceResult> >::iterator it=ps.begin(); it != ps.end(); ++it, ++i) {
-	parsers[i] = it->parser();
+	parsers[i] = const_cast<HParser*>(it->parser());
       }
       _parser = h_choice__a(parsers);      
     }