rparsec-ruby19 1.0

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.
@@ -0,0 +1,3 @@
1
+ %w{
2
+ parsers operators keywords expressions
3
+ }.each {|lib| require "rparsec/#{lib}"}
@@ -0,0 +1,83 @@
1
+ module RParsec
2
+
3
+ class ParseContext
4
+ attr_reader :error, :src, :index, :result
5
+ attr_writer :error, :index, :result
6
+
7
+ def initialize(src, index=0, error=nil)
8
+ @src, @index, @error = src, index, error
9
+ end
10
+
11
+ def scanner
12
+ @scanner = StringScanner.new(src) if @scanner.nil?
13
+ @scanner.pos= @index
14
+ @scanner
15
+ end
16
+
17
+ def prepare_error
18
+ @error.flatten! if @error.kind_of?(Array)
19
+ end
20
+
21
+ def to_msg
22
+ return '' if @error.nil?
23
+ return @error.msg unless @error.kind_of?(Array)
24
+ @error.map{|e|e.msg}.join(' or ')
25
+ end
26
+
27
+ def error_input
28
+ return nil if @error.nil?
29
+ err = @error
30
+ err = err.last if err.kind_of? Array
31
+ err.input
32
+ end
33
+
34
+ def reset_error
35
+ @error = nil
36
+ end
37
+
38
+ def current
39
+ @src[@index]
40
+ end
41
+
42
+ def eof
43
+ @index >= @src.length
44
+ end
45
+
46
+ def available
47
+ @src.length - @index
48
+ end
49
+
50
+ def peek i
51
+ @src[@index+i]
52
+ end
53
+
54
+ def next
55
+ @index += 1
56
+ end
57
+
58
+ def advance n
59
+ @index += n
60
+ end
61
+
62
+ def retn(val)
63
+ @result = val
64
+ true
65
+ end
66
+
67
+ def failure(msg=nil)
68
+ @error = Failure.new(@index, get_current_input, msg)
69
+ return false
70
+ end
71
+
72
+ def expecting(expected=nil)
73
+ @error = Expected.new(@index, get_current_input, expected)
74
+ return false
75
+ end
76
+
77
+ def get_current_input
78
+ return nil if eof
79
+ current
80
+ end
81
+ end
82
+
83
+ end # module
@@ -0,0 +1,28 @@
1
+ require 'rparsec/misc'
2
+
3
+ module RParsec
4
+
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
12
+ end
13
+
14
+ attr_reader :index, :input
15
+ attr_writer :index
16
+
17
+ def msg
18
+ return @msg.to_s
19
+ end
20
+
21
+ Precedence = 100
22
+ end
23
+
24
+ class Expected < Failure
25
+ Precedence = 100
26
+ end
27
+
28
+ end # module
@@ -0,0 +1,184 @@
1
+ require 'rparsec/parser'
2
+
3
+ module RParsec
4
+
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.
74
+ #
75
+ def infixr(op, precedence)
76
+ add(:infixr, op, precedence)
77
+ end
78
+
79
+ #
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
88
+
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
+ private
102
+
103
+ def self.array_to_dict arr
104
+ result = {}
105
+ arr.each_with_index do |key,i|
106
+ result [key] = i unless result.include? key
107
+ end
108
+ result
109
+ end
110
+
111
+ KindPrecedence = array_to_dict Associativities
112
+
113
+ public
114
+
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
+ private
127
+
128
+ def self.apply_operators(term, entries, delim)
129
+ # apply operators stored in [[precedence,associativity],[op...]] starting from beginning.
130
+ entries.inject(term) do |result, entry|
131
+ key, ops = *entry
132
+ null, kind_index = *key
133
+ op = ops[0]
134
+ op = Parsers.sum(*ops) if ops.length>1
135
+ apply_operator(result, op, Associativities[kind_index], delim)
136
+ end
137
+ end
138
+
139
+ def self.apply_operator(term, op, kind, delim)
140
+ term, op = ignore_rest(term, delim), ignore_rest(op, delim)
141
+ # we could use send here,
142
+ # but explicit case stmt is more straight forward and less coupled with names.
143
+ # performance might be another benefit,
144
+ # though it is not clear whether meta-code is indeed slower than regular ones at all.
145
+ case kind
146
+ when :prefix
147
+ term.prefix(op)
148
+ when :postfix
149
+ term.postfix(op)
150
+ when :infixl
151
+ term.infixl(op)
152
+ when :infixr
153
+ term.infixr(op)
154
+ when :infixn
155
+ term.infixn(op)
156
+ else
157
+ raise ArgumentError, "unknown associativity: #{kind}"
158
+ end
159
+ end
160
+
161
+ def self.ignore_rest(parser, delim)
162
+ return parser if delim.nil?
163
+ parser << delim
164
+ end
165
+
166
+ def self.prepare_suites(table)
167
+ # create a hash with [precedence, associativity] as key, and op as value.
168
+ suites = {}
169
+ table.operators.each do |entry|
170
+ kind, op, precedence = *entry
171
+ key = [-precedence, KindPrecedence[kind]]
172
+ suite = suites[key]
173
+ if suite.nil?
174
+ suite = [op]
175
+ suites[key] = suite
176
+ else
177
+ suite << op
178
+ end
179
+ end
180
+ suites
181
+ end
182
+ end
183
+
184
+ end # module
@@ -0,0 +1,274 @@
1
+ module RParsec
2
+
3
+ #
4
+ # This module provides frequently used functors.
5
+ #
6
+ module Functors
7
+ Id = proc {|x|x}
8
+ Idn = proc {|*x|x}
9
+ Neg = proc {|x|-x}
10
+ Inc = proc {|x|x+1}
11
+ Dec = proc {|x|x-1}
12
+ Plus = proc {|x,y|x+y}
13
+ Minus = proc {|x,y|x-y}
14
+ Mul = proc {|x,y|x*y}
15
+ Div = proc {|x,y|x/y}
16
+ Mod = proc {|x,y|x%y}
17
+ Power = proc {|x,y|x**y}
18
+ Not = proc {|x,y|!x}
19
+ And = proc {|x,y|x&&y}
20
+ Or = proc {|x,y|x||y}
21
+ Xor = proc {|x,y|x^y}
22
+ BitAnd = proc {|x,y|x&y}
23
+ Union = proc {|x,y|x|y}
24
+ Match = proc {|x,y|x=~y}
25
+ Eq = proc {|x,y|x==y}
26
+ Ne = proc {|x,y|x!=y}
27
+ Lt = proc {|x,y|x<y}
28
+ Gt = proc {|x,y|x>y}
29
+ Le = proc {|x,y|x<=y}
30
+ Ge = proc {|x,y|x>=y}
31
+ Compare = proc {|x,y|x<=>y}
32
+ Call = proc {|x,y|x.call(y)}
33
+ Feed = proc {|x,y|y.call(x)}
34
+ Fst = proc {|x,_|x}
35
+ Snd = proc {|_, x|x}
36
+ At = proc {|x,y|x[y]}
37
+ To_a = proc {|x|x.to_a}
38
+ To_s = proc {|x|x.to_s}
39
+ To_i = proc {|x|x.to_i}
40
+ To_sym = proc {|x|x.to_sym}
41
+ To_f = proc {|x|x.to_f}
42
+
43
+ #
44
+ # Get a Proc, when called, always return the given value.
45
+ #
46
+ def const(v)
47
+ proc {|_|v}
48
+ end
49
+
50
+ #
51
+ # Get a Proc, when called, return the nth parameter.
52
+ #
53
+ def nth(n)
54
+ proc {|*args|args[n]}
55
+ end
56
+
57
+ #
58
+ # Create a Proc, which expects the two parameters
59
+ # in the reverse order of _block_.
60
+ #
61
+ def flip(&block)
62
+ proc {|x,y|block.call(y,x)}
63
+ end
64
+
65
+ #
66
+ # Create a Proc, when called, the parameter is
67
+ # first passed into _f2_, _f1_ is called in turn
68
+ # with the return value from _other_.
69
+ #
70
+ def compose(f1, f2)
71
+ proc {|*x|f1.call(f2.call(*x))}
72
+ end
73
+
74
+ #
75
+ # Create a Proc that's curriable.
76
+ # When curried, parameters are passed in from left to right.
77
+ # i.e. curry(closure).call(a).call(b) is quivalent to closure.call(a,b) .
78
+ # _block_ is encapsulated under the hood to perform the actual
79
+ # job when currying is done.
80
+ # arity explicitly specifies the number of parameters to curry.
81
+ #
82
+ def curry(arity, &block)
83
+ fail "cannot curry for unknown arity" if arity < 0
84
+ Functors.make_curry(arity, &block)
85
+ end
86
+
87
+ #
88
+ # Create a Proc that's curriable.
89
+ # When curried, parameters are passed in from right to left.
90
+ # i.e. reverse_curry(closure).call(a).call(b) is quivalent to closure.call(b,a) .
91
+ # _block_ is encapsulated under the hood to perform the actual
92
+ # job when currying is done.
93
+ # arity explicitly specifies the number of parameters to curry.
94
+ #
95
+ def reverse_curry(arity, &block)
96
+ fail "cannot curry for unknown arity" if arity < 0
97
+ Functors.make_reverse_curry(arity, &block)
98
+ end
99
+
100
+ #
101
+ # Uncurry a curried closure.
102
+ #
103
+ def uncurry(&block)
104
+ return block unless block.arity == 1
105
+ proc do |*args|
106
+ result = block
107
+ args.each do |a|
108
+ result = result.call(a)
109
+ end
110
+ result
111
+ end
112
+ end
113
+
114
+ #
115
+ # Uncurry a reverse curried closure.
116
+ #
117
+ def reverse_uncurry(&block)
118
+ return block unless block.arity == 1
119
+ proc do |*args|
120
+ result = block
121
+ args.reverse_each do |a|
122
+ result = result.call(a)
123
+ end
124
+ result
125
+ end
126
+ end
127
+
128
+ #
129
+ # Create a Proc, when called,
130
+ # repeatedly call _block_ for _n_ times.
131
+ # The same arguments are passed to each invocation.
132
+ #
133
+ def repeat(n, &block)
134
+ proc do |*args|
135
+ result = nil
136
+ n.times {result = block.call(*args)}
137
+ result
138
+ end
139
+ end
140
+
141
+ #
142
+ # Create a Proc, when called,
143
+ # repeatedly call _block_ for _n_ times.
144
+ # At each iteration, return value from the previous iteration
145
+ # is used as parameter.
146
+ #
147
+ def power(n, &block)
148
+ return const(nil) if n<=0
149
+ return block if n==1
150
+ proc do |*args|
151
+ result = block.call(*args)
152
+ (n-1).times {result = block.call(result)}
153
+ result
154
+ end
155
+ end
156
+
157
+ extend self
158
+
159
+ private_class_method
160
+
161
+ def self.make_curry(arity, &block)
162
+ return block if arity<=1
163
+ proc do |x|
164
+ make_curry(arity-1) do |*rest|
165
+ block.call(*rest.insert(0, x))
166
+ end
167
+ end
168
+ end
169
+
170
+ def self.make_reverse_curry(arity, &block)
171
+ return block if arity <= 1
172
+ proc do |x|
173
+ make_reverse_curry(arity-1) do |*rest|
174
+ block.call(*rest << x)
175
+ end
176
+ end
177
+ end
178
+
179
+ end
180
+
181
+ #
182
+ # This module provides instance methods that
183
+ # manipulate closures in a functional style.
184
+ # It is typically included in Proc and Method.
185
+ #
186
+ module FunctorMixin
187
+ #
188
+ # Create a Proc, which expects the two parameters
189
+ # in the reverse order of _self_.
190
+ #
191
+ def flip
192
+ Functors.flip(&self)
193
+ end
194
+
195
+ #
196
+ # Create a Proc, when called, the parameter is
197
+ # first passed into _other_, _self_ is called in turn
198
+ # with the return value from _other_.
199
+ #
200
+ def compose(other)
201
+ Functors.compose(self, other)
202
+ end
203
+
204
+ alias << compose
205
+
206
+ #
207
+ # a >> b is equivalent to b << a
208
+ #
209
+ def >> (other)
210
+ other << self
211
+ end
212
+
213
+ #
214
+ # Create a Proc that's curriable.
215
+ # When curried, parameters are passed in from left to right.
216
+ # i.e. closure.curry.call(a).call(b) is quivalent to closure.call(a,b) .
217
+ # _self_ is encapsulated under the hood to perform the actual
218
+ # job when currying is done.
219
+ # _ary_ explicitly specifies the number of parameters to curry.
220
+ #
221
+ def curry(ary=arity)
222
+ Functors.curry(ary, &self)
223
+ end
224
+
225
+ #
226
+ # Create a Proc that's curriable.
227
+ # When curried, parameters are passed in from right to left.
228
+ # i.e. closure.reverse_curry.call(a).call(b) is quivalent to closure.call(b,a) .
229
+ # _self_ is encapsulated under the hood to perform the actual
230
+ # job when currying is done.
231
+ # _ary_ explicitly specifies the number of parameters to curry.
232
+ #
233
+ def reverse_curry(ary=arity)
234
+ Functors.reverse_curry(ary, &self)
235
+ end
236
+
237
+ #
238
+ # Uncurry a curried closure.
239
+ #
240
+ def uncurry
241
+ Functors.uncurry(&self)
242
+ end
243
+
244
+ #
245
+ # Uncurry a reverse curried closure.
246
+ #
247
+ def reverse_uncurry
248
+ Functors.reverse_uncurry(&self)
249
+ end
250
+
251
+ #
252
+ # Create a Proc, when called,
253
+ # repeatedly call _self_ for _n_ times.
254
+ # The same arguments are passed to each invocation.
255
+ #
256
+ def repeat(n)
257
+ Functors.repeat(n, &self)
258
+ end
259
+ #
260
+
261
+ # Create a Proc, when called,
262
+ # repeatedly call _self_ for _n_ times.
263
+ # At each iteration, return value from the previous iteration
264
+ # is used as parameter.
265
+ #
266
+ def power(n)
267
+ Functors.power(n, &self)
268
+ end
269
+
270
+ alias ** power
271
+ alias * repeat
272
+ end
273
+
274
+ end # module