rparsec2 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5de30f07e3855c6c2168832879138e3341ce79a20272ddf2c92857f47414e1ea
4
- data.tar.gz: 74c1ad503c94fe4a75a788d1384161b6f1b34a7e017a0740a0025d24f8a8518f
3
+ metadata.gz: 4561cdd86a68228d3d19811f6d8cf77a2664c21c61fac3b368035d6be7d55df3
4
+ data.tar.gz: bc34dfa71df4b91c505b6a27d5d3b23c3f6acc6c2542d77cebad140d78b670a9
5
5
  SHA512:
6
- metadata.gz: 26932d06bc2b3ec459ea0b3e22d091ebd1470d277bdac373b075821c97b82b4ab5936bdf4944150f21016cd9632f0a84d0428417f68446c31e33447734035e74
7
- data.tar.gz: e776214089f74d14ce7f61d4fde624ca245127d7edf89ca87033fe96b2132ab25b74f4d36a8927a6c0c24145c0722b911334f7e1eb32f08064ed7e6b448fd33f
6
+ metadata.gz: a9731ba718453a5814d896bccc2221b7473c577a16a62b710fe4e723225ea616c3067022e7e7cd902d217d290c9f47553184de4197a0421dd2b3d96418f6ccad
7
+ data.tar.gz: 89b2f4f0678b636570d6eb9d3b7ac0ac83555c64036a3ae9031c74df068a7603d028770bda66960c0933fa517a4c2b63249b772b18e4abae9f7b0523b3d8e49b
@@ -1,86 +1,88 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'strscan'
2
4
 
3
5
  module RParsec
4
6
 
5
- class ParseContext
6
- attr_reader :error, :src, :index, :result
7
- attr_writer :error, :index, :result
8
-
9
- def initialize(src, index=0, error=nil)
10
- @src, @index, @error = src, index, error
11
- @scanner = nil
12
- end
7
+ class ParseContext # :nodoc:
8
+ attr_reader :error, :src, :index, :result
9
+ attr_writer :error, :index, :result
13
10
 
14
- def scanner
15
- @scanner = StringScanner.new(src) if @scanner.nil?
16
- @scanner.pos= @index
17
- @scanner
18
- end
19
-
20
- def prepare_error
21
- @error.flatten! if @error.kind_of?(Array)
22
- end
23
-
24
- def to_msg
25
- return '' if @error.nil?
26
- return @error.msg unless @error.kind_of?(Array)
27
- @error.map{|e|e.msg}.join(' or ')
28
- end
29
-
30
- def error_input
31
- return nil if @error.nil?
32
- err = @error
33
- err = err.last if err.kind_of? Array
34
- err.input
35
- end
36
-
37
- def reset_error
38
- @error = nil
39
- end
40
-
41
- def current
42
- @src[@index]
43
- end
44
-
45
- def eof
46
- @index >= @src.length
47
- end
48
-
49
- def available
50
- @src.length - @index
51
- end
52
-
53
- def peek i
54
- @src[@index+i]
55
- end
56
-
57
- def next
58
- @index += 1
59
- end
60
-
61
- def advance n
62
- @index += n
63
- end
64
-
65
- def retn(val)
66
- @result = val
67
- true
68
- end
69
-
70
- def failure(msg=nil)
71
- @error = Failure.new(@index, get_current_input, msg)
72
- return false
73
- end
74
-
75
- def expecting(expected=nil)
76
- @error = Expected.new(@index, get_current_input, expected)
77
- return false
78
- end
79
-
80
- def get_current_input
81
- return nil if eof
82
- current
11
+ def initialize(src, index=0, error=nil)
12
+ @src, @index, @error = src, index, error
13
+ @scanner = nil
14
+ end
15
+
16
+ def scanner
17
+ @scanner = StringScanner.new(src) if @scanner.nil?
18
+ @scanner.pos = @index
19
+ @scanner
20
+ end
21
+
22
+ def prepare_error
23
+ @error.flatten! if @error.kind_of?(Array)
24
+ end
25
+
26
+ def to_msg
27
+ return '' if @error.nil?
28
+ return @error.msg unless @error.kind_of?(Array)
29
+ @error.map { |e| e.msg }.join(' or ')
30
+ end
31
+
32
+ def error_input
33
+ return nil if @error.nil?
34
+ err = @error
35
+ err = err.last if err.kind_of? Array
36
+ err.input
37
+ end
38
+
39
+ def reset_error
40
+ @error = nil
41
+ end
42
+
43
+ def current
44
+ @src[@index]
45
+ end
46
+
47
+ def eof
48
+ @index >= @src.length
49
+ end
50
+
51
+ def available
52
+ @src.length - @index
53
+ end
54
+
55
+ def peek i
56
+ @src[@index + i]
57
+ end
58
+
59
+ def next
60
+ @index += 1
61
+ end
62
+
63
+ def advance n
64
+ @index += n
65
+ end
66
+
67
+ def retn(val)
68
+ @result = val
69
+ true
70
+ end
71
+
72
+ def failure(msg=nil)
73
+ @error = Failure.new(@index, get_current_input, msg)
74
+ return false
75
+ end
76
+
77
+ def expecting(expected=nil)
78
+ @error = Expected.new(@index, get_current_input, expected)
79
+ return false
80
+ end
81
+
82
+ def get_current_input
83
+ return nil if eof
84
+ current
85
+ end
83
86
  end
