kaiseki 0.0.3 → 1.0.1
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.
- data/README +0 -0
- data/lib/action.rb +8 -0
- data/lib/grammar.rb +88 -0
- data/lib/kaiseki.rb +54 -48
- data/lib/mod_file.rb +5 -0
- data/lib/mod_kernel.rb +11 -0
- data/lib/mod_object.rb +11 -0
- data/lib/mod_proc.rb +7 -0
- data/lib/mod_regexp.rb +7 -0
- data/lib/mod_string.rb +11 -0
- data/lib/mod_symbol.rb +27 -0
- data/lib/node.rb +78 -0
- data/lib/parse_error.rb +16 -0
- data/lib/parse_result.rb +21 -0
- data/lib/parseable.rb +67 -0
- data/lib/{grammar/parslet.rb → parser_basic.rb} +7 -12
- data/lib/parser_choice.rb +24 -0
- data/lib/parser_eof.rb +27 -0
- data/lib/parser_multi.rb +27 -0
- data/lib/parser_package.rb +11 -0
- data/lib/parser_regexp.rb +19 -0
- data/lib/parser_repeat.rb +68 -0
- data/lib/parser_sequence.rb +41 -0
- data/lib/parser_string.rb +18 -0
- data/lib/parser_symbol.rb +16 -0
- data/lib/predicate_and.rb +19 -0
- data/lib/predicate_not.rb +19 -0
- data/lib/predicate_skip.rb +19 -0
- data/lib/result_cast.rb +33 -0
- data/lib/result_filter.rb +36 -0
- data/lib/result_merge.rb +20 -0
- data/lib/result_override.rb +20 -0
- data/lib/rule.rb +88 -0
- data/lib/stream.rb +98 -0
- data/lib/var_get.rb +40 -0
- data/lib/var_insert.rb +19 -0
- data/lib/var_set.rb +24 -0
- metadata +45 -40
- data/lib/additions/proc.rb +0 -7
- data/lib/additions/regexp.rb +0 -7
- data/lib/additions/string.rb +0 -7
- data/lib/additions/symbol.rb +0 -19
- data/lib/grammar/and_predicate.rb +0 -22
- data/lib/grammar/array_result.rb +0 -16
- data/lib/grammar/eof_parslet.rb +0 -32
- data/lib/grammar/grammar.rb +0 -113
- data/lib/grammar/grammar_node.rb +0 -31
- data/lib/grammar/location_tracking.rb +0 -57
- data/lib/grammar/log_node.rb +0 -21
- data/lib/grammar/node.rb +0 -59
- data/lib/grammar/not_predicate.rb +0 -22
- data/lib/grammar/parse_error.rb +0 -21
- data/lib/grammar/parse_logger.rb +0 -27
- data/lib/grammar/parse_result.rb +0 -33
- data/lib/grammar/parslet_choice.rb +0 -25
- data/lib/grammar/parslet_combination.rb +0 -35
- data/lib/grammar/parslet_combining.rb +0 -57
- data/lib/grammar/parslet_logging.rb +0 -22
- data/lib/grammar/parslet_merger.rb +0 -50
- data/lib/grammar/parslet_omission.rb +0 -20
- data/lib/grammar/parslet_repetition.rb +0 -65
- data/lib/grammar/parslet_sequence.rb +0 -45
- data/lib/grammar/predicate.rb +0 -30
- data/lib/grammar/proc_parslet.rb +0 -18
- data/lib/grammar/regexp_parslet.rb +0 -25
- data/lib/grammar/stream.rb +0 -90
- data/lib/grammar/string_parslet.rb +0 -29
- data/lib/grammar/string_result.rb +0 -16
- data/lib/grammar/symbol_parslet.rb +0 -22
@@ -0,0 +1,68 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class RepeatParser
|
3
|
+
include Parseable
|
4
|
+
attr_reader :expected, :min, :max
|
5
|
+
|
6
|
+
def initialize expected, min, max = nil
|
7
|
+
@expected = expected.to_parseable
|
8
|
+
@min = min
|
9
|
+
@max = max
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse! stream, options = {}
|
13
|
+
stream.must_be Stream
|
14
|
+
stream.lock do
|
15
|
+
result = []
|
16
|
+
count = 0
|
17
|
+
while max.nil? or count < max
|
18
|
+
begin
|
19
|
+
catch :SkipSuccess do
|
20
|
+
result << @expected.parse(stream, options)
|
21
|
+
end
|
22
|
+
count += 1
|
23
|
+
rescue ParseError
|
24
|
+
if options[:skipping]
|
25
|
+
begin
|
26
|
+
catch :SkipSuccess do
|
27
|
+
options[:skipping].parse stream, options.merge(:skipping => nil)
|
28
|
+
end
|
29
|
+
redo
|
30
|
+
rescue ParseError
|
31
|
+
break
|
32
|
+
end
|
33
|
+
else
|
34
|
+
break
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
if result.length < @min
|
39
|
+
raise ParseError.new "expected #{@min} match#{'es' unless @min == 1} but obtained #{result.length} when parsing #{self}", options
|
40
|
+
else
|
41
|
+
if options[:simplify]
|
42
|
+
if @min == 0 and @max == 1
|
43
|
+
result.length == 0 ? nil : result[0]
|
44
|
+
else
|
45
|
+
result
|
46
|
+
end
|
47
|
+
else
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def eql? other
|
55
|
+
other.is_a?(self.class) and other.expected == @expected and other.min == @min and other.max == @max
|
56
|
+
end
|
57
|
+
|
58
|
+
alias :== :eql?
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
if @max
|
62
|
+
@expected.to_s + " [#{@min}..#{@max}]"
|
63
|
+
else
|
64
|
+
@expected.to_s + " [#{@min}+]"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class SequenceParser < MultiParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
stream.must_be Stream
|
5
|
+
stream.lock do
|
6
|
+
result = []
|
7
|
+
@expected.each do |n|
|
8
|
+
begin
|
9
|
+
catch :SkipSuccess do
|
10
|
+
result << n.parse(stream, options)
|
11
|
+
end
|
12
|
+
rescue ParseError => e
|
13
|
+
if options[:skipping]
|
14
|
+
begin
|
15
|
+
catch :SkipSuccess do
|
16
|
+
options[:skipping].parse stream, options.merge(:skipping => nil)
|
17
|
+
end
|
18
|
+
redo
|
19
|
+
rescue ParseError
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
else
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
if options[:simplify]
|
28
|
+
result.length == 1 ? result[0] : result
|
29
|
+
else
|
30
|
+
result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
alias :& :append
|
36
|
+
|
37
|
+
def delimiter
|
38
|
+
'&'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class StringParser < BasicParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
stream.must_be Stream
|
5
|
+
stream.lock do
|
6
|
+
@expected.each_char do |char|
|
7
|
+
actual = stream.getc
|
8
|
+
if actual.nil?
|
9
|
+
raise ParseError.new "unexpected end-of-string (expected \"#{char}\") when parsing #{self}", options
|
10
|
+
elsif actual != char
|
11
|
+
raise ParseError.new "unexpected character \"#{actual}\" (expected \"#{char}\") when parsing #{self}", options
|
12
|
+
end
|
13
|
+
end
|
14
|
+
@expected.dup
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class SymbolParser < BasicParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
if options[:grammar]
|
5
|
+
if options[:grammar].rules[@expected]
|
6
|
+
options[:grammar].rules[@expected].parse stream, options.merge(:rule => @expected)
|
7
|
+
else
|
8
|
+
STDERR.puts "skipping #{self}: not implemented"
|
9
|
+
throw :SkipSuccess
|
10
|
+
end
|
11
|
+
else
|
12
|
+
raise "can't use #{self} without a grammar"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class AndPredicate < PackageParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
stream.must_be Stream
|
5
|
+
stream.lock do
|
6
|
+
begin
|
7
|
+
@expected.parse stream, options
|
8
|
+
rescue ParseError => e
|
9
|
+
raise ParseError.new "predicate not satisfied when parsing #{self}: #{e.to_s}", options
|
10
|
+
end
|
11
|
+
throw :PredicateSuccess
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@expected}.and?"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class NotPredicate < PackageParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
stream.must_be Stream
|
5
|
+
stream.lock do
|
6
|
+
begin
|
7
|
+
result = @expected.parse stream, options
|
8
|
+
rescue ParseError
|
9
|
+
throw :PredicateSuccess
|
10
|
+
end
|
11
|
+
raise ParseError.new "predicate not satisfied when parsing #{self}: matched #{result}", options
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@expected}.not!"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class SkipPredicate < PackageParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
stream.must_be Stream
|
5
|
+
stream.lock do
|
6
|
+
begin
|
7
|
+
@expected.parse stream, options
|
8
|
+
rescue ParseError => e
|
9
|
+
raise ParseError.new "predicate not satisfied when parsing #{self}: #{e.to_s}", options
|
10
|
+
end
|
11
|
+
throw :SkipSuccess
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@expected}.skip"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/result_cast.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class CastResult < PackageParser
|
3
|
+
attr_reader :to_class
|
4
|
+
|
5
|
+
def initialize expected, to_class
|
6
|
+
super expected
|
7
|
+
@to_class = to_class
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse! stream, options = {}
|
11
|
+
result = @expected.parse stream, options
|
12
|
+
if @to_class == Integer
|
13
|
+
result.is_a?(MatchData) ? result.to_s.to_i : result.to_i
|
14
|
+
elsif @to_class == Float
|
15
|
+
result.is_a?(MatchData) ? result.to_s.to_f : result.to_f
|
16
|
+
elsif @to_class == String
|
17
|
+
result.is_a?(Array) ? result.join : result.to_s
|
18
|
+
elsif @to_class == Symbol
|
19
|
+
result.is_a?(Array) ? result.join.to_sym : result.to_sym
|
20
|
+
elsif @to_class == Array
|
21
|
+
result.is_a?(String) ? result.split(options[:delimiter] || '') : result.to_a
|
22
|
+
else
|
23
|
+
raise "can't cast to #{@to_class}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def eql? other
|
28
|
+
other.is_a?(self.class) and other.expected == @expected and other.to_class == @to_class
|
29
|
+
end
|
30
|
+
|
31
|
+
alias :== :eql?
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class FilterResult < PackageParser
|
3
|
+
attr_reader :node, :block
|
4
|
+
|
5
|
+
def initialize expected, node = Node.subclass([:result], :arity => {:result => 0}), &block
|
6
|
+
super expected
|
7
|
+
@node = node
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse! stream, options = {}
|
12
|
+
if @node.is_a? Class
|
13
|
+
node_class = @node
|
14
|
+
else
|
15
|
+
if options[:grammar]
|
16
|
+
node_class = options[:grammar].nodes[@node]
|
17
|
+
else
|
18
|
+
raise "can't use named nodes without a grammar"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
result = @expected.parse stream, options
|
22
|
+
if result.is_a? Array
|
23
|
+
node = node_class.new result, options[:global]
|
24
|
+
else
|
25
|
+
node = node_class.new [result]
|
26
|
+
end
|
27
|
+
node.eval options[:global], &@block
|
28
|
+
end
|
29
|
+
|
30
|
+
def eql? other
|
31
|
+
other.is_a?(self.class) and other.expected == @expected and other.block == @block
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :== :eql?
|
35
|
+
end
|
36
|
+
end
|
data/lib/result_merge.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class MergeResult < PackageParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
results = @expected.parse stream, options
|
5
|
+
new_results = []
|
6
|
+
if results.respond_to? :each
|
7
|
+
results.each do |result|
|
8
|
+
if result.respond_to? :each
|
9
|
+
result.each {|n| new_results << n }
|
10
|
+
else
|
11
|
+
new_results << result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
else
|
15
|
+
new_results = results
|
16
|
+
end
|
17
|
+
new_results
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class OverrideResult < PackageParser
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize expected, options
|
6
|
+
super expected
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse! stream, options = {}
|
11
|
+
@expected.parse stream, options.merge(@options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eql? other
|
15
|
+
other.is_a?(self.class) and other.expected == @expected and other.options == @options
|
16
|
+
end
|
17
|
+
|
18
|
+
alias :== :eql?
|
19
|
+
end
|
20
|
+
end
|
data/lib/rule.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class Rule
|
3
|
+
attr_reader :parseable
|
4
|
+
|
5
|
+
def initialize name, grammar, &block
|
6
|
+
@name = name
|
7
|
+
@grammar = grammar
|
8
|
+
@parseable = nil
|
9
|
+
|
10
|
+
instance_eval &block if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def parses parseable
|
14
|
+
if @parseable
|
15
|
+
raise "parseable for rule #{@name.inspect} already defined"
|
16
|
+
else
|
17
|
+
@parseable = parseable.to_parseable
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def override options
|
22
|
+
if @parseable
|
23
|
+
@parseable = @parseable.override options
|
24
|
+
else
|
25
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def skipping parseable
|
30
|
+
if @parseable
|
31
|
+
@parseable = @parseable.override :skipping => parseable.to_parseable
|
32
|
+
else
|
33
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def simplify bool = true
|
38
|
+
if @parseable
|
39
|
+
@parseable = @parseable.override :simplify => bool
|
40
|
+
else
|
41
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def merge
|
46
|
+
if @parseable
|
47
|
+
@parseable = @parseable.merge
|
48
|
+
else
|
49
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def cast to_class
|
54
|
+
if @parseable
|
55
|
+
@parseable = @parseable.cast to_class
|
56
|
+
else
|
57
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def filter node = @name, &block
|
62
|
+
if @parseable
|
63
|
+
@grammar.nodes[@name] ||= Node.subclass([:result], :arity => {:result => 0})
|
64
|
+
@parseable = @parseable.filter node, &block
|
65
|
+
else
|
66
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def node args, options = {}
|
71
|
+
args.must_be Array
|
72
|
+
if @grammar.nodes.key? @name
|
73
|
+
raise "node #{@name.inspect} already defined"
|
74
|
+
else
|
75
|
+
parent = options[:class] || Node
|
76
|
+
@grammar.nodes[@name] = parent.subclass args, options
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def set *vars
|
81
|
+
if @parseable
|
82
|
+
@parseable = @parseable.set *vars
|
83
|
+
else
|
84
|
+
raise "parseable for rule #{@name.inspect} undefined"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/stream.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class Stream
|
3
|
+
attr_reader :pos
|
4
|
+
|
5
|
+
def initialize string
|
6
|
+
if string.is_a? File
|
7
|
+
@string = ''
|
8
|
+
string.each_char {|n| @string << n }
|
9
|
+
else
|
10
|
+
@string = string.to_s
|
11
|
+
end
|
12
|
+
@pos = 0
|
13
|
+
#index_lines
|
14
|
+
end
|
15
|
+
|
16
|
+
def getc
|
17
|
+
if @pos < @string.length
|
18
|
+
@pos += 1
|
19
|
+
@string[@pos - 1]
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def match regexp
|
26
|
+
match = @string[@pos..-1].match /\A#{regexp}/
|
27
|
+
if match
|
28
|
+
@pos += match.to_s.length
|
29
|
+
match
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def look len = 10
|
36
|
+
if @string.length - @pos > len
|
37
|
+
"\"#{@string[@pos, len - 3] + '...'}\""
|
38
|
+
else
|
39
|
+
"\"#{@string[@pos..-1]}\""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def goto pos
|
44
|
+
if pos < 0
|
45
|
+
@pos = 0
|
46
|
+
elsif pos > @string.length
|
47
|
+
@pos = @string.length
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def lock &block
|
52
|
+
safe_pos = @pos
|
53
|
+
begin
|
54
|
+
catch :PredicateSuccess do
|
55
|
+
return block.call
|
56
|
+
end
|
57
|
+
@pos = safe_pos
|
58
|
+
throw :SkipSuccess
|
59
|
+
rescue ParseError => e
|
60
|
+
@pos = safe_pos
|
61
|
+
#e.line ||= self.line
|
62
|
+
#e.column ||= self.column
|
63
|
+
raise e
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
@string.dup
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_stream
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def length
|
76
|
+
@string.length
|
77
|
+
end
|
78
|
+
|
79
|
+
alias :size :length
|
80
|
+
|
81
|
+
def line
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def column
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def index_lines
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def bsearch
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/var_get.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class GetVar < BasicParser
|
3
|
+
attr_reader :parser
|
4
|
+
|
5
|
+
def initialize expected, parser
|
6
|
+
super expected
|
7
|
+
@parser = parser.to_parseable
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse! stream, options = {}
|
11
|
+
if @expected.is_a? Symbol
|
12
|
+
if options[:global] and options[:global].key?(@expected)
|
13
|
+
source = options[:global][@expected]
|
14
|
+
else
|
15
|
+
raise "$#{@expected} undefined"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
source = @expected
|
19
|
+
end
|
20
|
+
result = @parser.parse stream, options
|
21
|
+
if source.is_a?(MatchData) and result.is_a?(MatchData) and source.to_s == result.to_s and source.regexp == result.regexp
|
22
|
+
result
|
23
|
+
elsif source == result
|
24
|
+
result
|
25
|
+
else
|
26
|
+
raise ParseError.new "unexpected result #{result.inspect} (expected #{source.inspect}) when parsing #{@parser}", options
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def eql? other
|
31
|
+
other.is_a?(self.class) and other.expected == @expected and other.parser == @parser
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :== :eql?
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
"#{@expected.is_a?(Symbol) ? "$#{@expected}" : @expected.inspect} (match)"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/var_insert.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class InsertVar < BasicParser
|
3
|
+
def parse! stream, options = {}
|
4
|
+
if @expected.is_a? Symbol
|
5
|
+
if options[:global] and options[:global].key?(@expected)
|
6
|
+
options[:global][@expected]
|
7
|
+
else
|
8
|
+
raise "$#{@expected} undefined"
|
9
|
+
end
|
10
|
+
else
|
11
|
+
@expected
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@expected.is_a?(Symbol) ? "$#{@expected}" : @expected.inspect} (ins)"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/var_set.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kaiseki
|
2
|
+
class SetVar < PackageParser
|
3
|
+
attr_reader :vars
|
4
|
+
|
5
|
+
def initialize expected, *vars
|
6
|
+
super expected
|
7
|
+
@vars = []
|
8
|
+
vars.each {|n| @vars << n }
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse! stream, options = {}
|
12
|
+
result = @expected.parse stream, options
|
13
|
+
options[:global] ||= {}
|
14
|
+
@vars.each {|n| options[:global][n] = result }
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
def eql? other
|
19
|
+
other.is_a?(self.class) and other.expected == @expected and other.vars == @vars
|
20
|
+
end
|
21
|
+
|
22
|
+
alias :== :eql?
|
23
|
+
end
|
24
|
+
end
|