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.
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
data/README ADDED
File without changes
data/lib/action.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Kaiseki
2
+ class Action < BasicParser
3
+ def parse! stream, options = {}
4
+ Node.new([], options[:global]).eval options[:global], &@expected
5
+ throw :SkipSuccess
6
+ end
7
+ end
8
+ end
data/lib/grammar.rb ADDED
@@ -0,0 +1,88 @@
1
+ module Kaiseki
2
+ class Grammar
3
+ attr_reader :rules, :nodes
4
+ attr_accessor :starting_rule, :skipping_rule, :simplify
5
+
6
+ def initialize &block
7
+ @rules = Hash.new {|hash, key| raise "rule #{key.inspect} undefined" }
8
+ @nodes = Hash.new {|hash, key| raise "node #{key.inspect} undefined" }
9
+ @starting_rule = nil
10
+ @skipping_rule = nil
11
+ @simplify = true
12
+
13
+ instance_eval &block if block_given?
14
+ end
15
+
16
+ def parse stream, options = {}
17
+ ParseResult.new do
18
+ parse! stream.to_stream, options
19
+ end
20
+ end
21
+
22
+ def parse! stream, options = {}
23
+ stream.must_be Stream
24
+ stream.lock do
25
+ default_options = {
26
+ :grammar => self,
27
+ :rule => 'main',
28
+ :skipping => @skipping_rule,
29
+ :simplify => @simplify,
30
+ :global => {},
31
+ }
32
+ if @starting_rule
33
+ @starting_rule.parse stream, default_options.merge(options)
34
+ else
35
+ raise "starting rule undefined"
36
+ end
37
+ end
38
+ end
39
+
40
+ def starting parseable
41
+ raise "starting rule already defined" if @starting_rule
42
+ @starting_rule = parseable
43
+ end
44
+
45
+ def skipping parseable
46
+ raise "skipping rule already defined" if @skipping_rule
47
+ @skipping_rule = parseable
48
+ end
49
+
50
+ def simplify bool = true
51
+ @simplify = bool
52
+ end
53
+
54
+ def rule name, parseable = nil, &block
55
+ if @rules.key? name
56
+ raise "rule #{name.inspect} already defined"
57
+ else
58
+ if parseable and block_given?
59
+ raise ArgumentError, "wrong number of arguments; the second argument is mutually exclusive with a block"
60
+ elsif parseable
61
+ @rules[name] = parseable.to_parseable
62
+ elsif block_given?
63
+ @rules[name] = Rule.new(name, self, &block).parseable
64
+ else
65
+ @rules[name] = nil
66
+ end
67
+ end
68
+ end
69
+
70
+ def action name, &block
71
+ if @rules.key? name
72
+ raise "rule #{name.inspect} already defined"
73
+ else
74
+ @rules[name] = block.to_parseable
75
+ end
76
+ end
77
+
78
+ def node name, args, options = {}
79
+ args.must_be Array
80
+ if @nodes.key? name
81
+ raise "node #{name.inspect} already defined"
82
+ else
83
+ parent = options[:class] || Node
84
+ @nodes[name] = parent.subclass args, options
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/kaiseki.rb CHANGED
@@ -1,49 +1,55 @@
1
- require 'pathname'
2
-
3
1
  module Kaiseki
