Fix memory issues, add HBytes#token.
This commit is contained in:
parent
cf59ec83ed
commit
b16eab8f33
3 changed files with 23 additions and 3 deletions
|
|
@ -16,4 +16,7 @@ parser = Hammer::Parser.build {
|
||||||
}
|
}
|
||||||
x.bind(Hammer::Parser.token('abd'))
|
x.bind(Hammer::Parser.token('abd'))
|
||||||
|
|
||||||
|
#$p = parser
|
||||||
$r = parser.parse 'abcabd'
|
$r = parser.parse 'abcabd'
|
||||||
|
|
||||||
|
p $r[:ast][:data][:seq].elements.map {|e| e[:data][:bytes].token }
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,11 @@ module Hammer
|
||||||
class HBytes < FFI::Struct
|
class HBytes < FFI::Struct
|
||||||
layout :token, :pointer, # uint8_t*
|
layout :token, :pointer, # uint8_t*
|
||||||
:len, :size_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
|
end
|
||||||
|
|
||||||
class HParsedTokenDataUnion < FFI::Union
|
class HParsedTokenDataUnion < FFI::Union
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ module Hammer
|
||||||
# name: Name of the parser. Should be a symbol.
|
# name: Name of the parser. Should be a symbol.
|
||||||
# h_parser: The pointer to the parser as returned by hammer.
|
# 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).
|
# 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
|
@name = name
|
||||||
@h_parser = h_parser
|
@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
|
end
|
||||||
|
|
||||||
attr_reader :name
|
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.
|
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)
|
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
|
end
|
||||||
|
|
||||||
# Binds an indirect parser.
|
# Binds an indirect parser.
|
||||||
def bind(other_parser)
|
def bind(other_parser)
|
||||||
raise RuntimeError, 'can only bind indirect parsers' unless self.name == :indirect
|
raise RuntimeError, 'can only bind indirect parsers' unless self.name == :indirect
|
||||||
Hammer::Internal.h_bind_indirect(self.h_parser, other_parser.h_parser)
|
Hammer::Internal.h_bind_indirect(self.h_parser, other_parser.h_parser)
|
||||||
|
@dont_gc << other_parser
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.token(string)
|
def self.token(string)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue