diff --git a/src/bindings/ruby/lib/hammer.rb b/src/bindings/ruby/lib/hammer.rb index cfb62dcb768d7614c933d6fceb204e6cff82f6d3..63ac2c79d305688e4080bc07bf354285fcc964a9 100644 --- a/src/bindings/ruby/lib/hammer.rb +++ b/src/bindings/ruby/lib/hammer.rb @@ -20,3 +20,25 @@ x.bind(Hammer::Parser.token('abd')) $r = parser.parse 'abcabd' p $r[:ast][:data][:seq].elements.map {|e| e[:data][:bytes].token } + + +h = Hammer::Parser +parser = + h.many( + h.action(h.uint8) { |r| + p "TT=#{r[:ast][:token_type]}, value=#{r[:ast][:data][:uint]}" + r[:ast][:data][:uint] *= 2 + r[:ast] if r[:ast][:data][:uint] % 3 == 0 + }) + +#parser = Hammer::Parser.build { +# many { +# uint8 +# action { |r| +# p r +# r[:ast] +# } +# } +#} +$r = parser.parse 'abcdefgh' +p $r[:ast][:data][:seq].elements.map {|e| e[:data][:uint]} diff --git a/src/bindings/ruby/lib/hammer/internal.rb b/src/bindings/ruby/lib/hammer/internal.rb index 12d797f5a8007a1cfd43e3ca1b7848c7bc5a6baa..bceff326c54a8699017a3a9200107336e6627b8a 100644 --- a/src/bindings/ruby/lib/hammer/internal.rb +++ b/src/bindings/ruby/lib/hammer/internal.rb @@ -119,7 +119,8 @@ module Hammer attach_function :h_indirect, [], :h_parser attach_function :h_bind_indirect, [:h_parser, :h_parser], :void - #attach_function :h_action, [:h_parser, ...], :h_parser + callback :HAction, [HParseResult.by_ref], HParsedToken.by_ref + attach_function :h_action, [:h_parser, :HAction], :h_parser #attach_function :h_attr_bool, [:h_parser, ...], :h_parser # free the parse result diff --git a/src/bindings/ruby/lib/hammer/parser.rb b/src/bindings/ruby/lib/hammer/parser.rb index c0c1cfc8416d159d28c0689c0cbbd1c1de61d5b7..f9ff4c703106757242b7ad493ce01e352ee0b862 100644 --- a/src/bindings/ruby/lib/hammer/parser.rb +++ b/src/bindings/ruby/lib/hammer/parser.rb @@ -45,6 +45,15 @@ module Hammer @dont_gc << other_parser end + # Can pass the action either as a Proc in second parameter, or as block. + def self.action(parser, action=nil, &block) + action = block if action.nil? + raise ArgumentError, 'no action' if action.nil? + + h_parser = Hammer::Internal.h_action(parser.h_parser, action) + return Hammer::Parser.new(:action, h_parser, [parser, action]) + end + def self.token(string) # Need to copy string to a memory buffer (not just string.dup) # * Original string might be modified, this must not affect existing tokens diff --git a/src/bindings/ruby/lib/hammer/parser_builder.rb b/src/bindings/ruby/lib/hammer/parser_builder.rb index d610db9cec397c475fbcd939c90f61de74a2ab94..6756314aacaa7d72b35056c5f8ec2a820ccc12c8 100644 --- a/src/bindings/ruby/lib/hammer/parser_builder.rb +++ b/src/bindings/ruby/lib/hammer/parser_builder.rb @@ -52,9 +52,18 @@ module Hammer return self end + # modifies previous parser + def action(&block) + parser = @parsers.last + raise RuntimeError, 'need a parser before action' if parser.nil? + @parsers << Hammer::Parser.action(parser, &block) + return self + end + # Defines a parser constructor with the given name. def self.define_parser(name, options = {}) define_method name do |*args| + # TODO: This is wrong!! Needs to accept a block for nested parsers! @parsers << Hammer::Parser.send(name, *args) return self end