binary_parser 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|