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 64 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 124 def dsl_params send(parser_abilities[@parser_type].at(0)) end
endian(endian = nil)
click to toggle source
# File lib/bindata/dsl.rb, line 75 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 114 def fields unless defined? @fields fields = parent_fields @fields = SanitizedFields.new(hints) @fields.copy_fields(fields) if fields end @fields end
hide(*args)
click to toggle source
# File lib/bindata/dsl.rb, line 101 def hide(*args) if option?(:hidden_fields) hidden = args.collect { |name| name.to_sym } unless defined? @hide @hide = parent_attribute(:hide, []).dup end @hide.concat(hidden.compact) @hide end end
method_missing(*args, &block)
click to toggle source
# File lib/bindata/dsl.rb, line 128 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 84 def search_prefix(*args) unless defined? @search_prefix @search_prefix = parent_attribute(:search_prefix, []).dup end prefix = args.collect { |name| name.to_sym }.compact if prefix.size > 0 if has_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 199 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, message)
click to toggle source
# File lib/bindata/dsl.rb, line 215 def dsl_raise(exception, message) backtrace = caller backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first raise exception, message + " in #{@the_class}", backtrace end
ensure_hints()
click to toggle source
# File lib/bindata/dsl.rb, line 151 def ensure_hints endian search_prefix end
has_fields?()
click to toggle source
# File lib/bindata/dsl.rb, line 185 def has_fields? defined? @fields and @fields.length > 0 end
hints()
click to toggle source
# File lib/bindata/dsl.rb, line 156 def hints { :endian => endian, :search_prefix => search_prefix } end
option?(opt)
click to toggle source
# File lib/bindata/dsl.rb, line 147 def option?(opt) parser_abilities[@parser_type].at(1).include?(opt) end
parent_attribute(attr, default = nil)
click to toggle source
# File lib/bindata/dsl.rb, line 205 def parent_attribute(attr, default = nil) parent = @the_class.superclass parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil if parser and parser.respond_to?(attr) parser.send(attr) else default end end
parent_fields()
click to toggle source
# File lib/bindata/dsl.rb, line 181 def parent_fields parent_attribute(:fields) end
parse_and_append_field(*args, &block)
click to toggle source
# File lib/bindata/dsl.rb, line 189 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 136 def parser_abilities @abilities ||= { :struct => [:to_struct_params, [:multiple_fields, :optional_fieldnames, :hidden_fields]], :array => [:to_array_params, [:multiple_fields, :optional_fieldnames]], :buffer => [:to_array_params, [:multiple_fields, :optional_fieldnames, :hidden_fields]], :choice => [:to_choice_params, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]], :delayed_io => [:to_array_params, [:multiple_fields, :optional_fieldnames, :hidden_fields]], :primitive => [:to_struct_params, [:multiple_fields, :optional_fieldnames]] } end
set_endian(endian)
click to toggle source
# File lib/bindata/dsl.rb, line 160 def set_endian(endian) if endian if has_fields? dsl_raise SyntaxError, "endian must be called before defining fields" end if not 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_array_params()
click to toggle source
# File lib/bindata/dsl.rb, line 222 def to_array_params case fields.length when 0 {} when 1 {:type => fields[0].prototype} else {:type => [:struct, to_struct_params]} end end
to_choice_params()
click to toggle source
# File lib/bindata/dsl.rb, line 233 def to_choice_params if fields.length == 0 {} elsif fields.all_field_names_blank? {:choices => fields.collect { |f| f.prototype }} else choices = {} fields.each { |f| choices[f.name] = f.prototype } {:choices => choices} end end
to_struct_params()
click to toggle source
# File lib/bindata/dsl.rb, line 245 def to_struct_params result = {:fields => fields} if not endian.nil? result[:endian] = endian end if not search_prefix.empty? result[:search_prefix] = search_prefix end if option?(:hidden_fields) and not hide.empty? result[:hide] = hide end result end
valid_endian?(endian)
click to toggle source
# File lib/bindata/dsl.rb, line 177 def valid_endian?(endian) [:big, :little, :big_and_little].include?(endian) end