lib/kompiler/parsers.rb in kompiler-0.2.0 vs lib/kompiler/parsers.rb in kompiler-0.3.0.pre.1
- old
+ new
@@ -84,11 +84,14 @@
end
def self.check_register_operand(str)
Kompiler::Architecture.registers.each do |register|
- return [true, register] if str == register[:reg_name]
+ # Downcase both the string and the register if the register name is not case sensitive (the default)
+ processed_str = register[:case_sensitive] ? str : str.downcase
+ processed_reg_name = register[:case_sensitive] ? register[:reg_name] : register[:reg_name].downcase
+ return [true, register] if processed_str == processed_reg_name
end
return [false, nil]
end
def self.check_binary_operand(str)
@@ -170,20 +173,20 @@
def self.check_immediate_operand(operand_str)
is_bin, bin_value = check_binary_operand(operand_str)
- return [true, {type: "immediate", value: bin_value, def_type: "binary"}] if is_bin
+ return [true, {type: "immediate", value: bin_value, def_type: "binary", definition: operand_str}] if is_bin
is_decimal, decimal_value = check_decimal_operand(operand_str)
- return [true, {type: "immediate", value: decimal_value, def_type: "decimal"}] if is_decimal
+ return [true, {type: "immediate", value: decimal_value, def_type: "decimal", definition: operand_str}] if is_decimal
is_hex, hex_value = check_hex_operand(operand_str)
- return [true, {type: "immediate", value: hex_value, def_type: "hex"}] if is_hex
+ return [true, {type: "immediate", value: hex_value, def_type: "hex", definition: operand_str}] if is_hex
is_char, char_value = check_char_operand(operand_str)
- return [true, {type: "immediate", value: char_value, def_type: "char"}] if is_char
+ return [true, {type: "immediate", value: char_value, def_type: "char", definition: operand_str}] if is_char
return [false, nil]
end
@@ -206,15 +209,15 @@
def self.parse_operand_str(operand_str)
# Check if the operand is a register
is_register, register = check_register_operand(operand_str)
- return {type: "register", value: register, register: register} if is_register
+ return {type: "register", value: register, register: register, definition: operand_str} if is_register
# Check if the operand is a string
is_string = operand_str[0] == "\""
- return {type: "string", value: operand_str[1...-1], string: operand_str[1...-1]} if is_string
+ return {type: "string", value: operand_str[1...-1], string: operand_str[1...-1], definition: operand_str} if is_string
# Checks if it's an immediate
is_immediate, immediate_val = check_immediate_operand(operand_str)
return immediate_val if is_immediate
@@ -223,11 +226,11 @@
# Check if it's a label
#
# The operand is a label if it doesn't start with a number and doesn't include spaces
is_label = check_label_operand(operand_str)
- return {type: "label", value: operand_str} if is_label
+ return {type: "label", value: operand_str, definition: operand_str} if is_label
# If no checks succeeded, return false
return false
end
@@ -317,140 +320,52 @@
return [keyword, operands]
end
-
-
-# def self.parse_instruction_line(line)
-# keyword = ""
-# i = 0
-#
-# # Loop until a non-whitespace character
-# while i < line.size
-# break if ![" ", "\t"].include?(line[i])
-# i += 1
-# end
-#
-# # Loop to get the keyword
-# loop do
-# # Exit out of the loop if the character is a whitespace
-# break if [" ", "\t"].include?(line[i]) || i >= line.size
-# # Add the character if not a whitespace
-# keyword << line[i]
-# # Proceed to the next character
-# i += 1
-# end
-#
-# operand_strings = []
-#
-# # Loop for operands
-# loop do
-# break if i >= line.size
-#
-# # Whitespace - skip
-# if [" ", "\t"].include? line[i]
-# i += 1
-# next
-# end
-#
-# # If a string operand - parse the string
-# if line[i] == "\""
-#
-# str_content, parsed_size = parse_str(line[i..])
-# operand_strings << line[i...(i + parsed_size)]
-# i += parsed_size
-#
-# # If anything else - parse until whitespace, comma or end of line
-# else
-# content = ""
-#
-# while i < line.size
-# break if [" ", ","].include? line[i]
-# content << line[i]
-# i += 1
-# end
-#
-# operand_strings << content
-# end
-#
-#
-# # After operand parsed
-# # Loop to meet a comma or end of line
-# # Give error if stuff except whitespace
-#
-# while i < line.size
-# # If comma, move to next character and repeat the bigger operand loop
-# if line[i] == ","
-# i += 1
-# break
-# end
-# # If non-whitespace, raise an error
-# # raise "Error: Unparsed content - exiting" if ![" ", "\t"].include?(line[i])
-# return false if ![" ", "\t"].include?(line[i])
-# i += 1
-# end
-# end
-#
-# # If end of line not reached, return an error
-# if i != line.size
-# return false
-# end
-#
-#
-# # Parse operand strings into operand types and values
-#
-# operands = []
-#
-# operand_strings.each do |operand_str|
-# operand = parse_operand_str(operand_str)
-# return false if operand == false
-# operands << operand
-# end
-#
-# return [keyword, operands]
-# end
-
-
-
def self.check_operand_match(operand_description, operand)
# If operand type doesn't not match, return false
return false if operand[:type] != operand_description[:type]
- # If no operand restrictions, return true
- return true if !operand_description.keys.include?(:restrictions)
+ # Get the restrictions
+ operand_restrictions = operand_description[:restrictions]
+ return true if !operand_restrictions # If no restrictions, return true
- case operand_description[:type]
+ # Get the operand's values / encoding
+ case operand[:type]
when "register"
-
- # Check register type match
- if operand_description[:restrictions].keys.include?(:reg_type)
- return false if operand[:register][:reg_type] != operand_description[:restrictions][:reg_type]
- end
-
- # Check register size match
- if operand_description[:restrictions].keys.include?(:reg_size)
- return false if operand[:register][:reg_size] != operand_description[:restrictions][:reg_size]
- end
-
+ operand_encoding = operand[:value]
when "immediate"
-
-
-
- when "label"
-
-
-
+ operand_encoding = operand[:value]
+ when "string"
+ operand_encoding = Hash.new
end
+
+ # Loop through each restriction to see if the operand matches it
+ operand_restrictions.each do |r_key, r_spec|
+ # Get the restricted value of the operand
+ op_value = operand_encoding[r_key]
+
+ # Check if it matches the restriction specification
+ # If an array, the OR algorithm works (the operand key value must be one of the specified values in the r_spec list)
+ if r_spec.is_a? Array
+ return false if !r_spec.include?(op_value)
+ else # If not an array, just check of equality
+ return false if op_value != r_spec
+ end
+ end
# If the restrictions match (by not returning a negative answer), return true
return true
end
+
+
+
# Returns array of [status, operands]
# If status = false, operands = nil; otherwise, status = true, operands = instruction operands
def self.match_instruction(line, instruction)
keyword, operands = parse_instruction_line(line)
@@ -529,6 +444,6 @@
end # End Kompiler::Parsers
-end # End Kompiler
\ No newline at end of file
+end # End Kompiler