Class: LLIP::ProductionCompiler
- Inherits:
-
Object
- Object
- LLIP::ProductionCompiler
- 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
Instance Attribute Summary collapse
-
#code ⇒ Object
readonly
It contains the produced.
Instance Method Summary collapse
-
#compile(production) ⇒ Object
It takes a ProductionSpecification and then call its compiling methods by itself.
-
#end(raise_on_error = true) ⇒ Object
It closes the method definition.
-
#initialize ⇒ ProductionCompiler
constructor
A new instance of ProductionCompiler.
-
#reset ⇒ Object
It resets the compiler.
-
#sort_production(production) ⇒ Object
:nodoc:.
-
#start(name) ⇒ Object
It initializes the compiler for a new generation.
-
#token(tokens) ⇒ Object
:call-seq: token(Array) token(Symbol) token(String).
Constructor Details
#initialize ⇒ ProductionCompiler
Returns a new instance of ProductionCompiler.
10 11 12 |
# File 'lib/llip/production_compiler.rb', line 10 def initialize reset end |
Instance Attribute Details
#code ⇒ Object (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 |
#reset ⇒ Object
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 |