4
- VERSION = '0.0.3'
5
- end
6
-
7
- dir_path = Pathname.new(__FILE__).realpath.dirname
8
-
9
- [
10
- 'grammar/parslet_combining',
11
- 'grammar/parslet_logging',
12
- 'grammar/location_tracking',
13
- 'grammar/parse_error',
14
- 'grammar/parse_result',
15
- 'grammar/string_result',
16
- 'grammar/array_result',
17
-
18
- 'grammar/stream',
19
- 'grammar/parslet',
20
- 'grammar/proc_parslet',
21
- 'grammar/regexp_parslet',
22
- 'grammar/string_parslet',
23
- 'grammar/symbol_parslet',
24
- 'grammar/eof_parslet',
25
-
26
- 'grammar/parslet_combination',
27
- 'grammar/parslet_sequence',
28
- 'grammar/parslet_merger',
29
- 'grammar/parslet_choice',
30
- 'grammar/parslet_repetition',
31
-
32
- 'grammar/predicate',
33
- 'grammar/and_predicate',
34
- 'grammar/not_predicate',
35
- 'grammar/parslet_omission',
36
-
37
- 'grammar/grammar',
38
- 'grammar/parse_logger',
39
- 'grammar/node',
40
- 'grammar/grammar_node',
41
- 'grammar/log_node',
42
-
43
- 'additions/proc',
44
- 'additions/regexp',
45
- 'additions/string',
46
- 'additions/symbol',
47
- ].each do |path|
48
- require dir_path + path
49
- end
2
+ VERSION = '1.0.1'
3
+ file_path = File.dirname __FILE__
4
+
5
+ #load basic kaiseki classes
6
+ require file_path + '/stream'
7
+ require file_path + '/parseable'
8
+ require file_path + '/parse_error'
9
+ require file_path + '/parse_result'
10
+
11
+ #load standard class modifiers
12
+ require file_path + '/mod_object'
13
+ require file_path + '/mod_string'
14
+ require file_path + '/mod_regexp'
15
+ require file_path + '/mod_symbol'
16
+ require file_path + '/mod_proc'
17
+ require file_path + '/mod_file'
18
+ require file_path + '/mod_kernel'
19
+
20
+ #load parsers
21
+ require file_path + '/parser_basic'
22
+ require file_path + '/parser_string'
23
+ require file_path + '/parser_regexp'
24
+ require file_path + '/parser_symbol'
25
+ require file_path + '/parser_eof'
26
+
27
+ require file_path + '/parser_multi'
28
+ require file_path + '/parser_sequence'
29
+ require file_path + '/parser_choice'
30
+ require file_path + '/parser_repeat'
31
+
32
+ require file_path + '/parser_package'
33
+
34
+ #load predicates
35
+ require file_path + '/predicate_and'
36
+ require file_path + '/predicate_not'
37
+ require file_path + '/predicate_skip'
38
+
39
+ #load result modifiers
40
+ require file_path + '/result_override'
41
+ require file_path + '/result_merge'
42
+ require file_path + '/result_cast'
43
+ require file_path + '/result_filter'
44
+ require file_path + '/node'
45
+
46
+ #load grammar classes
47
+ require file_path + '/grammar'
48
+ require file_path + '/rule'
49
+ require file_path + '/action'
50
+
51
+ #load varible manipulators
52
+ require file_path + '/var_set'
53
+ require file_path + '/var_get'
54
+ require file_path + '/var_insert'
55
+ end
data/lib/mod_file.rb ADDED
@@ -0,0 +1,5 @@
1
+ class File
2
+ def to_stream
3
+ Kaiseki::Stream.new self
4
+ end
5
+ end
data/lib/mod_kernel.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Kernel
2
+ private
3
+
4
+ def get var, parser
5
+ Kaiseki::GetVar.new var, parser
6
+ end
7
+
8
+ def insert var
9
+ Kaiseki::InsertVar.new var
10
+ end
11
+ end
data/lib/mod_object.rb ADDED
@@ -0,0 +1,11 @@
1
+ class Object
2
+ def must_be item
3
+ raise TypeError, "can't convert #{self.class} into #{item}" unless self.is_a? item
4
+ true
5
+ end
6
+
7
+ def must_have property, value
8
+ raise StandardError, "##{property} must be #{value} (#{self.send(property)})" unless self.send(property) == value
9
+ true
10
+ end
11
+ end
data/lib/mod_proc.rb ADDED
@@ -0,0 +1,7 @@
1
+ class Proc
2
+ include Kaiseki::Parseable
3
+
4
+ def to_parseable
5
+ Kaiseki::Action.new self
6
+ end
7
+ end
data/lib/mod_regexp.rb ADDED
@@ -0,0 +1,7 @@
1
+ class Regexp
2
+ include Kaiseki::Parseable
3
+
4
+ def to_parseable
5
+ Kaiseki::RegexpParser.new self
6
+ end
7
+ end
data/lib/mod_string.rb ADDED
@@ -0,0 +1,11 @@
1
+ class String
2
+ include Kaiseki::Parseable
3
+
4
+ def to_parseable
5
+ Kaiseki::StringParser.new self
6
+ end
7
+
8
+ def to_stream
9
+ Kaiseki::Stream.new self
10
+ end
11
+ end
data/lib/mod_symbol.rb ADDED
@@ -0,0 +1,27 @@
1
+ class Symbol
2
+ include Kaiseki::Parseable
3
+
4
+ def to_parseable
5
+ if self == :EOF
6
+ Kaiseki::EOFParser.new
7
+ else
8
+ Kaiseki::SymbolParser.new self
9
+ end
10
+ end
11
+
12
+ def to_instance_variable
13
+ if self[0] == '@'
14
+ self
15
+ else
16
+ :"@#{self}"
17
+ end
18
+ end
19
+
20
+ def from_instance_variable
21
+ if self[0] == '@'
22
+ self[1..-1].to_sym
23
+ else
24
+ self
25
+ end
26
+ end
27
+ end
data/lib/node.rb ADDED
@@ -0,0 +1,78 @@
1
+ module Kaiseki
2
+ class Node
3
+ def initialize args = [], global = nil
4
+ args.must_be Array
5
+ if global
6
+ global.each_pair do |key, value|
7
+ instance_variable_set key.to_instance_variable, value
8
+ end
9
+ end
10
+ list = args.reverse
11
+ self.class.arg_names.each do |name|
12
+ value = []
13
+ while 0 >= self.class.arity[name] or value.length < self.class.arity[name]
14
+ if !list.empty?
15
+ value << list.pop
16
+ elsif value.empty? and self.class.defaults.key?(name)
17
+ value << self.class.defaults[name]
18
+ break
19
+ else
20
+ if self.class.arity[name] <= 0
21
+ break
22
+ else
23
+ raise ArgumentError, "wrong number of arguments (#{value.length} for #{self.class.arity[name]})"
24
+ end
25
+ end
26
+ end
27
+ if self.class.arity[name] == 1
28
+ value = value[0]
29
+ elsif self.class.arity[name] == 0
30
+ if value.length < 1
31
+ value = nil
32
+ elsif value.length == 1
33
+ value = value[0]
34
+ end
35
+ end
36
+ instance_variable_set name.to_instance_variable, value
37
+ end
38
+ end
39
+
40
+ def eval global = nil, &block
41
+ value = instance_eval &block
42
+ if global
43
+ (instance_variables.collect {|n| n.from_instance_variable } - self.class.arg_names).each do |n|
44
+ global[n] = instance_variable_get n.to_instance_variable
45
+ end
46
+ end
47
+ value
48
+ end
49
+ end
50
+
51
+ class << Node
52
+ def subclass args, options = {}
53
+ args.must_be Array
54
+ Class.new(self).bind args, options
55
+ end
56
+
57
+ def bind args, options = {}
58
+ args.must_be Array
59
+ raise "can't bind parent NodeClass" if self == Node
60
+ define_singleton_method(:arg_names) { args }
61
+ define_singleton_method(:arity) { Hash.new {|hash, key| 1 }.merge(options[:arity] || {}) }
62
+ define_singleton_method(:defaults) { options[:defaults] || {} }
63
+ self
64
+ end
65
+
66
+ def arg_names
67
+ []
68
+ end
69
+
70
+ def arity
71
+ {}
72
+ end
73
+
74
+ def defaults
75
+ {}
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,16 @@
1
+ module Kaiseki
2
+ class ParseError < StandardError
3
+ attr_accessor :rule, :line, :column
4
+
5
+ def initialize string, options
6
+ super string
7
+ @rule = options[:rule]
8
+ @line = nil
9
+ @column = nil
10
+ end
11
+
12
+ def verbose
13
+ to_s
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Kaiseki
2
+ class ParseResult
3
+ attr_reader :result, :error
4
+
5
+ def initialize &block
6
+ begin
7
+ catch :SkipSuccess do
8
+ @result = block.call
9
+ return
10
+ end
11
+ @result = '(skipped)'
12
+ rescue ParseError => e
13
+ @error = e
14
+ end
15
+ end
16
+
17
+ def has_errors?
18
+ !!@error
19
+ end
20
+ end
21
+ end
data/lib/parseable.rb ADDED
@@ -0,0 +1,67 @@
1
+ module Kaiseki
2
+ module Parseable
3
+ def to_parseable
4
+ self
5
+ end
6
+
7
+ def parse stream, options = {}
8
+ self.to_parseable.parse! stream.to_stream, options
9
+ end
10
+
11
+ def & other
12
+ SequenceParser.new self, other
13
+ end
14
+
15
+ def | other
16
+ ChoiceParser.new self, other
17
+ end
18
+
19
+ def repeat min, max = nil
20
+ RepeatParser.new self, min, max
21
+ end
22
+
23
+ def optional
24
+ repeat 0, 1
25
+ end
26
+
27
+ def zero_or_more
28
+ repeat 0
29
+ end
30
+
31
+ def one_or_more
32
+ repeat 1
33
+ end
34
+
35
+ def and?
36
+ AndPredicate.new self
37
+ end
38
+
39
+ def not!
40
+ NotPredicate.new self
41
+ end
42
+
43
+ def skip
44
+ SkipPredicate.new self
45
+ end
46
+
47
+ def override options
48
+ OverrideResult.new self, options
49
+ end
50
+
51
+ def merge
52
+ MergeResult.new self
53
+ end
54
+
55
+ def cast to_class
56
+ CastResult.new self, to_class
57
+ end
58
+
59
+ def filter node = Node.subclass([:result], :arity => {:result => 0}), &block
60
+ FilterResult.new self, node, &block
61
+ end
62
+
63
+ def set *vars
64
+ SetVar.new self, *vars
65
+ end
66
+ end
67
+ end
@@ -1,29 +1,24 @@
1
1
  module Kaiseki
