Class: LLIP::ProductionCompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/llip/production_compiler.rb

Overview

It’s the main class which handles the generation of the source code dinamically.

Direct Known Subclasses

RecursiveProductionCompiler

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProductionCompiler

Returns a new instance of ProductionCompiler.



10
11
12
# File 'lib/llip/production_compiler.rb', line 10

def initialize
  reset
end

Instance Attribute Details

#codeObject (readonly)

It contains the produced



8
9
10
# File 'lib/llip/production_compiler.rb', line 8

def code
  @code
end

Instance Method Details

#compile(production) ⇒ Object

It takes a ProductionSpecification and then call its compiling methods by itself. It takes care to order all the productions the right way.



79
80
81
82
83
# File 'lib/llip/production_compiler.rb', line 79

def compile(production)
  start(production.name)
  sort_production(production).each { |tk| token(tk)}
  self.end(production.raise_on_error)
end

#end(raise_on_error = true) ⇒ Object

It closes the method definition



66
67
68
69
# File 'lib/llip/production_compiler.rb', line 66

def end(raise_on_error=true)
  build_else(raise_on_error) if @else != ""
  build_end
end

#resetObject

It resets the compiler



72
73
74
75
76
# File 'lib/llip/production_compiler.rb', line 72

def reset
  @code = ""
  @name = nil
  @else = ""
end

#sort_production(production) ⇒ Object

:nodoc:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/llip/production_compiler.rb', line 85

def sort_production(production) # :nodoc:
  tokens = production.tokens
    
  lk_tk = []
  not_lk_tk = []
    
  tokens.keys.each	do |tk|
    if tk.kind_of? Array
      lk_tk << tk
      lk_tk << tk[0] if tokens.has_key? tk[0]
    end
  end	
    
  not_lk_tk = tokens.keys - lk_tk
    
  lk_tk.uniq!	
  lk_tk.sort! do |a,b|
    if a.kind_of? Array and b.kind_of? Array
      if a.size > b.size
        -1
      else
        1
      end
    elsif a.kind_of? Array and not b.kind_of? Array
      -1
    else
      1
    end
  end
   	
  if not_lk_tk.include? :everything
    ret_value = not_lk_tk + lk_tk
    ret_value.delete(:everything)
    ret_value << :everything
    ret_value
  else
    not_lk_tk + lk_tk
  end
end

#start(name) ⇒ Object

It initializes the compiler for a new generation.



15
16
17
18
19
20
21
22
23
24
# File 'lib/llip/production_compiler.rb', line 15

def start(name)
  reset
  @name_str = name
  @name = str_to_sym(name)
  @code << <<-CODE
			def parse_#{name}
result = productions[#{@name}].default.call(@scanner,self)
		CODE
  self
end

#token(tokens) ⇒ Object

:call-seq: token(Array) token(Symbol) token(String)

If the argument is a Symbol or a String, the produced code will match them through ==. It the argument is an Array, lookaheads will be used, so the scanner must support lookaheads (or use a Buffer which supports them).



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/llip/production_compiler.rb', line 33

def token(tokens)
  lookaheads = ""
  name = nil
  token_identifier = nil
  
  if tokens.kind_of? Array
    tokens_names = tokens.map { |tk| build_token_name(tk) }
    token_identifier = "["
    tokens_names.each { |tk| token_identifier << tk + "," }
    token_identifier[-1] = "]"	
    
    name = build_token_name(tokens[0])
    counter = 0
    tokens[1..-1].each do |token|
      lookaheads << " and " 
      counter += 1
      token = build_token_name(token)
      lookaheads << "@scanner.lookahead(#{counter}) == #{token}"
    end
  else
    name = build_token_name(tokens)
    token_identifier = name
  end
  
  @code << <<-CODE
			#{@else}if @scanner.current == #{name}#{lookaheads}
result = productions[#{@name}].tokens[#{token_identifier}].call(result,@scanner,self)
		CODE
  @else = "els"
  self
end