Class: Rips::Assembler
- Inherits:
-
Object
- Object
- Rips::Assembler
- Defined in:
- lib/rips/assembler.rb
Instance Method Summary collapse
-
#<<(value) ⇒ Object
Stores each new line of file.
-
#argument_size ⇒ Object
Check number of arguments given with expected by instruction.
-
#argument_syntax ⇒ Object
Check if arguments are the same variable type of instruction.
-
#exists_instruction ⇒ Object
Exists instruction in Instruction Set?.
-
#find_instructions ⇒ Object
Store number line for each instruction.
-
#find_labels ⇒ Object
Store labels and number line.
-
#generate ⇒ Object
Generate output in “progfile.dat”.
-
#get_instruction ⇒ Object
Obtain instruction’s instance object.
-
#initialize(debug) ⇒ Assembler
constructor
@debug: switch to show trace in console @input: array with assembly instructions @output: array with coded instructions @cmd: line split on tokens (name + arguments) @instruction: instruction instance @instructions: array with line for each instruction @labels: name and number line of label @line: number of file’s line.
-
#parse_input(line) ⇒ Object
Split on tokens.
-
#parse_label ⇒ Object
Translate label’s name to instruction’s number.
-
#run ⇒ Object
Analyze and translate each instruction.
-
#show ⇒ Object
Codification log of instruction.
Constructor Details
#initialize(debug) ⇒ Assembler
@debug: switch to show trace in console @input: array with assembly instructions @output: array with coded instructions @cmd: line split on tokens (name + arguments) @instruction: instruction instance @instructions: array with line for each instruction @labels: name and number line of label @line: number of file’s line
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/rips/assembler.rb', line 14 def initialize (debug) @debug = debug @input = [] @output = [] @cmd = {} @instruction @instructions = [] @labels = {} @line = 1 end |
Instance Method Details
#<<(value) ⇒ Object
Stores each new line of file
54 55 56 |
# File 'lib/rips/assembler.rb', line 54 def << (value) @input << value.strip end |
#argument_size ⇒ Object
Check number of arguments given with expected by instruction
165 166 167 168 169 170 171 172 173 |
# File 'lib/rips/assembler.rb', line 165 def argument_size if @cmd[:arguments].size != @instruction.args_number Error::( 5, @line, @cmd[:name], @cmd[:arguments].size, @instruction.args_number ) end end |
#argument_syntax ⇒ Object
Check if arguments are the same variable type of instruction
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/rips/assembler.rb', line 176 def argument_syntax @instruction.variables.each_with_index do |var,i| if var.syntax? @cmd[:arguments][i] @cmd[:arguments][i] = var.to_i(@cmd[:arguments][i]) else Error::( 6, @line, var.error(@cmd[:arguments][i]) ) end end end |
#exists_instruction ⇒ Object
Exists instruction in Instruction Set?
156 157 158 159 160 161 162 |
# File 'lib/rips/assembler.rb', line 156 def exists_instruction if !Instructions::SET.include? (@cmd[:name]) Error::( 4, @line, @cmd[:name] ) end end |
#find_instructions ⇒ Object
Store number line for each instruction
44 45 46 47 48 49 50 51 |
# File 'lib/rips/assembler.rb', line 44 def find_instructions @input.each_with_index do |line,i| if (!line.empty?) && (line.scan(/\w+:/).empty?) && (line[0] != "#") @instructions << i+1 end end end |
#find_labels ⇒ Object
Store labels and number line
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rips/assembler.rb', line 26 def find_labels @input.each_with_index do |line, i| if !line.empty? label = line.scan(/\w+:/) if (label.size == 1) if !@labels.include?(label[0].to_s.split(":").first) @labels[label[0].to_s.split(":").first] = [*@instructions.each_with_index].bsearch{|x, _| x >= i}.last else Error::(7, i+1, label[0].to_s.split(":").first) end end end end end |
#generate ⇒ Object
Generate output in “progfile.dat”
111 112 113 114 115 116 117 |
# File 'lib/rips/assembler.rb', line 111 def generate File.open("progfile.dat", "w") do |f| @output.each do |line| f.puts line end end end |
#get_instruction ⇒ Object
Obtain instruction’s instance object
151 152 153 |
# File 'lib/rips/assembler.rb', line 151 def get_instruction Object.const_get("Rips::Instructions::#{@cmd[:name].capitalize}").new end |
#parse_input(line) ⇒ Object
Split on tokens
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/rips/assembler.rb', line 120 def parse_input (line) if line[0] == "#" @cmd[:comments] = line else @cmd[:name] = line.split("#").first.split(" ").first.downcase @cmd[:arguments] = line.split("#").first.split("#{@cmd[:name]} ") if !@cmd[:arguments].empty? @cmd[:arguments] = @cmd[:arguments].pop.split("#").first.del(/\s+|\t+/).split(",") end if @cmd[:arguments].first == "jr" || @cmd[:arguments].first == "nop" @cmd[:arguments] = [] end @cmd[:comments] = line.split("#").slice(1..-1).join @cmd[:comments].insert(0,"#") if !@cmd[:comments].empty? end end |
#parse_label ⇒ Object
Translate label’s name to instruction’s number
140 141 142 143 144 145 146 147 148 |
# File 'lib/rips/assembler.rb', line 140 def parse_label if (@instruction.is_a? Rips::Instructions::Beqz) || (@instruction.is_a? Rips::Instructions::Bnez) || (@instruction.is_a? Rips::Instructions::J) || (@instruction.is_a? Rips::Instructions::Jal) @cmd[:arguments] = [@labels[@cmd[:arguments].first].to_s] end end |
#run ⇒ Object
Analyze and translate each instruction
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rips/assembler.rb', line 59 def run find_instructions find_labels @input.each do |line| # If line is empty -> next line # Or if not is a label if (!line.empty?) && (line.scan(/\w+:/).empty?) parse_input(line) @instruction = nil # If it's a comment -> show but not work with it if line[0] != "#" exists_instruction @instruction = get_instruction parse_label argument_size argument_syntax @instruction.set_arguments(@cmd[:arguments]) @output << @instruction.code end show if @debug end @line += 1 end generate end |
#show ⇒ Object
Codification log of instruction
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/rips/assembler.rb', line 96 def show # If line was a comment -> @instruction should be nil if @instruction.nil? codification = "" else codification = @instruction.code.scan(/.{4}|.+/).join("_") end puts "@#{@line}:" \ "\t#{codification}" \ "\t#{@cmd[:comments]}" end |