Class: PegLite::Compiler

Inherits:
Object
  • Object
show all
Defined in:
lib/peglite/compiler.rb

Overview


Instance Method Summary collapse

Constructor Details

#initialize(peglite_rule) ⇒ Compiler

Returns a new instance of Compiler.



5
6
7
# File 'lib/peglite/compiler.rb', line 5

def initialize peglite_rule
  tokenize peglite_rule
end

Instance Method Details

#compileObject



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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_allObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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_anyObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 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) ⇒ Object



91
92
93
94
95
96
97
98
# 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_refObject



79
80
81
82
83
84
85
86
87
88
89
# 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) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/peglite/compiler.rb', line 100

def tokenize text
  input = text.clone
  @tokens = []
  while (token = get_token input)
    @tokens.concat token
  end
end