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