Class: ParserCombinator
- Inherits:
-
Object
show all
- Defined in:
- lib/parser_combinator.rb,
lib/parser_combinator/version.rb,
lib/parser_combinator/string_parser.rb
Defined Under Namespace
Classes: Fail, Item, Items, Ok, ParsedSeq, StandardFailStatus, StringParser
Constant Summary
collapse
- ParserCombinatorError =
Class.new(RuntimeError)
- VERSION =
"0.0.4"
Instance Attribute Summary collapse
Class Method Summary
collapse
-
.binopl(parser, op_proc_parser) ⇒ Object
-
.binopl_fail(parser, op_proc_parser) ⇒ Object
-
.discardl(parser1, parser2) ⇒ Object
-
.discardr(parser1, parser2) ⇒ Object
-
.either(parser1, parser2) ⇒ Object
-
.either_fail(parser1, parser2) ⇒ Object
-
.end_of_input ⇒ Object
-
.fail(status = nil) ⇒ Object
-
.item ⇒ Object
-
.many(parser, separator_parser = ok(nil)) ⇒ Object
-
.many1(parser, separator_parser = ok(nil)) ⇒ Object
-
.many1_fail(parser, separator_parser = ok(nil)) ⇒ Object
-
.many_fail(parser, separator_parser = ok(nil)) ⇒ Object
-
.ok(object) ⇒ Object
-
.opt(parser) ⇒ Object
-
.opt_fail(parser) ⇒ Object
-
.parser(name, &proc) ⇒ Object
Memorization DSL suport (for recursive grammer) ——————–.
-
.sat(&item_cond_proc) ⇒ Object
-
.seq(*parsers) ⇒ Object
-
.so_then(parser, &continuation_proc) ⇒ Object
Instance Method Summary
collapse
Constructor Details
#initialize(status_handler = proc{nil}, name = nil, &proc) ⇒ ParserCombinator
Returns a new instance of ParserCombinator.
137
138
139
140
141
|
# File 'lib/parser_combinator.rb', line 137
def initialize(status_handler=proc{nil}, name=nil, &proc)
@status_handler = status_handler
@parser_name = name
@parser_proc = proc
end
|
Instance Attribute Details
#parser_name ⇒ Object
Returns the value of attribute parser_name.
136
137
138
|
# File 'lib/parser_combinator.rb', line 136
def parser_name
@parser_name
end
|
#parser_proc ⇒ Object
Returns the value of attribute parser_proc.
136
137
138
|
# File 'lib/parser_combinator.rb', line 136
def parser_proc
@parser_proc
end
|
#status_handler ⇒ Object
Returns the value of attribute status_handler.
136
137
138
|
# File 'lib/parser_combinator.rb', line 136
def status_handler
@status_handler
end
|
Class Method Details
.binopl(parser, op_proc_parser) ⇒ Object
328
329
330
331
332
333
334
335
336
337
338
|
# File 'lib/parser_combinator.rb', line 328
def self.binopl(parser, op_proc_parser)
rest = proc{|a|
op_proc_parser >> proc{|f|
parser >> proc{|b|
rest.call(f.call(a, b))
}} | ok(a)
}
parser >> proc{|a|
rest.call(a)
}
end
|
.binopl_fail(parser, op_proc_parser) ⇒ Object
340
341
342
343
344
345
346
347
348
349
350
|
# File 'lib/parser_combinator.rb', line 340
def self.binopl_fail(parser, op_proc_parser)
rest = proc{|a|
op_proc_parser >> proc{|f|
parser >> proc{|b|
rest.call(f.call(a, b))
}} ^ ok(a)
}
parser >> proc{|a|
rest.call(a)
}
end
|
.discardl(parser1, parser2) ⇒ Object
317
318
319
|
# File 'lib/parser_combinator.rb', line 317
def self.discardl(parser1, parser2)
parser1 >> proc{parser2}
end
|
.discardr(parser1, parser2) ⇒ Object
321
322
323
324
325
326
|
# File 'lib/parser_combinator.rb', line 321
def self.discardr(parser1, parser2)
parser1 >> proc{|x|
parser2 >> proc{
ok(x)
}}
end
|
.either(parser1, parser2) ⇒ Object
229
230
231
232
233
234
235
236
237
238
239
240
|
# File 'lib/parser_combinator.rb', line 229
def self.either(parser1, parser2)
new{|i|
case result1 = parser1.parse(i)
when Fail
parser2.parse(i)
when Ok
result1
else
raise "error"
end
}
end
|
.either_fail(parser1, parser2) ⇒ Object
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
# File 'lib/parser_combinator.rb', line 242
def self.either_fail(parser1, parser2)
new{|i|
case result1 = parser1.parse(i)
when Fail
if result1.status == nil
parser2.parse(i)
else
result1
end
when Ok
result1
else
raise "error"
end
}
end
|
263
264
265
|
# File 'lib/parser_combinator.rb', line 263
def self.end_of_input
new{|i| i.size == 0 ? Ok.new(nil, i) : Fail.new}
end
|
.fail(status = nil) ⇒ Object
212
213
214
|
# File 'lib/parser_combinator.rb', line 212
def self.fail(status=nil)
new{|i| Fail.new(status)}
end
|
.item ⇒ Object
259
260
261
|
# File 'lib/parser_combinator.rb', line 259
def self.item
new{|i| i.size == 0 ? Fail.new : Ok.new(i.head, i.rest)}
end
|
.many(parser, separator_parser = ok(nil)) ⇒ Object
291
292
293
|
# File 'lib/parser_combinator.rb', line 291
def self.many(parser, separator_parser=ok(nil))
many1(parser, separator_parser) | ok([])
end
|
.many1(parser, separator_parser = ok(nil)) ⇒ Object
295
296
297
298
299
300
|
# File 'lib/parser_combinator.rb', line 295
def self.many1(parser, separator_parser=ok(nil))
parser >> proc{|x|
many(separator_parser > parser) >> proc{|xs|
ok([x] + xs)
}}
end
|
.many1_fail(parser, separator_parser = ok(nil)) ⇒ Object
310
311
312
313
314
315
|
# File 'lib/parser_combinator.rb', line 310
def self.many1_fail(parser, separator_parser=ok(nil))
parser >> proc{|x|
many_fail(separator_parser > parser) >> proc{|xs|
ok([x] + xs)
}}
end
|
.many_fail(parser, separator_parser = ok(nil)) ⇒ Object
306
307
308
|
# File 'lib/parser_combinator.rb', line 306
def self.many_fail(parser, separator_parser=ok(nil))
many1_fail(parser, separator_parser) ^ ok([])
end
|
.ok(object) ⇒ Object
208
209
210
|
# File 'lib/parser_combinator.rb', line 208
def self.ok(object)
new{|i| Ok.new(object, i)}
end
|
.opt(parser) ⇒ Object
287
288
289
|
# File 'lib/parser_combinator.rb', line 287
def self.opt(parser)
parser.map{|x| [x]} | ok([])
end
|
.opt_fail(parser) ⇒ Object
302
303
304
|
# File 'lib/parser_combinator.rb', line 302
def self.opt_fail(parser)
parser.map{|x| [x]} ^ ok([])
end
|
.parser(name, &proc) ⇒ Object
Memorization DSL suport (for recursive grammer)
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
# File 'lib/parser_combinator.rb', line 355
def self.parser(name, &proc)
@cache ||= {}
spcls = class << self; self end
spcls.send(:define_method, name) do |*args|
key = [name, args]
if @cache[key]
return @cache[key]
else
status_handler = proc{ raise "this is never-called proc (status_handler)" }
parser_proc = proc{ raise "this is never-called proc (parser_proc)" }
@cache[key] = self.new(proc{|*args| status_handler.call(*args)}){|*args| parser_proc.call(*args)}
generated_parser = proc.call(*args)
parser_proc = generated_parser.parser_proc
status_handler = generated_parser.status_handler
return @cache[key]
end
end
end
|
.sat(&item_cond_proc) ⇒ Object
267
268
269
270
271
|
# File 'lib/parser_combinator.rb', line 267
def self.sat(&item_cond_proc)
item >> proc{|i|
item_cond_proc.call(i.item) ? ok(i) : fail
}
end
|
.seq(*parsers) ⇒ Object
276
277
278
279
280
281
282
283
284
285
|
# File 'lib/parser_combinator.rb', line 276
def self.seq(*parsers)
if parsers.size == 0
ok(ParsedSeq.empty)
else
parsers.first >> proc{|x|
seq(*parsers.drop(1)) >> proc{|xs|
ok(xs.cons(x, parsers.first.parser_name))
}}
end
end
|
.so_then(parser, &continuation_proc) ⇒ Object
216
217
218
219
220
221
222
223
224
225
226
227
|
# File 'lib/parser_combinator.rb', line 216
def self.so_then(parser, &continuation_proc)
new{|i|
case result = parser.parse(i)
when Fail
result
when Ok
continuation_proc.call(result.parsed).parse(result.rest)
else
raise "error"
end
}
end
|
Instance Method Details
#<(other) ⇒ Object
201
202
203
|
# File 'lib/parser_combinator.rb', line 201
def <(other)
self.class.discardr(self, other)
end
|
#>(other) ⇒ Object
197
198
199
|
# File 'lib/parser_combinator.rb', line 197
def >(other)
self.class.discardl(self, other)
end
|
#>>(proc) ⇒ Object
185
186
187
|
# File 'lib/parser_combinator.rb', line 185
def >>(proc)
self.class.so_then(self, &proc)
end
|
#^(other) ⇒ Object
193
194
195
|
# File 'lib/parser_combinator.rb', line 193
def ^(other)
self.class.either_fail(self, other)
end
|
#map(&mapping) ⇒ Object
181
182
183
|
# File 'lib/parser_combinator.rb', line 181
def map(&mapping)
self >> proc{|x| self.class.ok(mapping.call(x))}
end
|
#name(new_name) ⇒ Object
177
178
179
|
# File 'lib/parser_combinator.rb', line 177
def name(new_name)
self.class.new(@status_handler, new_name, &parser_proc)
end
|
#onfail(message = nil, ifnotyet = false, &status_handler) ⇒ Object
159
160
161
162
163
164
165
166
167
168
|
# File 'lib/parser_combinator.rb', line 159
def onfail(message=nil, ifnotyet=false, &status_handler)
raise "Only eihter message or fail_handler can be specified" if message && status_handler
if message
onfail{|items, status| status == nil ? StandardFailStatus.new(message, items) : status}
elsif status_handler
self.class.new(status_handler, @parser_name, &parser_proc)
else
self
end
end
|
#onparse(&proc) ⇒ Object
170
171
172
173
174
175
|
# File 'lib/parser_combinator.rb', line 170
def onparse(&proc)
self.class.new(@status_handler, @parser_name) do |*args|
proc.call(*args)
@parser_proc.call(*args)
end
end
|
#parse(items) ⇒ Object
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/parser_combinator.rb', line 143
def parse(items)
result = @parser_proc.call(items)
case result
when Fail
if @status_handler.call(items, result.status) != nil
result.class.new(@status_handler.call(items, result.status))
else
result
end
when Ok
result
else
raise "parsed object is #{result.inspect}/#{result.class}"
end
end
|
#|(other) ⇒ Object
189
190
191
|
# File 'lib/parser_combinator.rb', line 189
def |(other)
self.class.either(self, other)
end
|