kaiseki 0.0.3 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/README +0 -0
  2. data/lib/action.rb +8 -0
  3. data/lib/grammar.rb +88 -0
  4. data/lib/kaiseki.rb +54 -48
  5. data/lib/mod_file.rb +5 -0
  6. data/lib/mod_kernel.rb +11 -0
  7. data/lib/mod_object.rb +11 -0
  8. data/lib/mod_proc.rb +7 -0
  9. data/lib/mod_regexp.rb +7 -0
  10. data/lib/mod_string.rb +11 -0
  11. data/lib/mod_symbol.rb +27 -0
  12. data/lib/node.rb +78 -0
  13. data/lib/parse_error.rb +16 -0
  14. data/lib/parse_result.rb +21 -0
  15. data/lib/parseable.rb +67 -0
  16. data/lib/{grammar/parslet.rb → parser_basic.rb} +7 -12
  17. data/lib/parser_choice.rb +24 -0
  18. data/lib/parser_eof.rb +27 -0
  19. data/lib/parser_multi.rb +27 -0
  20. data/lib/parser_package.rb +11 -0
  21. data/lib/parser_regexp.rb +19 -0
  22. data/lib/parser_repeat.rb +68 -0
  23. data/lib/parser_sequence.rb +41 -0
  24. data/lib/parser_string.rb +18 -0
  25. data/lib/parser_symbol.rb +16 -0
  26. data/lib/predicate_and.rb +19 -0
  27. data/lib/predicate_not.rb +19 -0
  28. data/lib/predicate_skip.rb +19 -0
  29. data/lib/result_cast.rb +33 -0
  30. data/lib/result_filter.rb +36 -0
  31. data/lib/result_merge.rb +20 -0
  32. data/lib/result_override.rb +20 -0
  33. data/lib/rule.rb +88 -0
  34. data/lib/stream.rb +98 -0
  35. data/lib/var_get.rb +40 -0
  36. data/lib/var_insert.rb +19 -0
  37. data/lib/var_set.rb +24 -0
  38. metadata +45 -40
  39. data/lib/additions/proc.rb +0 -7
  40. data/lib/additions/regexp.rb +0 -7
  41. data/lib/additions/string.rb +0 -7
  42. data/lib/additions/symbol.rb +0 -19
  43. data/lib/grammar/and_predicate.rb +0 -22
  44. data/lib/grammar/array_result.rb +0 -16
  45. data/lib/grammar/eof_parslet.rb +0 -32
  46. data/lib/grammar/grammar.rb +0 -113
  47. data/lib/grammar/grammar_node.rb +0 -31
  48. data/lib/grammar/location_tracking.rb +0 -57
  49. data/lib/grammar/log_node.rb +0 -21
  50. data/lib/grammar/node.rb +0 -59
  51. data/lib/grammar/not_predicate.rb +0 -22
  52. data/lib/grammar/parse_error.rb +0 -21
  53. data/lib/grammar/parse_logger.rb +0 -27
  54. data/lib/grammar/parse_result.rb +0 -33
  55. data/lib/grammar/parslet_choice.rb +0 -25
  56. data/lib/grammar/parslet_combination.rb +0 -35
  57. data/lib/grammar/parslet_combining.rb +0 -57
  58. data/lib/grammar/parslet_logging.rb +0 -22
  59. data/lib/grammar/parslet_merger.rb +0 -50
  60. data/lib/grammar/parslet_omission.rb +0 -20
  61. data/lib/grammar/parslet_repetition.rb +0 -65
  62. data/lib/grammar/parslet_sequence.rb +0 -45
  63. data/lib/grammar/predicate.rb +0 -30
  64. data/lib/grammar/proc_parslet.rb +0 -18
  65. data/lib/grammar/regexp_parslet.rb +0 -25
  66. data/lib/grammar/stream.rb +0 -90
  67. data/lib/grammar/string_parslet.rb +0 -29
  68. data/lib/grammar/string_result.rb +0 -16
  69. 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
@@ -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
@@ -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