84
- end
85
87
 
86
88
  end # module
data/lib/rparsec/error.rb CHANGED
@@ -1,28 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rparsec/misc'
2
4
 
3
5
  module RParsec
4
6
 
5
- class ParserException < StandardError
6
- extend DefHelper
7
- def_readable :index
8
- end
9
- class Failure
10
- def initialize(ind, input, message = nil)
11
- @index, @input, @msg = ind, input, message
7
+ class ParserException < StandardError # :nodoc:
8
+ extend DefHelper
9
+ def_readable :index
12
10
  end
13
11
 
14
- attr_reader :index, :input
15
- attr_writer :index
12
+ class Failure # :nodoc:
13
+ def initialize(ind, input, message = nil)
14
+ @index, @input, @msg = ind, input, message
15
+ end
16
16
 
17
- def msg
18
- return @msg.to_s
19
- end
17
+ attr_reader :index, :input
18
+ attr_writer :index
20
19
 
21
- Precedence = 100
22
- end
20
+ def msg
21
+ return @msg.to_s
22
+ end
23
23
 
24
- class Expected < Failure
25
- Precedence = 100
26
- end
24
+ Precedence = 100
25
+ end
26
+
27
+ class Expected < Failure # :nodoc:
28
+ Precedence = 100
29
+ end
27
30
 
28
- end # module
31
+ end # module
@@ -1,186 +1,98 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rparsec/parser'
2
4
 
3
5
  module RParsec
4
6
 
5
- Associativities = [:prefix, :postfix, :infixn, :infixr, :infixl]
6
- #
7
- # This class holds information about operator precedences
8
- # and associativities.
9
- # prefix, postfix, infixl, infixr, infixn can be called
10
- # to register operators.
11
- #
12
- class OperatorTable
13
- #
14
- # operators attribute is used internally. Do not access it.
15
- #
16
- attr_reader :operators
17
-
18
- #
19
- # Re-initialize the operator table. Internal use only.
20
- #
21
- def reinit
22
- @operators = []
23
- end
24
-
25
- #
26
- # To create an OperatorTable instance.
27
- # If a block is given, it is invoked to do post-instantiation.
28
- # For example:
29
- #
30
- # OperatorTable.new do |tbl|
31
- # tbl.infixl(char(?+) >> Plus, 10)
32
- # tbl.infixl(char(?-) >> Minus, 10)
33
- # tbl.infixl(char(?*) >> Mul, 20)
34
- # tbl.infixl(char(?/) >> Div, 20)
35
- # tbl.prefix(char(?-) >> Neg, 50)
36
- # end
37
- #
38
- def self.new
39
- this = allocate
40
- this.reinit
41
- if block_given?
42
- yield this
43
- end
44
- this
45
- end
46
-
47
- #
48
- # Defines a prefix operator that returns a unary Proc object with a precedence associated.
49
- # Returns self.
50
- #
51
- def prefix(op, precedence)
52
- add(:prefix, op, precedence)
53
- end
54
-
55
- #
56
- # Defines a postfix operator that returns a unary Proc object with a precedence associated.
57
- # Returns self.
58
- #
59
- def postfix(op, precedence)
60
- add(:postfix, op, precedence)
61
- end
62
-
63
- #
64
- # Defines a left associative infix operator that returns a binary Proc object with a precedence
65
- # associated. Returns self.
66
- #
67
- def infixl(op, precedence)
68
- add(:infixl, op, precedence)
69
- end
70
-
71
- #
72
- # Defines a right associative infix operator that returns a binary Proc object with a precedence
73
- # associated. Returns self.
7
+ Associativities = [:prefix, :postfix, :infixn, :infixr, :infixl]
74
8
  #
75
- def infixr(op, precedence)
76
- add(:infixr, op, precedence)
77
- end
78
-
9
+ # This module helps build an expression parser
10
+ # using an OperatorTable instance and a parser
11
+ # that parses the term expression.
79
12
  #
