Implement first version of HParseResult.

This commit is contained in:
Jakob Rath 2013-12-15 12:01:41 +01:00 committed by Dan Hirsch
parent 6d38b8e82a
commit c08818e5a5
3 changed files with 60 additions and 14 deletions

View file

@ -71,3 +71,5 @@ p parser.parse 'abcabdabd'
p parser.parse 'abcabd' p parser.parse 'abcabd'
p parser.parse 'abdabd' p parser.parse 'abdabd'
p parser.parse 'abd' p parser.parse 'abd'
$r = parser.parse 'abcabd'

View file

@ -7,10 +7,59 @@ module Hammer
ffi_lib 'libhammer.dylib' ffi_lib 'libhammer.dylib'
typedef :pointer, :h_parser 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 # 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 # build a parser
attach_function :h_token, [:string, :size_t], :h_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_action, [:h_parser, ...], :h_parser
#attach_function :h_attr_bool, [: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 # 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? # TODO: Does the HParser* need to be freed?
end end

View file

@ -16,17 +16,15 @@ module Hammer
attr_reader :name attr_reader :name
attr_reader :h_parser 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. # data: A string containing the data to parse.
def parse(data) def parse(data)
raise RuntimeError, '@h_parser is nil' if @h_parser.nil? 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. 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) result = Hammer::Internal.h_parse(@h_parser, data, data.length)
# TODO: Do something with the data return result unless result.null?
# (wrap in garbage-collected object, call h_parse_result_free when destroyed by GC)
Hammer::Internal.h_parse_result_free(result)
!result.null?
end end
# Binds an indirect parser. # Binds an indirect parser.
@ -36,6 +34,9 @@ module Hammer
end end
def self.token(string) 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_string = string.dup
h_parser = Hammer::Internal.h_token(h_string, h_string.length) h_parser = Hammer::Internal.h_token(h_string, h_string.length)