diff --git a/src/bindings/ruby/lib/hammer.rb b/src/bindings/ruby/lib/hammer.rb
index bb0e2a2dafa4b14a31491730ebd1cb60e25b8694..cfb62dcb768d7614c933d6fceb204e6cff82f6d3 100644
--- a/src/bindings/ruby/lib/hammer.rb
+++ b/src/bindings/ruby/lib/hammer.rb
@@ -16,4 +16,7 @@ parser = Hammer::Parser.build {
 }
 x.bind(Hammer::Parser.token('abd'))
 
+#$p = parser
 $r = parser.parse 'abcabd'
+
+p $r[:ast][:data][:seq].elements.map {|e| e[:data][:bytes].token }
diff --git a/src/bindings/ruby/lib/hammer/internal.rb b/src/bindings/ruby/lib/hammer/internal.rb
index 8f673d4e8e5727e14ec624d3d2cff1d206062f9a..0c462fe2d869ddf05e9fbd5700ce45b650644c6a 100644
--- a/src/bindings/ruby/lib/hammer/internal.rb
+++ b/src/bindings/ruby/lib/hammer/internal.rb
@@ -37,6 +37,11 @@ module Hammer
     class HBytes < FFI::Struct
       layout  :token, :pointer, # uint8_t*
               :len, :size_t
+
+      def token
+        # TODO: Encoding? Should probably be the same encoding as the string the token was created with.
+        return self[:token].read_string(self[:len]) #.force_encoding('UTF-8')
+      end
     end
 
     class HParsedTokenDataUnion < FFI::Union
diff --git a/src/bindings/ruby/lib/hammer/parser.rb b/src/bindings/ruby/lib/hammer/parser.rb
index 1d7a76ed7408ec14fd5d4e2ada80ae1eb9c3a818..c0c1cfc8416d159d28c0689c0cbbd1c1de61d5b7 100644
--- a/src/bindings/ruby/lib/hammer/parser.rb
+++ b/src/bindings/ruby/lib/hammer/parser.rb
@@ -7,10 +7,12 @@ module Hammer
     # name: Name of the parser. Should be a symbol.
     # h_parser: The pointer to the parser as returned by hammer.
     # dont_gc: Pass additional data that's used by the parser and needs to be saved from the garbage collector (at least as long this object lives).
-    def initialize(name, h_parser, dont_gc)
+    def initialize(name, h_parser, dont_gc=[])
       @name = name
       @h_parser = h_parser
-      @dont_gc = dont_gc
+      # Always store as array, so we can easily add stuff later on
+      dont_gc = [dont_gc] unless dont_gc.is_a? Array
+      @dont_gc = dont_gc.dup
     end
 
     attr_reader :name
@@ -24,13 +26,23 @@ module Hammer
       raise ArgumentError, 'expecting a String' unless data.is_a? String # TODO: Not needed, FFI checks that.
 
       result = Hammer::Internal.h_parse(@h_parser, data, data.bytesize)
-      return result unless result.null?
+      if result.null?
+        return nil
+      else
+        # NOTE:
+        # The parse result *must* hold a reference to the parser that created it!
+        # Otherwise, the parser might get garbage-collected while the result is still valid.
+        # Any pointers to token strings will then be invalid.
+        result.instance_variable_set :@parser, self
+        return result
+      end
     end
 
     # Binds an indirect parser.
     def bind(other_parser)
       raise RuntimeError, 'can only bind indirect parsers' unless self.name == :indirect
       Hammer::Internal.h_bind_indirect(self.h_parser, other_parser.h_parser)
+      @dont_gc << other_parser
     end
 
     def self.token(string)