2
- class Parslet
3
- include ParsletCombining
4
-
2
+ class BasicParser
3
+ include Parseable
5
4
  attr_reader :expected
6
5
 
7
6
  def initialize expected
8
7
  @expected = expected
9
8
  end
10
9
 
11
- def parse *args
10
+ def parse! stream, options = {}
12
11
  raise NotImplementedError
13
12
  end
14
13
 
15
- def to_s
16
- "#{@expected}"
17
- end
18
-
19
- def to_parseable
20
- self
21
- end
22
-
23
14
  def eql? other
24
15
  other.is_a?(self.class) and other.expected == @expected
25
16
  end
26
17
 
27
18
  alias :== :eql?
19
+
20
+ def to_s
21
+ @expected.inspect
22
+ end
28
23
  end
29
24
  end
@@ -0,0 +1,24 @@
1
+ module Kaiseki
2
+ class ChoiceParser < MultiParser
3
+ def parse! stream, options = {}
4
+ stream.must_be Stream
5
+ stream.lock do
6
+ error = true
7
+ @expected.each do |n|
8
+ begin
9
+ return n.parse stream, options
10
+ rescue ParseError
11
+ next
12
+ end
13
+ end
14
+ raise ParseError.new "no valid alternatives when parsing #{self}", options
15
+ end
16
+ end
17
+
18
+ alias :| :append
19
+
20
+ def delimiter
21
+ '|'
22
+ end
23
+ end
24
+ end
data/lib/parser_eof.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Kaiseki
2
+ class EOFParser
3
+ include Parseable
4
+
5
+ def parse! stream, options = {}
6
+ stream.must_be Stream
7
+ stream.lock do
8
+ actual = stream.getc
9
+ if actual
10
+ raise ParseError.new "unexpected character \"#{actual}\" (expected end-of-string) when parsing #{self}", options
11
+ else
12
+ throw :SkipSuccess
13
+ end
14
+ end
15
+ end
16
+
17
+ def eql? other
18
+ other.is_a? self.class
19
+ end
20
+
21
+ alias :== :eql?
22
+
23
+ def to_s
24
+ 'EOF'
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Kaiseki
2
+ class MultiParser < BasicParser
3
+ def initialize *parsers
4
+ @expected = []
5
+ parsers.each do |n|
6
+ append n
7
+ end
8
+ end
9
+
10
+ def append parseable
11
+ @expected << parseable.to_parseable
12
+ self
13
+ end
14
+
15
+ def delimiter
16
+ '--'
17
+ end
18
+
19
+ def to_s
20
+ if @expected.empty?
21
+ '(empty)'
22
+ else
23
+ @expected.join ' ' + delimiter + ' '
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module Kaiseki
2
+ class PackageParser < BasicParser
3
+ def initialize expected
4
+ super expected.to_parseable
5
+ end
6
+
7
+ def to_s
8
+ @expected.to_s
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Kaiseki
2
+ class RegexpParser < BasicParser
3
+ def parse! stream, options = {}
4
+ stream.must_be Stream
5
+ stream.lock do
6
+ match = stream.match @expected
7
+ if match
8
+ if options[:simplify]
9
+ match.to_s
10
+ else
11
+ match
12
+ end
13
+ else
14
+ raise ParseError.new "non-matching characters when parsing #{self}", options
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end