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
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