Implement first version of HParseResult.
This commit is contained in:
parent
6d38b8e82a
commit
c08818e5a5
3 changed files with 60 additions and 14 deletions
|
|
@ -71,3 +71,5 @@ p parser.parse 'abcabdabd'
|
|||
p parser.parse 'abcabd'
|
||||
p parser.parse 'abdabd'
|
||||
p parser.parse 'abd'
|
||||
|
||||
$r = parser.parse 'abcabd'
|
||||
|
|
|
|||
|
|
@ -7,10 +7,59 @@ module Hammer
|
|||
ffi_lib 'libhammer.dylib'
|
||||
|
||||
typedef :pointer, :h_parser
|
||||
typedef :pointer, :h_parse_result
|
||||
|
||||
HTokenType = enum(:none, 1,
|
||||
:bytes, 2,
|
||||
:sint, 4,
|
||||
:uint, 8,
|
||||
:sequence, 16,
|
||||
:reserved_1,
|
||||
:err, 32,
|
||||
:user, 64,
|
||||
:max)
|
||||
|
||||
class HCountedArray < FFI::Struct
|
||||
layout :capacity, :size_t,
|
||||
:used, :size_t,
|
||||
:arena, :pointer,
|
||||
:elements, :pointer # TODO
|
||||
end
|
||||
|
||||
class HBytes < FFI::Struct
|
||||
layout :token, :uint8,
|
||||
:len, :size_t
|
||||
end
|
||||
|
||||
class HParsedTokenDataUnion < FFI::Union
|
||||
layout :bytes, HBytes.by_value,
|
||||
:sint, :int64,
|
||||
:uint, :uint64,
|
||||
:dbl, :double,
|
||||
:flt, :float,
|
||||
:seq, HCountedArray.by_ref,
|
||||
:user, :pointer
|
||||
end
|
||||
|
||||
class HParsedToken < FFI::Struct
|
||||
layout :token_type, HTokenType,
|
||||
:data, HParsedTokenDataUnion.by_value,
|
||||
:index, :size_t,
|
||||
:bit_offset, :char
|
||||
end
|
||||
|
||||
class HParseResult < FFI::Struct
|
||||
layout :ast, HParsedToken.by_ref,
|
||||
:bit_length, :long_long,
|
||||
:arena, :pointer
|
||||
|
||||
def self.release(ptr)
|
||||
p "freeing #{ptr}"
|
||||
Hammer::Internal.h_parse_result_free(ptr) unless ptr.null?
|
||||
end
|
||||
end
|
||||
|
||||
# run a parser
|
||||
attach_function :h_parse, [:h_parser, :string, :size_t], :h_parse_result
|
||||
attach_function :h_parse, [:h_parser, :string, :size_t], HParseResult.auto_ptr
|
||||
|
||||
# build a parser
|
||||
attach_function :h_token, [:string, :size_t], :h_parser
|
||||
|
|
@ -57,14 +106,8 @@ module Hammer
|
|||
#attach_function :h_action, [:h_parser, ...], :h_parser
|
||||
#attach_function :h_attr_bool, [:h_parser, ...], :h_parser
|
||||
|
||||
#class HParseResult < FFI::Struct
|
||||
# layout :ast, :pointer,
|
||||
# :bit_length, :longlong,
|
||||
# :arena, :pointer
|
||||
#end
|
||||
|
||||
# free the parse result
|
||||
attach_function :h_parse_result_free, [:h_parse_result], :void
|
||||
attach_function :h_parse_result_free, [HParseResult.by_ref], :void
|
||||
|
||||
# TODO: Does the HParser* need to be freed?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,17 +16,15 @@ module Hammer
|
|||
attr_reader :name
|
||||
attr_reader :h_parser
|
||||
|
||||
# Parse the given data. Returns true if successful, false otherwise.
|
||||
# Parse the given data. Returns the parse result if successful, nil otherwise.
|
||||
#
|
||||
# data: A string containing the data to parse.
|
||||
def parse(data)
|
||||
raise RuntimeError, '@h_parser is nil' if @h_parser.nil?
|
||||
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.length)
|
||||
# TODO: Do something with the data
|
||||
# (wrap in garbage-collected object, call h_parse_result_free when destroyed by GC)
|
||||
Hammer::Internal.h_parse_result_free(result)
|
||||
!result.null?
|
||||
return result unless result.null?
|
||||
end
|
||||
|
||||
# Binds an indirect parser.
|
||||
|
|
@ -36,6 +34,9 @@ module Hammer
|
|||
end
|
||||
|
||||
def self.token(string)
|
||||
# TODO:
|
||||
# This might fail in JRuby.
|
||||
# See "String Memory Allocation" at https://github.com/ffi/ffi/wiki/Core-Concepts
|
||||
h_string = string.dup
|
||||
h_parser = Hammer::Internal.h_token(h_string, h_string.length)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue