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
@@ -1,57 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
module ParsletCombining
|
3
|
-
def sequence other
|
4
|
-
ParsletSequence.new self.to_parseable, other.to_parseable
|
5
|
-
end
|
6
|
-
|
7
|
-
alias :& :sequence
|
8
|
-
|
9
|
-
def merge other
|
10
|
-
ParsletMerger.new self.to_parseable, other.to_parseable
|
11
|
-
end
|
12
|
-
|
13
|
-
alias :>> :merge
|
14
|
-
|
15
|
-
def choose other
|
16
|
-
ParsletChoice.new self.to_parseable, other.to_parseable
|
17
|
-
end
|
18
|
-
|
19
|
-
alias :| :choose
|
20
|
-
|
21
|
-
def repeat min, max = nil
|
22
|
-
ParsletRepetition.new self.to_parseable, min, max
|
23
|
-
end
|
24
|
-
|
25
|
-
def optional
|
26
|
-
repeat 0, 1
|
27
|
-
end
|
28
|
-
|
29
|
-
alias :zero_or_one :optional
|
30
|
-
|
31
|
-
def zero_or_more
|
32
|
-
repeat 0
|
33
|
-
end
|
34
|
-
|
35
|
-
def one_or_more
|
36
|
-
repeat 1
|
37
|
-
end
|
38
|
-
|
39
|
-
def and_predicate
|
40
|
-
AndPredicate.new self.to_parseable
|
41
|
-
end
|
42
|
-
|
43
|
-
alias :and? :and_predicate
|
44
|
-
|
45
|
-
def not_predicate
|
46
|
-
NotPredicate.new self.to_parseable
|
47
|
-
end
|
48
|
-
|
49
|
-
alias :not! :not_predicate
|
50
|
-
|
51
|
-
def omission
|
52
|
-
ParsletOmission.new self.to_parseable
|
53
|
-
end
|
54
|
-
|
55
|
-
alias :skip :omission
|
56
|
-
end
|
57
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
module ParsletLogging
|
3
|
-
def log parse_logger = nil, &block
|
4
|
-
if parse_logger
|
5
|
-
node = LogNode.new self
|
6
|
-
parse_logger.root ? parse_logger.add(node) : parse_logger.root = node
|
7
|
-
parse_logger.push node
|
8
|
-
begin
|
9
|
-
node.result = block.call
|
10
|
-
parse_logger.pop
|
11
|
-
node.result
|
12
|
-
rescue ParseError => e
|
13
|
-
node.result = e
|
14
|
-
parse_logger.pop
|
15
|
-
raise e
|
16
|
-
end
|
17
|
-
else
|
18
|
-
block.call
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class ParsletMerger < ParsletCombination
|
3
|
-
def initialize *components
|
4
|
-
super *components
|
5
|
-
@delimiter = '&'
|
6
|
-
end
|
7
|
-
|
8
|
-
alias :>> :append
|
9
|
-
|
10
|
-
def parse stream, options = {}
|
11
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
12
|
-
parsed = ArrayResult.new
|
13
|
-
pos = stream.pos
|
14
|
-
@components.each do |parseable|
|
15
|
-
catch :PredicateSuccess do
|
16
|
-
begin
|
17
|
-
result = parseable.parse stream, options
|
18
|
-
if result.respond_to? :each
|
19
|
-
result.each {|n| parsed << n }
|
20
|
-
else
|
21
|
-
parsed << result
|
22
|
-
end
|
23
|
-
rescue ParseError => e
|
24
|
-
if options[:skipping]
|
25
|
-
begin
|
26
|
-
options[:skipping].parse stream, options.merge(:skipping => nil, :logger => nil)
|
27
|
-
redo
|
28
|
-
rescue ParseError
|
29
|
-
stream.rewind pos
|
30
|
-
raise e
|
31
|
-
end
|
32
|
-
else
|
33
|
-
stream.rewind pos
|
34
|
-
raise e
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
if options[:simplify]
|
40
|
-
if parsed.length == 1
|
41
|
-
parsed.first
|
42
|
-
else
|
43
|
-
parsed
|
44
|
-
end
|
45
|
-
else
|
46
|
-
parsed
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class ParsletOmission < Predicate
|
3
|
-
def initialize parseable
|
4
|
-
super parseable
|
5
|
-
@prefix = 'skip'
|
6
|
-
end
|
7
|
-
|
8
|
-
def parse stream, options = {}
|
9
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
10
|
-
pos = stream.pos
|
11
|
-
begin
|
12
|
-
@parseable.parse stream, options
|
13
|
-
rescue ParseError => e
|
14
|
-
stream.rewind pos
|
15
|
-
raise e
|
16
|
-
end
|
17
|
-
throw :PredicateSuccess
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class ParsletRepetition
|
3
|
-
include ParsletCombining
|
4
|
-
|
5
|
-
attr_reader :parseable, :min, :max
|
6
|
-
|
7
|
-
def initialize parseable, min, max = nil
|
8
|
-
@parseable = parseable
|
9
|
-
@min = min
|
10
|
-
@max = max
|
11
|
-
end
|
12
|
-
|
13
|
-
def parse stream, options = {}
|
14
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
15
|
-
parsed = ArrayResult.new
|
16
|
-
pos = stream.pos
|
17
|
-
while @max.nil? or parsed.length < @max
|
18
|
-
begin
|
19
|
-
parsed << @parseable.parse(stream, options)
|
20
|
-
rescue ParseError
|
21
|
-
if options[:skipping]
|
22
|
-
begin
|
23
|
-
options[:skipping].parse stream, options.merge(:skipping => nil, :logger => nil)
|
24
|
-
redo
|
25
|
-
rescue ParseError
|
26
|
-
break
|
27
|
-
end
|
28
|
-
else
|
29
|
-
break
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
if parsed.length < @min
|
35
|
-
stream.rewind pos
|
36
|
-
raise ParseError.new "required #{@min} match#{'es' unless @min == 1} but obtained #{parsed.length} (expected `#{@parseable}')",
|
37
|
-
options.merge(:line_end => stream.line, :column_end => stream.column)
|
38
|
-
else
|
39
|
-
if options[:simplify]
|
40
|
-
if @min == 0 and @max == 1
|
41
|
-
parsed.length == 0 ? nil : parsed.first
|
42
|
-
else
|
43
|
-
parsed
|
44
|
-
end
|
45
|
-
else
|
46
|
-
parsed
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_s
|
52
|
-
"repeat(#{@min}, #{@max}): #{@parseable}"
|
53
|
-
end
|
54
|
-
|
55
|
-
def to_parseable
|
56
|
-
self
|
57
|
-
end
|
58
|
-
|
59
|
-
def eql? other
|
60
|
-
other.is_a?(ParsletRepetition) and other.parseable == @parseable and other.min == @min and other.max == @max
|
61
|
-
end
|
62
|
-
|
63
|
-
alias :== :eql?
|
64
|
-
end
|
65
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class ParsletSequence < ParsletCombination
|
3
|
-
def initialize *components
|
4
|
-
super *components
|
5
|
-
@delimiter = '&'
|
6
|
-
end
|
7
|
-
|
8
|
-
alias :& :append
|
9
|
-
|
10
|
-
def parse stream, options = {}
|
11
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
12
|
-
parsed = ArrayResult.new
|
13
|
-
pos = stream.pos
|
14
|
-
@components.each do |parseable|
|
15
|
-
catch :PredicateSuccess do
|
16
|
-
begin
|
17
|
-
parsed << parseable.parse(stream, options)
|
18
|
-
rescue ParseError => e
|
19
|
-
if options[:skipping]
|
20
|
-
begin
|
21
|
-
options[:skipping].parse stream, options.merge(:skipping => nil, :logger => nil)
|
22
|
-
redo
|
23
|
-
rescue ParseError
|
24
|
-
stream.rewind pos
|
25
|
-
raise e
|
26
|
-
end
|
27
|
-
else
|
28
|
-
stream.rewind pos
|
29
|
-
raise e
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
if options[:simplify]
|
35
|
-
if parsed.length == 1
|
36
|
-
parsed.first
|
37
|
-
else
|
38
|
-
parsed
|
39
|
-
end
|
40
|
-
else
|
41
|
-
parsed
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/grammar/predicate.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class Predicate
|
3
|
-
include ParsletCombining
|
4
|
-
|
5
|
-
attr_reader :parseable
|
6
|
-
|
7
|
-
def initialize parseable
|
8
|
-
@parseable = parseable
|
9
|
-
@prefix = 'predicate'
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse *args
|
13
|
-
raise NotImplementedError
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_s
|
17
|
-
"<#{@prefix}:#{@parseable}>"
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_parseable
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def eql? other
|
25
|
-
other.is_a?(self.class) and other.parseable == @parseable
|
26
|
-
end
|
27
|
-
|
28
|
-
alias :== :eql?
|
29
|
-
end
|
30
|
-
end
|
data/lib/grammar/proc_parslet.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class ProcParslet < Parslet
|
3
|
-
def initialize procedure = nil, &block
|
4
|
-
raise ArgumentError, "can't have both an argument and a block" if block_given? and procedure
|
5
|
-
if block_given?
|
6
|
-
super block
|
7
|
-
else
|
8
|
-
raise TypeError, "can't convert #{procedure.class} into Proc" unless procedure.is_a? Proc
|
9
|
-
super procedure
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def parse stream, options = {}
|
14
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
15
|
-
@expected.call stream, options
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class RegexpParslet < Parslet
|
3
|
-
def initialize regexp
|
4
|
-
raise TypeError, "can't convert #{regexp.class} into Regexp" unless regexp.is_a? Regexp
|
5
|
-
super regexp
|
6
|
-
end
|
7
|
-
|
8
|
-
def parse stream, options = {}
|
9
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
10
|
-
parsed = StringResult.new
|
11
|
-
pos = stream.pos
|
12
|
-
match = stream.getc(-1).match /\A#{@expected}/
|
13
|
-
if match
|
14
|
-
stream.rewind pos + match.to_s.length
|
15
|
-
parsed << match.to_s
|
16
|
-
parsed.info[:captures] = match.captures
|
17
|
-
parsed
|
18
|
-
else
|
19
|
-
stream.rewind pos
|
20
|
-
raise ParseError.new "non-matching characters while parsing `#{@expected}'",
|
21
|
-
options.merge(:line_end => stream.line, :column_end => stream.column)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/grammar/stream.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class Stream
|
3
|
-
attr_reader :file
|
4
|
-
|
5
|
-
def initialize source
|
6
|
-
if source.is_a? String
|
7
|
-
@file = nil
|
8
|
-
@string = source.dup
|
9
|
-
elsif source.is_a? File
|
10
|
-
@file = source.path
|
11
|
-
@string = ''
|
12
|
-
source.each_char {|c| @string << c }
|
13
|
-
else
|
14
|
-
raise TypeError, "can't convert #{source.class} into Stream"
|
15
|
-
end
|
16
|
-
@pos = 0
|
17
|
-
@newlines = []
|
18
|
-
start = 0
|
19
|
-
@string.length.times do |i|
|
20
|
-
if @string[i] == "\n"
|
21
|
-
@newlines << [start, i]
|
22
|
-
start = i + 1
|
23
|
-
end
|
24
|
-
end
|
25
|
-
@newlines << [start, @string.length]
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_s
|
29
|
-
@string.dup
|
30
|
-
end
|
31
|
-
|
32
|
-
def length
|
33
|
-
@string.length
|
34
|
-
end
|
35
|
-
|
36
|
-
def pos
|
37
|
-
@pos
|
38
|
-
end
|
39
|
-
|
40
|
-
def line
|
41
|
-
bsearch @pos, 0, @newlines.length
|
42
|
-
end
|
43
|
-
|
44
|
-
def column
|
45
|
-
@pos - @newlines[self.line].first
|
46
|
-
end
|
47
|
-
|
48
|
-
def getc num = 0
|
49
|
-
if num == 0
|
50
|
-
char = @string[@pos]
|
51
|
-
if char
|
52
|
-
@pos += 1
|
53
|
-
char
|
54
|
-
end
|
55
|
-
elsif num > 0
|
56
|
-
string = @string[@pos..(@pos + num - 1)]
|
57
|
-
@pos += string.length
|
58
|
-
string
|
59
|
-
else
|
60
|
-
string = @string[@pos..num]
|
61
|
-
@pos += string.length
|
62
|
-
string
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def rewind pos = 0
|
67
|
-
if pos < 0
|
68
|
-
pos = @string.length + pos + 1
|
69
|
-
@pos = pos < 0 ? 0 : pos
|
70
|
-
elsif pos > @string.length
|
71
|
-
@pos = @string.length
|
72
|
-
else
|
73
|
-
@pos = pos
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
def bsearch value, low, high
|
79
|
-
return nil if high < low
|
80
|
-
mid = low + (high - low) / 2
|
81
|
-
if value < @newlines[mid].first
|
82
|
-
bsearch value, low, mid - 1
|
83
|
-
elsif value > @newlines[mid].last
|
84
|
-
bsearch value, mid + 1, high
|
85
|
-
else
|
86
|
-
mid
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class StringParslet < Parslet
|
3
|
-
def initialize string
|
4
|
-
raise TypeError, "can't convert #{string.class} into String" unless string.is_a? String
|
5
|
-
super string
|
6
|
-
end
|
7
|
-
|
8
|
-
def parse stream, options = {}
|
9
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
10
|
-
parsed = StringResult.new
|
11
|
-
pos = stream.pos
|
12
|
-
@expected.each_char do |char|
|
13
|
-
actual = stream.getc
|
14
|
-
if actual.nil?
|
15
|
-
stream.rewind pos
|
16
|
-
raise ParseError.new "unexpected end-of-string (expected `#{char}') while parsing `#{@expected}'",
|
17
|
-
options.merge(:line_end => stream.line, :column_end => stream.column)
|
18
|
-
elsif actual != char
|
19
|
-
stream.rewind pos
|
20
|
-
raise ParseError.new "unexpected character `#{actual}' (expected `#{char}') while parsing `#{@expected}'",
|
21
|
-
options.merge(:line_end => stream.line, :column_end => stream.column)
|
22
|
-
else
|
23
|
-
parsed << actual
|
24
|
-
end
|
25
|
-
end
|
26
|
-
parsed
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class StringResult < String
|
3
|
-
include LocationTracking
|
4
|
-
|
5
|
-
attr_reader :info
|
6
|
-
|
7
|
-
def initialize string = '', info = {}
|
8
|
-
super string
|
9
|
-
self.line_start = info[:line_start] if info.key? :line_start
|
10
|
-
self.column_start = info[:column_start] if info.key? :column_start
|
11
|
-
self.line_end = info[:line_end] if info.key? :line_end
|
12
|
-
self.column_end = info[:column_end] if info.key? :column_end
|
13
|
-
@info = info
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Kaiseki
|
2
|
-
class SymbolParslet < Parslet
|
3
|
-
include ParsletLogging
|
4
|
-
|
5
|
-
def initialize symbol
|
6
|
-
raise TypeError, "can't convert #{symbol.class} into Symbol" unless symbol.is_a? Symbol
|
7
|
-
super symbol
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse stream, options = {}
|
11
|
-
raise TypeError, "can't convert #{stream.class} into Stream" unless stream.is_a? Stream
|
12
|
-
raise ArgumentError, "parsing requires a grammar" unless options.key? :grammar
|
13
|
-
log options[:logger] do
|
14
|
-
options[:grammar].wrap stream, options.merge(:rule => @expected)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
":#{@expected}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|