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