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.
- 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
data/README
ADDED
File without changes
|
data/lib/action.rb
ADDED
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 = '
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
'
|
11
|
-
'
|
12
|
-
|
13
|
-
|
14
|
-
'
|
15
|
-
'
|
16
|
-
'
|
17
|
-
|
18
|
-
'
|
19
|
-
'
|
20
|
-
'
|
21
|
-
|
22
|
-
|
23
|
-
'
|
24
|
-
'
|
25
|
-
|
26
|
-
'
|
27
|
-
'
|
28
|
-
|
29
|
-
'
|
30
|
-
'
|
31
|
-
|
32
|
-
'
|
33
|
-
|
34
|
-
'
|
35
|
-
|
36
|
-
|
37
|
-
'
|
38
|
-
'
|
39
|
-
'
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
'
|
44
|
-
'
|
45
|
-
'
|
46
|
-
'
|
47
|
-
|
48
|
-
|
49
|
-
|
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
data/lib/mod_kernel.rb
ADDED
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
data/lib/mod_regexp.rb
ADDED
data/lib/mod_string.rb
ADDED
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
|
data/lib/parse_error.rb
ADDED
data/lib/parse_result.rb
ADDED
@@ -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
|
3
|
-
include
|
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
|
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
|
data/lib/parser_multi.rb
ADDED
@@ -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,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
|