rparsec-ruby19 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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