diff --git a/src/bindings/ruby/lib/hammer/parser.rb b/src/bindings/ruby/lib/hammer/parser.rb
index b5d95c87cfff02a09578ce200ed091e51f6afa9a..665b870ae11048772c2ce4a6c115a1869f2005aa 100644
--- a/src/bindings/ruby/lib/hammer/parser.rb
+++ b/src/bindings/ruby/lib/hammer/parser.rb
@@ -40,48 +40,35 @@ module Hammer
       return parser
     end
 
-    def self.sequence(*parsers)
-      args = parsers.flat_map { |p| [:pointer, p.h_parser] }
-      h_parser = Hammer::Internal.h_sequence(*args, :pointer, nil)
-      sub_parsers = parsers # store them so they don't get garbage-collected (probably not needed, though)
-      # TODO: Use (managed?) FFI struct instead of void pointers
-
-      parser = Hammer::Parser.new
-      parser.instance_variable_set :@h_parser, h_parser
-      parser.instance_variable_set :@sub_parsers, sub_parsers
-      return parser
-    end
-
-    def self.choice(*parsers)
-      args = parsers.flat_map { |p| [:pointer, p.h_parser] }
-      h_parser = Hammer::Internal.h_choice(*args, :pointer, nil)
-      sub_parsers = parsers # store them so they don't get garbage-collected (probably not needed, though)
-      # TODO: Use (managed?) FFI struct instead of void pointers
-
-      parser = Hammer::Parser.new
-      parser.instance_variable_set :@h_parser, h_parser
-      parser.instance_variable_set :@sub_parsers, sub_parsers
-      return parser
-    end
-
     # Defines a parser constructor with the given name.
     # Options:
     #   hammer_function: name of the hammer function to call (default: 'h_'+name)
+    #   varargs: Whether the function is taking a variable number of arguments (default: false)
     def self.define_parser(name, options = {})
       hammer_function = options[:hammer_function] || ('h_' + name.to_s)
+      varargs = options[:varargs] || false
 
       # Define a new class method
       define_singleton_method name do |*parsers|
-        #args = parsers.map { |p| p.instance_variable_get :@h_parser }
-        h_parser = Hammer::Internal.send hammer_function, *parsers.map(&:h_parser)
+        if varargs
+          args = parsers.flat_map { |p| [:pointer, p.h_parser] }
+          args += [:pointer, nil]
+        else
+          args = parsers.map(&:h_parser)
+        end
+        h_parser = Hammer::Internal.send hammer_function, *args
 
         parser = Hammer::Parser.new
         parser.instance_variable_set :@h_parser, h_parser
+        parser.instance_variable_set :@sub_parsers, parsers # store sub parsers to prevent them from being garbage-collected
         return parser
       end
     end
     private_class_method :define_parser
 
+    define_parser :sequence, varargs: true
+    define_parser :choice, varargs: true
+
     define_parser :int64
     define_parser :int32
     define_parser :int16