class BinData::DSLMixin::DSLParser
A DSLParser parses and accumulates field definitions of the form
type name, params
where:
* +type+ is the under_scored name of a registered type * +name+ is the (possible optional) name of the field * +params+ is a hash containing any parameters
Attributes
parser_type[R]
Public Class Methods
new(the_class, parser_type)
click to toggle source
# File lib/bindata/dsl.rb, line 63 def initialize(the_class, parser_type) raise "unknown parser type #{parser_type}" unless parser_abilities[parser_type] @the_class = the_class @parser_type = parser_type @validator = DSLFieldValidator.new(the_class, self) @endian = nil end
Public Instance Methods
dsl_params()
click to toggle source
# File lib/bindata/dsl.rb, line 113 def dsl_params abilities = parser_abilities[@parser_type] send(abilities.at(0), abilities.at(1)) end
endian(endian = nil)
click to toggle source
# File lib/bindata/dsl.rb, line 74 def endian(endian = nil) if endian set_endian(endian) elsif @endian.nil? set_endian(parent_attribute(:endian)) end @endian end
fields()
click to toggle source
# File lib/bindata/dsl.rb, line 109 def fields @fields ||= SanitizedFields.new(hints, parent_fields) end
hide(*args)
click to toggle source
# File lib/bindata/dsl.rb, line 98 def hide(*args) if option?(:hidden_fields) @hide ||= parent_attribute(:hide, []).dup hidden = args.collect(&:to_sym).compact @hide.concat(hidden) @hide end end
method_missing(*args, &block)
click to toggle source
# File lib/bindata/dsl.rb, line 118 def method_missing(*args, &block) ensure_hints parse_and_append_field(*args, &block) end
search_prefix(*args)
click to toggle source
# File lib/bindata/dsl.rb, line 83 def search_prefix(*args) @search_prefix ||= parent_attribute(:search_prefix, []).dup prefix = args.collect(&:to_sym).compact unless prefix.empty? if fields? dsl_raise SyntaxError, "search_prefix must be called before defining fields" end @search_prefix = prefix.concat(@search_prefix) end @search_prefix end
Private Instance Methods
append_field(type, name, params)
click to toggle source
# File lib/bindata/dsl.rb, line 190 def append_field(type, name, params) fields.add_field(type, name, params) rescue BinData::UnRegisteredTypeError => err raise TypeError, "unknown type '#{err.message}'" end
dsl_raise(exception, msg)
click to toggle source
# File lib/bindata/dsl.rb, line 206 def dsl_raise(exception, msg) backtrace = caller backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first raise exception, "#{msg} in #{@the_class}", backtrace end
ensure_hints()
click to toggle source
# File lib/bindata/dsl.rb, line 142 def ensure_hints endian search_prefix end
fields?()
click to toggle source
# File lib/bindata/dsl.rb, line 176 def fields? defined?(@fields) && !@fields.empty? end
hints()
click to toggle source
# File lib/bindata/dsl.rb, line 147 def hints { endian: endian, search_prefix: search_prefix } end
option?(opt)
click to toggle source
# File lib/bindata/dsl.rb, line 138 def option?(opt) parser_abilities[@parser_type].at(2).include?(opt) end
parent_attribute(attr, default = nil)
click to toggle source
# File lib/bindata/dsl.rb, line 196 def parent_attribute(attr, default = nil) parent = @the_class.superclass parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil if parser && parser.respond_to?(attr) parser.send(attr) else default end end
parent_fields()
click to toggle source
# File lib/bindata/dsl.rb, line 172 def parent_fields parent_attribute(:fields) end
parse_and_append_field(*args, &block)
click to toggle source
# File lib/bindata/dsl.rb, line 180 def parse_and_append_field(*args, &block) parser = DSLFieldParser.new(hints, *args, &block) begin @validator.validate_field(parser.name) append_field(parser.type, parser.name, parser.params) rescue Exception => err dsl_raise err.class, err.message end end
parser_abilities()
click to toggle source
# File lib/bindata/dsl.rb, line 126 def parser_abilities @abilities ||= { struct: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames, :hidden_fields]], array: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames]], buffer: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]], choice: [:to_choice_params, :choices, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]], delayed_io: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]], primitive: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames]], skip: [:to_object_params, :until_valid, [:multiple_fields, :optional_fieldnames]], } end
set_endian(endian)
click to toggle source
# File lib/bindata/dsl.rb, line 151 def set_endian(endian) if endian if fields? dsl_raise SyntaxError, "endian must be called before defining fields" end if !valid_endian?(endian) dsl_raise ArgumentError, "unknown value for endian '#{endian}'" end if endian == :big_and_little DSLBigAndLittleEndianHandler.handle(@the_class) end @endian = endian end end
to_choice_params(key)
click to toggle source
# File lib/bindata/dsl.rb, line 224 def to_choice_params(key) if fields.empty? {} elsif fields.all_field_names_blank? {key => fields.collect(&:prototype)} else choices = {} fields.each { |f| choices[f.name] = f.prototype } {key => choices} end end
to_object_params(key)
click to toggle source
# File lib/bindata/dsl.rb, line 213 def to_object_params(key) case fields.length when 0 {} when 1 {key => fields[0].prototype} else {key=> [:struct, to_struct_params]} end end
to_struct_params(*unused)
click to toggle source
# File lib/bindata/dsl.rb, line 236 def to_struct_params(*unused) result = {fields: fields} if !endian.nil? result[:endian] = endian end if !search_prefix.empty? result[:search_prefix] = search_prefix end if option?(:hidden_fields) && !hide.empty? result[:hide] = hide end result end
valid_endian?(endian)
click to toggle source
# File lib/bindata/dsl.rb, line 168 def valid_endian?(endian) [:big, :little, :big_and_little].include?(endian) end