class Python::Parser::Combinator

Constants

ParserDefinitionError

Attributes

f[RW]

Public Class Methods

any_char(x) click to toggle source
# File lib/python/parser/combinator.rb, line 127
def self.any_char(x)
  case x
  when String
    chars = x.cahrs.map{|c| char(c)}
    if chars.length < 0
      raise ParserDefinitionError.new
    else
      chars.inject(&:|)
    end
  when Range
    chars = x.map{|c| char(c)}
    if chars.length < 0
      raise ParserDefinitionError.new
    else
      chars.inject(&:|)
    end
  else
    raise ParserDefinitionError.new
  end
end
binopl(parser, op_proc_parser) click to toggle source
# File lib/python/parser/combinator.rb, line 178
def self.binopl(parser, op_proc_parser)
  rest = proc{|a|
    op_proc_parser >> proc{|f|
      parser >> proc{|b|
        rest.call(f.call(a, b))
      }} | ret(a)
  }
  parser >> proc{|a|
    rest.call(a)
  }
end
char(char) click to toggle source
# File lib/python/parser/combinator.rb, line 123
def self.char(char)
  sat{|c| c == char}
end
discardl(parser1, parser2) click to toggle source
# File lib/python/parser/combinator.rb, line 80
def self.discardl(parser1, parser2)
  parser1 >> proc{parser2}
end
discardr(parser1, parser2) click to toggle source
# File lib/python/parser/combinator.rb, line 84
def self.discardr(parser1, parser2)
  parser1 >> proc{|x|
    parser2 >> proc{
      ret(x)
    }}
end
either(parser1, parser2) click to toggle source
# File lib/python/parser/combinator.rb, line 67
def self.either(parser1, parser2)
  new{|inp|
    case result = parser1.parse(inp)
    when Failed
      parser2.parse(inp)
    when Succeeded
      result
    else
      raise "error."
    end
  }
end
failure() click to toggle source
# File lib/python/parser/combinator.rb, line 46
def self.failure
  new{|inp| Failed.new}
end
item() click to toggle source
# File lib/python/parser/combinator.rb, line 50
def self.item
  new{|inp| inp.size == 0 ? Failed.new : Succeeded.new(inp[0], inp[1, inp.size - 1])}
end
many(parser) click to toggle source
# File lib/python/parser/combinator.rb, line 106
def self.many(parser)
  many1(parser) | ret([])
end
many1(parser) click to toggle source
# File lib/python/parser/combinator.rb, line 110
def self.many1(parser)
  parser >> proc{|x|
    many(parser) >> proc{|xs|
      ret([x] + xs)
    }}
end
new(&proc) click to toggle source
# File lib/python/parser/combinator.rb, line 18
def initialize(&proc)
  @f = proc
end
optional(parser) click to toggle source
# File lib/python/parser/combinator.rb, line 102
def self.optional(parser)
  (parser >> proc{|x| ret([x])}) | ret([])
end
parser(name, &proc) click to toggle source
# File lib/python/parser/combinator.rb, line 190
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
      @cache[key] = self.new{}
      @cache[key].f = proc.call(*args).f
      return @cache[key]
    end
  end
end
ret(something) click to toggle source
# File lib/python/parser/combinator.rb, line 42
def self.ret(something)
  new{|inp| Succeeded.new(something, inp)}
end
sat(&proc) click to toggle source
# File lib/python/parser/combinator.rb, line 117
def self.sat(&proc)
  item >> proc{|c|
    proc.call(c) ? ret(c) : failure
  }
end
separator(element_parser, separating_token_str) click to toggle source
# File lib/python/parser/combinator.rb, line 91
def self.separator(element_parser, separating_token_str)
  element_parser >> proc{|x|
    many(token_str(separating_token_str) + element_parser) >> proc{|xs|
      ret([x] + xs)
    }}
end
separator_allow_empty(element_parser, separating_token_str) click to toggle source
# File lib/python/parser/combinator.rb, line 98
def self.separator_allow_empty(element_parser, separating_token_str)
  separator(element_parser, separating_token_str) | ret([])
end
so(parser, &proc) click to toggle source
# File lib/python/parser/combinator.rb, line 54
def self.so(parser, &proc)
  new{|inp|
    case result = parser.parse(inp)
    when Failed
      result
    when Succeeded
      proc.call(result.parsed).parse(result.rest)
    else
      raise "error."
    end
  }
end
string(str) click to toggle source
# File lib/python/parser/combinator.rb, line 148
def self.string(str)
  if str.size == 0
    ret(str)
  else
    char(str[0]) >> proc{|c|
      string(str[1, str.size - 1]) >> proc{
        ret(str)
      }
    }
  end
end
token(parser) click to toggle source
# File lib/python/parser/combinator.rb, line 166
def self.token(parser)
  whitespace >> proc{
    parser >> proc{|x|
      whitespace >> proc{
        ret(x)
      }}}
end
token_str(str) click to toggle source
# File lib/python/parser/combinator.rb, line 174
def self.token_str(str)
  token(string(str))
end
whitespace() click to toggle source
# File lib/python/parser/combinator.rb, line 160
def self.whitespace
  many(char("\s") | char("\t")) >> proc{|ws|
    ret(:whitespace)
  }
end

Public Instance Methods

+(other) click to toggle source
# File lib/python/parser/combinator.rb, line 34
def +(other)
  self.class.discardl(self, other)
end
-(other) click to toggle source
# File lib/python/parser/combinator.rb, line 38
def -(other)
  self.class.discardr(self, other)
end
>>(proc) click to toggle source
# File lib/python/parser/combinator.rb, line 26
def >>(proc)
  self.class.so(self, &proc)
end
parse(inp) click to toggle source
# File lib/python/parser/combinator.rb, line 22
def parse(inp)
  @f.call(inp)
end
|(other) click to toggle source
# File lib/python/parser/combinator.rb, line 30
def |(other)
  self.class.either(self, other)
end