binary_parser 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/binary_parser.gemspec +2 -2
- data/lib/binary_parser/version.rb +1 -1
- data/lib/binary_parser.rb +5 -1
- data/lib/built_in_template/binary.rb +14 -0
- data/lib/built_in_template/uint.rb +74 -1
- data/lib/general_class/bit_position.rb +1 -1
- data/lib/general_class/condition.rb +4 -3
- data/lib/general_class/expression.rb +216 -40
- data/lib/general_class/free_condition.rb +20 -0
- data/lib/general_class/memorize.rb +36 -0
- data/lib/general_class/proxy.rb +14 -0
- data/lib/loop_list.rb +2 -0
- data/lib/scope.rb +46 -36
- data/lib/structure_definition.rb +88 -55
- data/lib/template_base.rb +14 -12
- data/lib/while_list.rb +31 -0
- data/unit_test/built_in_template/test_binary.rb +40 -0
- data/unit_test/built_in_template/test_uint.rb +87 -0
- data/unit_test/general_class/test_bit_position.rb +1 -1
- data/unit_test/general_class/test_condition.rb +2 -2
- data/unit_test/general_class/test_expression.rb +29 -5
- data/unit_test/general_class/test_free_condition.rb +20 -0
- data/unit_test/test_scope.rb +46 -0
- data/unit_test/test_structure_definition.rb +47 -6
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc0580a7a3667f74608fc328897ce3ee3772b94a
|
4
|
+
data.tar.gz: d9c1e1b204e9813ff8239cd2d36f45a509430c54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 658d10fb088312e15f51965c4a8a9f366b60a58e3be00a61d0dc70fc243f0f124e8adac9b5ef5f113eb2e43ca7b0fa7f83b0998684a7001492819cec4f94547e
|
7
|
+
data.tar.gz: c8347f938c25674e959014f1bcc1f4097a6d8efdde741f819a5c72f490297d372415c70c68121eea7a14cb6cfffab3a24f46ba394a64163472548ec6a8dc850e
|
data/.gitignore
CHANGED
data/binary_parser.gemspec
CHANGED
@@ -7,10 +7,10 @@ require 'binary_parser/version'
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = "binary_parser"
|
9
9
|
spec.version = BinaryParser::VERSION
|
10
|
-
spec.authors = ["
|
10
|
+
spec.authors = ["sawaken"]
|
11
11
|
spec.email = ["sasasawada@gmail.com"]
|
12
12
|
spec.summary = "An elegant DSL library for parsing binary-data."
|
13
|
-
spec.homepage = "https://github.com/
|
13
|
+
spec.homepage = "https://github.com/sawaken/ruby-binary-parser"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
data/lib/binary_parser.rb
CHANGED
@@ -12,7 +12,10 @@ module BinaryParser
|
|
12
12
|
'expression.rb',
|
13
13
|
'bit_position.rb',
|
14
14
|
'condition.rb',
|
15
|
-
'
|
15
|
+
'free_condition.rb',
|
16
|
+
'buffered_stream.rb',
|
17
|
+
'proxy.rb',
|
18
|
+
'memorize.rb'
|
16
19
|
]
|
17
20
|
|
18
21
|
GENERAL_CLASS_FILES.each do |path|
|
@@ -38,6 +41,7 @@ module BinaryParser
|
|
38
41
|
LIB_DIR = '/lib/'
|
39
42
|
LIB_FILES =
|
40
43
|
['loop_list.rb',
|
44
|
+
'while_list.rb',
|
41
45
|
'scope.rb',
|
42
46
|
'structure_definition.rb',
|
43
47
|
'template_base.rb',
|
@@ -6,6 +6,20 @@ module BinaryParser
|
|
6
6
|
bytes = chars[0, 5].map{|i| sprintf("0x%02x", i)}.join(", ")
|
7
7
|
return "[" + bytes + (chars.length > 5 ? ", ..." : "") + "]"
|
8
8
|
end
|
9
|
+
|
10
|
+
def to_str
|
11
|
+
self.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
if other.is_a?(Binary)
|
16
|
+
self.to_s == other.to_s
|
17
|
+
elsif other.is_a?(String)
|
18
|
+
self.to_s == other
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
9
23
|
end
|
10
24
|
end
|
11
25
|
end
|
@@ -1,8 +1,81 @@
|
|
1
1
|
module BinaryParser
|
2
2
|
module BuiltInTemplate
|
3
3
|
class UInt < TemplateBase
|
4
|
+
|
5
|
+
include Comparable
|
6
|
+
|
4
7
|
def content_description
|
5
|
-
to_i.to_s
|
8
|
+
self.to_i.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s(base=10)
|
12
|
+
self.to_i.to_s(base)
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](bit_index)
|
16
|
+
self.to_i[bit_index]
|
17
|
+
end
|
18
|
+
|
19
|
+
def coerce(other)
|
20
|
+
if other.is_a?(Integer)
|
21
|
+
return other, self.to_i
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def +(other)
|
28
|
+
if other.is_a?(UInt)
|
29
|
+
self.to_i + other.to_i
|
30
|
+
elsif other.is_a?(Integer)
|
31
|
+
self.to_i + other
|
32
|
+
else
|
33
|
+
x, y = other.coerce(self)
|
34
|
+
x + y
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def *(other)
|
39
|
+
if other.is_a?(UInt)
|
40
|
+
self.to_i * other.to_i
|
41
|
+
elsif other.is_a?(Integer)
|
42
|
+
self.to_i * other
|
43
|
+
else
|
44
|
+
x, y = other.coerce(self)
|
45
|
+
x * y
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def -(other)
|
50
|
+
if other.is_a?(UInt)
|
51
|
+
self.to_i - other.to_i
|
52
|
+
elsif other.is_a?(Integer)
|
53
|
+
self.to_i - other
|
54
|
+
else
|
55
|
+
x, y = other.coerce(self)
|
56
|
+
x - y
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def /(other)
|
61
|
+
if other.is_a?(UInt)
|
62
|
+
self.to_i / other.to_i
|
63
|
+
elsif other.is_a?(Integer)
|
64
|
+
self.to_i / other
|
65
|
+
else
|
66
|
+
x, y = other.coerce(self)
|
67
|
+
x / y
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def <=>(other)
|
72
|
+
if other.is_a?(UInt)
|
73
|
+
self.to_i <=> other.to_i
|
74
|
+
elsif other.is_a?(Integer)
|
75
|
+
self.to_i <=> other
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
6
79
|
end
|
7
80
|
end
|
8
81
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module BinaryParser
|
2
2
|
class Condition
|
3
3
|
def initialize(*var_names, &condition_proc)
|
4
|
-
@
|
4
|
+
@tokens = var_names.map{|symbol| Expression.value_var(symbol)}
|
5
|
+
@condition_proc = condition_proc
|
5
6
|
end
|
6
7
|
|
7
|
-
def eval(&
|
8
|
-
return @condition_proc.call(*@
|
8
|
+
def eval(&token_eval_proc)
|
9
|
+
return @condition_proc.call(*@tokens.map{|token| token_eval_proc.call(token)})
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -1,66 +1,242 @@
|
|
1
1
|
module BinaryParser
|
2
2
|
class Expression
|
3
|
-
attr_reader :rpn
|
4
3
|
|
5
|
-
def
|
6
|
-
|
4
|
+
def self.value_var(symbol)
|
5
|
+
Token::Variable::Value.new(symbol)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.length_var(symbol)
|
9
|
+
Token::Variable::Length.new(symbol)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.control_var(symbol)
|
13
|
+
Token::Variable::Control.new(symbol)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.nextbits_var(length)
|
17
|
+
Token::Variable::Nextbits.new(length)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.immediate(value)
|
21
|
+
Token::Immediate.new(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def value_var?
|
25
|
+
self.is_a?(Token::Variable::Value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def length_var?
|
29
|
+
self.is_a?(Token::Variable::Length)
|
30
|
+
end
|
31
|
+
|
32
|
+
def control_var?
|
33
|
+
self.is_a?(Token::Variable::Control)
|
34
|
+
end
|
35
|
+
|
36
|
+
def nextbits_var?
|
37
|
+
self.is_a?(Token::Variable::Nextbits)
|
38
|
+
end
|
39
|
+
|
40
|
+
def immediate?
|
41
|
+
self.is_a?(Token::Immediate)
|
42
|
+
end
|
43
|
+
|
44
|
+
def coerce(other)
|
45
|
+
if other.is_a?(Integer)
|
46
|
+
return Token::Immediate.new(other), self
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
7
50
|
end
|
8
51
|
|
9
52
|
def +(other)
|
10
|
-
|
53
|
+
binary_op(other, Token::Operator::Add.instance)
|
11
54
|
end
|
12
55
|
|
13
56
|
def -(other)
|
14
|
-
|
57
|
+
binary_op(other, Token::Operator::Sub.instance)
|
15
58
|
end
|
16
59
|
|
17
60
|
def *(other)
|
18
|
-
|
61
|
+
binary_op(other, Token::Operator::Mul.instance)
|
19
62
|
end
|
20
63
|
|
21
64
|
def /(other)
|
22
|
-
|
65
|
+
binary_op(other, Token::Operator::Div.instance)
|
23
66
|
end
|
24
67
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
68
|
+
def %(other)
|
69
|
+
binary_op(other, Token::Operator::Mod.instance)
|
70
|
+
end
|
71
|
+
|
72
|
+
def binary_op(other, op)
|
73
|
+
BinaryOperator.new(self, other, op)
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_exp(exp)
|
77
|
+
if exp.is_a?(Expression)
|
78
|
+
exp
|
79
|
+
elsif exp.is_a?(Integer)
|
80
|
+
Token::Immediate.new(exp)
|
31
81
|
else
|
32
|
-
raise BadManipulationError, "
|
82
|
+
raise BadManipulationError, "Can't convert #{exp} into Expression."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def eval(&token_eval_proc)
|
87
|
+
to_rpn.eval(&token_eval_proc)
|
88
|
+
end
|
89
|
+
|
90
|
+
def variable_tokens
|
91
|
+
to_rpn.tokens.select{|token| token.is_a?(Token::Variable)}
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize(*args)
|
95
|
+
raise BadManipulationError, "Expression is abstract class."
|
96
|
+
end
|
97
|
+
|
98
|
+
class BinaryOperator < self
|
99
|
+
def initialize(chl, chr, op)
|
100
|
+
check_op(op)
|
101
|
+
@chl, @chr, @op = to_exp(chl), to_exp(chr), op
|
102
|
+
end
|
103
|
+
|
104
|
+
def check_op(op)
|
105
|
+
unless op.is_a?(Token::Operator)
|
106
|
+
raise BadManipulationError, "Argument should be Token::Operator."
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_rpn
|
111
|
+
@rpn ||= @chl.to_rpn + @chr.to_rpn + @op.to_rpn
|
33
112
|
end
|
34
113
|
end
|
35
114
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
115
|
+
class Token < self
|
116
|
+
|
117
|
+
def initialize
|
118
|
+
#override but do nothing
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_rpn
|
122
|
+
@rpn ||= RPN.new(self)
|
123
|
+
end
|
124
|
+
|
125
|
+
class Variable < self
|
126
|
+
|
127
|
+
attr_reader :symbol
|
128
|
+
|
129
|
+
def initialize(symbol)
|
130
|
+
raise BadManipulationError, "Argument should be Symbol." unless symbol.is_a?(Symbol)
|
131
|
+
@symbol = symbol
|
132
|
+
end
|
133
|
+
|
134
|
+
class Length < self
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
class Value < self
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
class Control < self
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
class Nextbits < self
|
147
|
+
|
148
|
+
attr_reader :length
|
149
|
+
|
150
|
+
def initialize(length)
|
151
|
+
unless length.is_a?(Integer) && length > 0
|
152
|
+
raise BadManipulationError, "Argument should be positive Integer."
|
153
|
+
end
|
154
|
+
@length = length
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class Immediate < self
|
160
|
+
|
161
|
+
attr_reader :value
|
162
|
+
|
163
|
+
def initialize(value)
|
164
|
+
raise BadManipulationError, "Argument should be Integer." unless value.is_a?(Integer)
|
165
|
+
@value = value
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class Operator < self
|
170
|
+
|
171
|
+
require 'singleton'
|
172
|
+
include Singleton
|
173
|
+
|
174
|
+
class Add < self
|
175
|
+
def operate(op1, op2)
|
176
|
+
op1 + op2
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class Sub < self
|
181
|
+
def operate(op1, op2)
|
182
|
+
op1 - op2
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class Mul < self
|
187
|
+
def operate(op1, op2)
|
188
|
+
op1 * op2
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class Div < self
|
193
|
+
def operate(op1, op2)
|
194
|
+
op1 / op2
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class Mod < self
|
199
|
+
def operate(op1, op2)
|
200
|
+
op1 % op2
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class RPN
|
207
|
+
attr_reader :tokens
|
208
|
+
|
209
|
+
def initialize(*tokens)
|
210
|
+
check_tokens(tokens)
|
211
|
+
@tokens = tokens
|
212
|
+
end
|
213
|
+
|
214
|
+
def check_tokens(tokens)
|
215
|
+
tokens.all?{|token| token.is_a?(Expression::Token)}
|
216
|
+
end
|
217
|
+
|
218
|
+
def +(other)
|
219
|
+
RPN.new(*(self.tokens + other.tokens))
|
220
|
+
end
|
221
|
+
|
222
|
+
def eval(&token_eval_proc)
|
223
|
+
stack = @tokens.inject([]) do |stack, token|
|
224
|
+
if token.is_a?(Expression::Token::Operator)
|
225
|
+
raise BadManipulationError, "Cannot calculate this RPN." if stack.length < 2
|
226
|
+
stack + [token.operate(*[stack.pop, stack.pop].reverse)]
|
227
|
+
elsif token.is_a?(Expression::Token::Immediate)
|
228
|
+
stack + [token.value]
|
229
|
+
elsif token.is_a?(Expression::Token::Variable)
|
230
|
+
eval_value = token_eval_proc.call(token)
|
231
|
+
unless eval_value.is_a?(Integer)
|
232
|
+
raise BadManipulationError, "Evaluation is faild. #{eval_value} is not Integer."
|
233
|
+
end
|
234
|
+
stack + [eval_value]
|
235
|
+
end
|
60
236
|
end
|
237
|
+
raise BadManipulationError, "Cannot calculate this RPN." if stack.length != 1
|
238
|
+
return stack.last
|
61
239
|
end
|
62
|
-
raise ProgramAssertionError, "Cannot calc RPN." unless stack.length == 1
|
63
|
-
return stack.last
|
64
240
|
end
|
65
241
|
end
|
66
242
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BinaryParser
|
2
|
+
class FreeCondition
|
3
|
+
def initialize(&condition_proc)
|
4
|
+
@condition_proc = condition_proc
|
5
|
+
end
|
6
|
+
|
7
|
+
def eval(&name_eval_proc)
|
8
|
+
@name_eval_proc = name_eval_proc
|
9
|
+
return Proxy.new(self, []).instance_eval(&@condition_proc)
|
10
|
+
end
|
11
|
+
|
12
|
+
def symbol_call(symbol, *args, &block)
|
13
|
+
if symbol == :nextbits && args.length == 1
|
14
|
+
@name_eval_proc.call(Expression.nextbits_var(args[0]))
|
15
|
+
else
|
16
|
+
@name_eval_proc.call(Expression.value_var(symbol))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BinaryParser
|
2
|
+
module Memorize
|
3
|
+
module Extension
|
4
|
+
|
5
|
+
attr_accessor :memorize_methods
|
6
|
+
|
7
|
+
def method_added(method_name)
|
8
|
+
@memorized ||= Hash.new
|
9
|
+
if @memorize_methods.include?(method_name) && !@memorized[method_name]
|
10
|
+
@memorized[method_name] = true
|
11
|
+
memorize(method_name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def memorize(method_name)
|
16
|
+
pure_method_name = "pure_#{method_name}".to_sym
|
17
|
+
alias_method pure_method_name, method_name
|
18
|
+
define_method(method_name) do |arg|
|
19
|
+
@memo ||= Hash.new
|
20
|
+
@memo[method_name] ||= Hash.new
|
21
|
+
@memo[method_name][arg] ||= send(pure_method_name, arg)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.one_arg_method(*method_names)
|
27
|
+
@method_names = method_names
|
28
|
+
return self
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.included(klass)
|
32
|
+
klass.extend Extension
|
33
|
+
klass.memorize_methods = @method_names
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Proxy < BasicObject
|
2
|
+
def initialize(target, proxy_methods)
|
3
|
+
@target = target
|
4
|
+
@proxy_methods = proxy_methods
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_missing(message, *args, &block)
|
8
|
+
if @proxy_methods.include?(message)
|
9
|
+
@target.__send__(message, *args, &block)
|
10
|
+
else
|
11
|
+
@target.symbol_call(message, *args, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/loop_list.rb
CHANGED
data/lib/scope.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module BinaryParser
|
2
2
|
class Scope
|
3
|
+
include Memorize.one_arg_method(:load_var, :eval_bit_position, :eval_bit_length)
|
3
4
|
|
4
5
|
attr_reader :abstract_binary
|
5
6
|
|
@@ -7,7 +8,6 @@ module BinaryParser
|
|
7
8
|
@definition = structure_definition
|
8
9
|
@abstract_binary = abstract_binary
|
9
10
|
@parent_scope = parent_scope
|
10
|
-
@data, @ebs, @ebl = {}, {}, {}
|
11
11
|
end
|
12
12
|
|
13
13
|
def names
|
@@ -18,16 +18,17 @@ module BinaryParser
|
|
18
18
|
raise UndefinedError, "Undefined data-name '#{name}'." unless @definition[name]
|
19
19
|
end
|
20
20
|
|
21
|
-
# * Unsatisfactory memorized method (little obfuscated? : need refactoring?)
|
22
21
|
def load_var(name)
|
23
22
|
return @parent_scope.load_var(name) if !@definition[name] && @parent_scope
|
24
23
|
check_name_defined(name)
|
25
24
|
case @definition[name]
|
26
25
|
when StructureDefinition::DataDefinition
|
27
|
-
|
28
|
-
@definition[name].klass.new(load_binary(name))
|
26
|
+
eval_bit_length(name) == 0 ? nil : @definition[name].klass.new(load_binary(name))
|
29
27
|
when StructureDefinition::LoopDefinition
|
30
|
-
|
28
|
+
LoopList.new(@definition[name], load_binary(name), self)
|
29
|
+
when StructureDefinition::WhileDefinition
|
30
|
+
sub_binary = @abstract_binary.sub(:bit_index => eval_bit_position(name))
|
31
|
+
WhileList.new(@definition[name], sub_binary, self, name)
|
31
32
|
else
|
32
33
|
raise ProgramAssertionError, "Unknown definition-class '#{@definition[name].class}'."
|
33
34
|
end
|
@@ -45,52 +46,61 @@ module BinaryParser
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
|
49
|
+
def preview_as_integer(start_pos, length)
|
50
|
+
sub_binary = @abstract_binary.sub(:bit_index => start_pos, :bit_length => length)
|
51
|
+
TemplateBase.new(sub_binary).to_i
|
52
|
+
end
|
53
|
+
|
49
54
|
def eval_bit_position(name)
|
50
55
|
check_name_defined(name)
|
51
|
-
return @
|
52
|
-
eval_bit_length(name)
|
53
|
-
end
|
56
|
+
return eval(@definition[name].bit_position, nil)
|
54
57
|
end
|
55
58
|
|
56
|
-
# * memorized method (little obfuscated? : need refactoring?)
|
57
59
|
def eval_bit_length(name)
|
58
60
|
check_name_defined(name)
|
59
|
-
|
60
|
-
|
61
|
-
cond.eval{|name| load_var(name)}
|
61
|
+
unless @definition[name].conditions.all?{|cond| eval(cond, name)}
|
62
|
+
return 0
|
62
63
|
end
|
63
|
-
return @
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
64
|
+
return eval(@definition[name].bit_length, name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def eval_entire_bit_length
|
68
|
+
eval(@definition.bit_at, nil)
|
69
|
+
end
|
70
|
+
|
71
|
+
def eval(target, name)
|
72
|
+
target.eval do |token|
|
73
|
+
token_eval(token, name)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
def
|
78
|
-
if
|
77
|
+
def token_eval(token, name)
|
78
|
+
if token.control_var?
|
79
|
+
bit_length_control_variable_resolution(name, token.symbol)
|
80
|
+
elsif token.nextbits_var?
|
81
|
+
preview_as_integer(eval_bit_position(name), token.length)
|
82
|
+
elsif token.length_var?
|
83
|
+
eval_bit_length(token.symbol)
|
84
|
+
elsif token.value_var?
|
85
|
+
unless val = load_var(token.symbol)
|
86
|
+
raise ParsingError, "Variable '#{token.symbol}' assigned to Nil is referenced" +
|
87
|
+
"at the time of resolving '#{name}'."
|
88
|
+
end
|
89
|
+
val.to_i
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def bit_length_control_variable_resolution(name, symbol)
|
94
|
+
if symbol == :rest
|
79
95
|
length = @abstract_binary.bit_length - eval_bit_position(name)
|
80
96
|
raise ParsingError, "Binary is too short. (So, 'rest' is failed.)" if length < 0
|
81
97
|
return length
|
82
|
-
elsif
|
98
|
+
elsif symbol == :position
|
83
99
|
return eval_bit_position(name)
|
84
|
-
elsif
|
85
|
-
return
|
100
|
+
elsif symbol == :non_fixed
|
101
|
+
return load_var(name).bit_length
|
86
102
|
else
|
87
|
-
raise ProgramAssertionError, "Unknown Control-Variable '#{
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def eval_entire_bit_length
|
92
|
-
return @definition.bit_at.eval do |name|
|
93
|
-
eval_bit_length(name)
|
103
|
+
raise ProgramAssertionError, "Unknown Control-Variable '#{symbol}'."
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|