class ParserCombinator
Constants
- ParserCombinatorError
- VERSION
Attributes
parser_name[R]
parser_proc[R]
status_handler[R]
Public Class Methods
binopl(parser, op_proc_parser)
click to toggle source
# File lib/parser_combinator.rb, line 292 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)
click to toggle source
# File lib/parser_combinator.rb, line 304 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)
click to toggle source
# File lib/parser_combinator.rb, line 281 def self.discardl(parser1, parser2) parser1 >> proc{parser2} end
discardr(parser1, parser2)
click to toggle source
# File lib/parser_combinator.rb, line 285 def self.discardr(parser1, parser2) parser1 >> proc{|x| parser2 >> proc{ ok(x) }} end
either(parser1, parser2)
click to toggle source
# File lib/parser_combinator.rb, line 193 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)
click to toggle source
# File lib/parser_combinator.rb, line 206 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
end_of_input()
click to toggle source
# File lib/parser_combinator.rb, line 227 def self.end_of_input new{|i| i.size == 0 ? Ok.new(nil, i) : Fail.new} end
fail(status=nil)
click to toggle source
# File lib/parser_combinator.rb, line 176 def self.fail(status=nil) new{|i| Fail.new(status)} end
item()
click to toggle source
# File lib/parser_combinator.rb, line 223 def self.item new{|i| i.size == 0 ? Fail.new : Ok.new(i.head, i.rest)} end
many(parser, separator_parser=ok(nil))
click to toggle source
# File lib/parser_combinator.rb, line 255 def self.many(parser, separator_parser=ok(nil)) many1(parser, separator_parser) | ok([]) end
many1(parser, separator_parser=ok(nil))
click to toggle source
# File lib/parser_combinator.rb, line 259 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))
click to toggle source
# File lib/parser_combinator.rb, line 274 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))
click to toggle source
# File lib/parser_combinator.rb, line 270 def self.many_fail(parser, separator_parser=ok(nil)) many1_fail(parser, separator_parser) ^ ok([]) end
new(status_handler=proc{nil}, name=nil, &proc)
click to toggle source
# File lib/parser_combinator.rb, line 101 def initialize(status_handler=proc{nil}, name=nil, &proc) @status_handler = status_handler @parser_name = name @parser_proc = proc end
ok(object)
click to toggle source
CoreCombinator
# File lib/parser_combinator.rb, line 172 def self.ok(object) new{|i| Ok.new(object, i)} end
opt(parser)
click to toggle source
# File lib/parser_combinator.rb, line 251 def self.opt(parser) parser.map{|x| [x]} | ok([]) end
opt_fail(parser)
click to toggle source
# File lib/parser_combinator.rb, line 266 def self.opt_fail(parser) parser.map{|x| [x]} ^ ok([]) end
parser(name, &proc)
click to toggle source
Memorization DSL suport (for recursive grammer)
# File lib/parser_combinator.rb, line 319 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)
click to toggle source
# File lib/parser_combinator.rb, line 231 def self.sat(&item_cond_proc) item >> proc{|i| item_cond_proc.call(i.item) ? ok(i) : fail } end
seq(*parsers)
click to toggle source
UtilCombinator
# File lib/parser_combinator.rb, line 240 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)
click to toggle source
# File lib/parser_combinator.rb, line 180 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
Public Instance Methods
<(other)
click to toggle source
# File lib/parser_combinator.rb, line 165 def <(other) self.class.discardr(self, other) end
>(other)
click to toggle source
# File lib/parser_combinator.rb, line 161 def >(other) self.class.discardl(self, other) end
>>(proc)
click to toggle source
# File lib/parser_combinator.rb, line 149 def >>(proc) self.class.so_then(self, &proc) end
^(other)
click to toggle source
# File lib/parser_combinator.rb, line 157 def ^(other) self.class.either_fail(self, other) end
map(&mapping)
click to toggle source
# File lib/parser_combinator.rb, line 145 def map(&mapping) self >> proc{|x| self.class.ok(mapping.call(x))} end
name(new_name)
click to toggle source
# File lib/parser_combinator.rb, line 141 def name(new_name) self.class.new(@status_handler, new_name, &parser_proc) end
onfail(message=nil, ifnotyet=false, &status_handler)
click to toggle source
# File lib/parser_combinator.rb, line 123 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)
click to toggle source
# File lib/parser_combinator.rb, line 134 def onparse(&proc) self.class.new(@status_handler, @parser_name) do |*args| proc.call(*args) @parser_proc.call(*args) end end
parse(items)
click to toggle source
# File lib/parser_combinator.rb, line 107 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)
click to toggle source
# File lib/parser_combinator.rb, line 153 def |(other) self.class.either(self, other) end