class PegLite::Compiler

Public Class Methods

new(peglite_rule) click to toggle source
# File lib/peglite/compiler.rb, line 5
def initialize peglite_rule
  tokenize peglite_rule
end

Public Instance Methods

compile() click to toggle source
# File lib/peglite/compiler.rb, line 9
def compile
  fail if @tokens.empty?
  if @tokens[0] == '('
    @tokens.shift
    got = compile
    fail if (@tokens.empty? or not @tokens.shift.match /^\)([\?\*\+]?)/)
    got.merge! compile_limits $1
  elsif @tokens.size > 1
    if @tokens[1] == '|'
      got = compile_any
    else
      got = compile_all
    end
  else
    fail @tokens.to_s
  end
  return got
end
compile_all() click to toggle source
# File lib/peglite/compiler.rb, line 28
def compile_all
  fail if @tokens.empty?
  all = []
  until @tokens.empty?
    if @tokens[0] == '('
      all.push compile
    elsif @tokens[0].match /^\)/
      break
    elsif @tokens[0].match /^\w/
      all.push compile_ref
    else
      fail
    end
  end
  return {
    'type' => 'all',
    'rule' => all,
    'min' => 1,
    'max' => 1,
  }
end
compile_any() click to toggle source
# File lib/peglite/compiler.rb, line 50
def compile_any
  fail if @tokens.empty?
  any = []
  until @tokens.empty?
    if @tokens[0] == '('
      any.push compile
    elsif @tokens[0].match /^\)/
      break
    elsif @tokens[0].match /^\w/
      any.push compile_ref
      if not @tokens.empty?
        if @tokens[0] == '|'
          @tokens.shift
        elsif not @tokens[0].match /^\)/
          fail
        end
      end
    else
      fail
    end
  end
  return {
    'type' => 'any',
    'rule' => any,
    'min' => 1,
    'max' => 1,
  }
end
compile_limits(quantifier) click to toggle source
# File lib/peglite/compiler.rb, line 91
def compile_limits quantifier
  case quantifier
  when '?'; { 'min' => 0, 'max' => 1 }
  when '*'; { 'min' => 0, 'max' => 0 }
  when '+'; { 'min' => 1, 'max' => 0 }
  else; { 'min' => 1, 'max' => 1 }
  end
end
compile_ref() click to toggle source
# File lib/peglite/compiler.rb, line 79
def compile_ref
  fail if @tokens.empty?
  token = @tokens.shift
  token.match(/^(\w+)([\?\*\+]?)$/) or fail
  rule, quantifier = $1, $2
  ref = {
    'type' => 'ref',
    'rule' => rule,
  }
  return ref.merge! compile_limits(quantifier)
end
get_token(input) click to toggle source
# File lib/peglite/compiler.rb, line 108
def get_token input
  return if input.empty?
  patterns = [
    /\A\s+/,
    /\A(\()/,
    /\A(\w+[\?\*\+]?)/,
    /\A(\|)/,
    /\A(\)[\?\*\+]?)/,
  ]
  patterns.each do |r|
    if m = input.match(r)
      input.sub! r, ''
      return m.captures
    end
  end
  fail "Failed to find next token in '#{input}'"
end
tokenize(text) click to toggle source
# File lib/peglite/compiler.rb, line 100
def tokenize text
  input = text.clone
  @tokens = []
  while (token = get_token input)
    @tokens.concat token
  end
end