80
- # Defines a non-associative infix operator that returns a binary Proc object with a precedence
81
- # associated. Returns self.
82
- #
83
- def infixn(op, precedence)
84
- add(:infixn, op, precedence)
85
- end
86
-
87
- private
13
+ module Expressions
14
+ class << self
15
+ private
88
16
 
89
- def add(*entry)
90
- @operators << entry
91
- self
92
- end
93
- end
94
-
95
- #
96
- # This module helps build an expression parser
97
- # using an OperatorTable instance and a parser
98
- # that parses the term expression.
99
- #
100
- module Expressions
101
- class << self
102
- private
103
-
104
- def array_to_dict arr
105
- result = {}
106
- arr.each_with_index do |key, i|
107
- result[key] = i unless result.include? key
17
+ def array_to_dict arr
18
+ result = {}
19
+ arr.each_with_index do |key, i|
20
+ result[key] = i unless result.include? key
21
+ end
22
+ result
108
23
  end
109
- result
110
24
  end
111
- end
112
25
 
113
- KindPrecedence = array_to_dict Associativities
26
+ KindPrecedence = array_to_dict Associativities
114
27
 
115
- #
116
- # build an expression parser using the given term parser
117
- # and operator table.
118
- # When _delim_ is specified, patterns recognized by _delim_
119
- # is automatically ignored.
120
- #
121
- def self.build(term, table, delim = nil)
122
- # sort so that higher precedence first.
123
- apply_operators(term, prepare_suites(table).sort, delim)
124
- end
125
-
126
- class << self
127
- private
28
+ #
29
+ # build an expression parser using the given +term+ parser and
30
+ # operator +table+. When +delim+ is specified, patterns
31
+ # recognized by +delim+ is automatically ignored.
32
+ #
33
+ def self.build(term, table, delim = nil)
34
+ # sort so that higher precedence first.
35
+ apply_operators(term, prepare_suites(table).sort, delim)
36
+ end
128
37
 
129
- def apply_operators(term, entries, delim)
130
- # apply operators stored in [[precedence,associativity],[op...]] starting from beginning.
131
- entries.inject(term) do |result, entry|
132
- key, ops = *entry
133
- _, kind_index = *key
134
- op = ops[0]
135
- op = Parsers.sum(*ops) if ops.length > 1
136
- apply_operator(result, op, Associativities[kind_index], delim)
38
+ class << self
39
+ private
40
+
41
+ def apply_operators(term, entries, delim)
42
+ # apply operators stored in [[precedence,associativity],[op...]] starting from beginning.
43
+ entries.inject(term) do |result, entry|
44
+ key, ops = *entry
45
+ _, kind_index = *key
46
+ op = ops[0]
47
+ op = Parsers.sum(*ops) if ops.length > 1
48
+ apply_operator(result, op, Associativities[kind_index], delim)
49
+ end
137
50
  end
138
- end
139
51
 
140
- def apply_operator(term, op, kind, delim)
141
- term, op = ignore_rest(term, delim), ignore_rest(op, delim)
142
- # we could use send here,
143
- # but explicit case stmt is more straight forward and less coupled with names.
144
- # performance might be another benefit,
145
- # though it is not clear whether meta-code is indeed slower than regular ones at all.
146
- case kind
147
- when :prefix
148
- term.prefix(op)
149
- when :postfix
150
- term.postfix(op)
151
- when :infixl
152
- term.infixl(op)
153
- when :infixr
154
- term.infixr(op)
155
- when :infixn
156
- term.infixn(op)
157
- else
158
- raise ArgumentError, "unknown associativity: #{kind}"
52
+ def apply_operator(term, op, kind, delim)
53
+ term, op = ignore_rest(term, delim), ignore_rest(op, delim)
54
+ # we could use send here,
55
+ # but explicit case stmt is more straight forward and less coupled with names.
56
+ # performance might be another benefit,
57
+ # though it is not clear whether meta-code is indeed slower than regular ones at all.
58
+ case kind
59
+ when :prefix
60
+ term.prefix(op)
61
+ when :postfix
62
+ term.postfix(op)
63
+ when :infixl
64
+ term.infixl(op)
65
+ when :infixr
66
+ term.infixr(op)
67
+ when :infixn
68
+ term.infixn(op)
69
+ else
70
+ raise ArgumentError, "unknown associativity: #{kind}"
71
+ end
159
72
  end
160
- end
161
73
 
