Class: BinaryParser::StructureDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/structure_definition.rb

Defined Under Namespace

Classes: DataDefinition, LoopDefinition

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(method_names = [], parent_structure = nil, &init_proc) ⇒ StructureDefinition

Returns a new instance of StructureDefinition.



9
10
11
12
13
14
15
16
# File 'lib/structure_definition.rb', line 9

def initialize(method_names=[], parent_structure=nil, &init_proc)
  @method_names = method_names
  @parent_structure = parent_structure
  @bit_at = BitPosition.new     
  @data_def, @var = {}, {}
  @conditions, @names = [], []
  instance_eval(&init_proc) if init_proc
end

Instance Attribute Details

#bit_atObject (readonly)

Returns the value of attribute bit_at.



7
8
9
# File 'lib/structure_definition.rb', line 7

def bit_at
  @bit_at
end

#namesObject (readonly)

Returns the value of attribute names.



7
8
9
# File 'lib/structure_definition.rb', line 7

def names
  @names
end

#parent_structureObject (readonly)

Returns the value of attribute parent_structure.



7
8
9
# File 'lib/structure_definition.rb', line 7

def parent_structure
  @parent_structure
end

Instance Method Details

#[](name) ⇒ Object



117
118
119
# File 'lib/structure_definition.rb', line 117

def [](name)
  return @data_def[name]
end

#check_new_def_name(name) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/structure_definition.rb', line 68

def check_new_def_name(name)
  if name[0..1] == "__"
    raise DefinitionError, "Name that starts with '__' is system-reserved."
  end
  if @method_names.include?(name)
    raise DefinitionError, "Name '#{name}' is already used as method name." +
      "You should chanege to other name."
  end
  if @data_def[name]
    raise DefinitionError, "Name #{name} is already defined." +
      "You should change to other name."
  end
end

#cond(*var_names, &condition_proc) ⇒ Object



87
88
89
90
91
92
# File 'lib/structure_definition.rb', line 87

def cond(*var_names, &condition_proc)
  unless var_names.all?{|name| name_solvable?(name)}
    raise DefinitionError, "As condition variable, unsolvable variable #{symbol} is used."
  end
  return Condition.new(*var_names, &condition_proc)
end

#data(name, klass, bit_length) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/structure_definition.rb', line 18

def data(name, klass, bit_length)
  check_new_def_name(name)
  unless klass.ancestors.include?(TemplateBase)
    raise DefinitionError, "Class #{klass} should be TemplateBase."
  end
  bit_at, bit_length = process_bit_length(bit_length, name)
  @data_def[name] = DataDefinition.new(bit_at, bit_length, @conditions.dup, klass)
  @names << name
end

#IF(condition, &block) ⇒ Object



62
63
64
65
66
# File 'lib/structure_definition.rb', line 62

def IF(condition, &block)
  @conditions.push(condition)
  block.call
  @conditions.pop
end

#len(name) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/structure_definition.rb', line 101

def len(name)
  unless name_solvable?(name)
    raise DefinitionError, "Unsolvable variable #{name} is used."
  end
  symbol = ("__LEN__" + name.to_s).to_sym
  return Expression.new([symbol])
end

#name_solvable?(name, structure = self) ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
85
# File 'lib/structure_definition.rb', line 82

def name_solvable?(name, structure=self)
  return structure[name] ||
    (structure.parent_structure && name_solvable?(name, structure.parent_structure))
end

#positionObject



109
110
111
# File 'lib/structure_definition.rb', line 109

def position
  return Expression.new([:__position])
end

#restObject



113
114
115
# File 'lib/structure_definition.rb', line 113

def rest
  return Expression.new([:__rest])
end

#SPEND(bit_length, name, &block) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/structure_definition.rb', line 28

def SPEND(bit_length, name, &block)
  check_new_def_name(name)
  bit_at, bit_length = process_bit_length(bit_length, name)
  used_method_names = NamelessTemplate.instance_methods + Scope.instance_methods
  structure = StructureDefinition.new(used_method_names, self, &block)
  @data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
  @names << name
end

#TIMES(times, name, &block) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/structure_definition.rb', line 37

def TIMES(times, name, &block)
  check_new_def_name(name)
  structure = StructureDefinition.new(Scope.instance_methods, self, &block)
  if structure.bit_at.names.empty?
    bit_at, bit_length = process_bit_length(times * structure.bit_at.imm, name)
    @data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
  else
    bit_length = Expression.new([0])
    structure.bit_at.names.each do |bit_at_depending_name|
      depending_length_exp = structure[bit_at_depending_name].bit_length
      depending_length_exp.variables.each do |var_name|
        if structure[var_name]
          raise DefinitionError, "In '#{name}', same level variable #{var_name} is referenced." + 
            "*** TIMES's inner structure's bit-length must be always same." +
            "In other words, that bit-length must not rely on same level variables. ***"
        end
      end
      bit_length += depending_length_exp
    end
    bit_at, bit_length = process_bit_length(bit_length * times, name)
    @data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
  end
  @names << name
end

#var(name) ⇒ Object



94
95
96
97
98
99
# File 'lib/structure_definition.rb', line 94

def var(name)
  unless name_solvable?(name)
    raise DefinitionError, "Unsolvable variable #{name} is used."
  end
  return Expression.new([name])
end