162
- def ignore_rest(parser, delim)
163
- return parser if delim.nil?
164
- parser << delim
165
- end
74
+ def ignore_rest(parser, delim)
75
+ return parser if delim.nil?
76
+ parser << delim
77
+ end
166
78
 
167
- def prepare_suites(table)
168
- # create a hash with [precedence, associativity] as key, and op as value.
169
- suites = {}
170
- table.operators.each do |entry|
171
- kind, op, precedence = *entry
172
- key = [-precedence, KindPrecedence[kind]]
173
- suite = suites[key]
174
- if suite.nil?
175
- suite = [op]
176
- suites[key] = suite
177
- else
178
- suite << op
79
+ def prepare_suites(table)
80
+ # create a hash with [precedence, associativity] as key, and op as value.
81
+ suites = {}
82
+ table.operators.each do |entry|
83
+ kind, op, precedence = *entry
84
+ key = [-precedence, KindPrecedence[kind]]
85
+ suite = suites[key]
86
+ if suite.nil?
87
+ suite = [op]
88
+ suites[key] = suite
89
+ else
90
+ suite << op
91
+ end
179
92
  end
93
+ suites
180
94
  end
181
- suites
182
95
  end
183
96
  end
184
- end
185
97
 
186
98
  end # module
@@ -0,0 +1,102 @@
1
+ module RParsec
2
+ #
3
+ # This module provides instance methods that
4
+ # manipulate closures in a functional style.
5
+ # It is typically included in Proc and Method.
6
+ #
7
+ module FunctorMixin
8
+ #
9
+ # Create a +Proc+, which expects the two parameters in the reverse
10
+ # order of +self+.
11
+ #
12
+ def flip
13
+ Functors.flip(&self)
14
+ end
15
+
16
+ #
17
+ # Create a +Proc+, when called, the parameter is first passed into
18
+ # +other+, +self+ is called in turn with the return value from
19
+ # +other+.
20
+ #
21
+ def compose(other)
22
+ Functors.compose(self, other)
23
+ end
24
+
25
+ alias << compose
26
+
27
+ #
28
+ # <tt>a >> b</tt> is equivalent to <tt>b << a</tt>. See also #<<.
29
+ #
30
+ def >>(other)
31
+ other << self
32
+ end
33
+
34
+ #
35
+ # Create a Proc that's curriable.
36
+ # When curried, parameters are passed in from left to right.
37
+ # i.e. closure.curry.call(a).call(b) is quivalent to closure.call(a,b) .
38
+ # _self_ is encapsulated under the hood to perform the actual
39
+ # job when currying is done.
40
+ # _ary_ explicitly specifies the number of parameters to curry.
41
+ #
42
+ # *IMPORTANT*
43
+ # Proc and Method have built-in curry.
44
+ # but the arity always return -1.
45
+ # So, curry.reverse_curry does not work as expected.
46
+ # You need to use the "using FunctorMixin"
47
+ # See the "functor_test.rb"
48
+ [Proc, Method].each do |klass|
49
+ refine klass do
50
+ def curry(ary = arity)
51
+ Functors.curry(ary, &self)
52
+ end
53
+ end
54
+ end
55
+
56
+ #
57
+ # Create a +Proc+ that's curriable. When curried, parameters are
58
+ # passed in from right to left.
59
+ # i.e. <tt>closure.reverse_curry.call(a).call(b)</tt> is quivalent
60
+ # to <tt>closure.call(b, a)</tt>. +self+ is encapsulated under
61
+ # the hood to perform the actual job when currying is done. +ary+
62
+ # explicitly specifies the number of parameters to curry.
63
+ #
64
+ def reverse_curry(ary = arity)
65
+ Functors.reverse_curry(ary, &self)
66
+ end
67
+
68
+ #
69
+ # Uncurry a curried closure.
70
+ #
71
+ def uncurry
72
+ Functors.uncurry(&self)
73
+ end
74
+
75
+ #
76
+ # Uncurry a reverse curried closure.
77
+ #
78
+ def reverse_uncurry
79
+ Functors.reverse_uncurry(&self)
80
+ end
81
+
82
+ #
83
+ # Create a +Proc+, when called, repeatedly call +self+ for +n+
84
+ # times. The same arguments are passed to each invocation.
85
+ #
86
+ def repeat(n)
87
+ Functors.repeat(n, &self)
88
+ end
89
+ #
90
+
91
+ # Create a +Proc+, when called, repeatedly call +self+ for +n+
92
+ # times. At each iteration, return value from the previous
93
+ # iteration is used as parameter.
94
+ #
95
+ def power(n)
96
+ Functors.power(n, &self)
97
+ end
98
+
99
+ alias ** power
100
+ alias * repeat
101
+ end
102
+ end