- fix "negative" spacing bug w/better debug out

- now checks for negative values when indenting comments, forces a space
- now catches errors a little more gracefully, giving you the source line where it failed
This commit is contained in:
Dagen Brock 2017-12-27 09:25:32 -06:00
parent a9e13efea6
commit 83ff82b5fe
1 changed files with 146 additions and 132 deletions

278
radius.rb
View File

@ -77,151 +77,165 @@ file.close unless file.nil?
# begin line-by-line processing
output_buf = ""
# most editors will start numbering with line 1
linenum = 1
source_contents.each_line do |line|
# state machine - resets each line
in_quote = false
in_comment = false
label_done = false
in_label = false
opcode_done = false
in_opcode = false
operand_done = false
in_operand = false
chars_started = false
quote_char = false
x=0
# we catch any issue that causes radius to fail and just print out the line
# that it failed on. not the best, but *shrug*
begin
# state machine - resets each line
in_quote = false
in_comment = false
label_done = false
in_label = false
opcode_done = false
in_opcode = false
operand_done = false
in_operand = false
chars_started = false
quote_char = false
x=0
buf = "" # line buffer, starts empty each line and is appended to output_buf
buf = "" # line buffer, starts empty each line and is appended to output_buf
# begin char-by-char processing
line.each_char.with_index(0) do |c, i|
# begin char-by-char processing
line.each_char.with_index(0) do |c, i|
# starts with whitespace? do an indent
if i == 0 && c.strip.empty?
buf << " "*mnemonic_col_x # optimize?
x+=mnemonic_col_x
label_done = true
next # SHORT CIRCUIT
end
# are we in a comment? just print the char
if in_comment
# don't print embedded newline :P
if !c.include?("\n")
buf << c
x+=1
end
next # SHORT CIRCUIT
end
# are we in a quote? print, but also look for matching end quote
if in_quote
##print c
buf << c
x+=1
if c == quote_char # second quotes
in_quote = false
end
next # SHORT CIRCUIT
end
# not already in comment or quote
if c.strip.empty?
#ignore
if in_label
in_label = false
# starts with whitespace? do an indent
if i == 0 && c.strip.empty?
buf << " "*mnemonic_col_x # optimize?
x+=mnemonic_col_x
label_done = true
# do we need to bump out space
if x > mnemonic_col_x-min_space
buf << " "*min_space # optimize?
x+=min_space
else
buf << " "*(mnemonic_col_x-x) # optimize ?
x+=mnemonic_col_x-x
end
elsif in_opcode
in_opcode = false
opcode_done = true
# do we need to bump out space
if x > operand_col_x-min_space
buf << " "*min_space
x+=min_space
else
buf << " "*(operand_col_x-x)
x+=operand_col_x-x
end
elsif in_operand
in_operand = false
operand_done = true
# do we need to bump out space
if x > comment_col_x-min_space
buf << " "*min_space
x+=min_space
else
buf << " "*(comment_col_x-x)
x+=comment_col_x-x
end
next # SHORT CIRCUIT
end
# are we in a comment? just print the char
if in_comment
# don't print embedded newline :P
if !c.include?("\n")
buf << c
x+=1
end
next # SHORT CIRCUIT
end
next
else
chars_started = true
# see if we are starting a quote
if c == '"' || c == "'"
quote_char = c
in_quote = true
buf << c
# see if we are starting a line with a comment
elsif (c == ';' || c == '*') && i == 0
in_comment = true
buf << c
x+=1
# found a semi-colon not in an operand (macro!danger)
# (and not in quote or comment)
elsif c == ';' && !in_operand
in_comment = true
buf << " "*(comment_col_x-x)
x+=comment_col_x-x
buf << c
x+=1
# found asterisk preceded only by whitespace
elsif c == '*' && line[0..i-1].strip.empty?
in_comment = true
buf << c
x+=1
# real label!
elsif i == 0
buf << ""
in_label = true
buf << c
x+=1
# already in label?
elsif in_label
buf << c
x+=1
# real opcode!
elsif label_done && !opcode_done
in_opcode = true
buf << c
x+=1
# already in opcode
elsif in_opcode
buf << c
x+=1
# real operand!
elsif opcode_done && !operand_done
in_operand = true
buf << c
x+=1
# already in operand
elsif in_operand
# are we in a quote? print, but also look for matching end quote
if in_quote
##print c
buf << c
x+=1
if c == quote_char # second quotes
in_quote = false
end
next # SHORT CIRCUIT
end
# not already in comment or quote
if c.strip.empty?
#ignore
if in_label
in_label = false
label_done = true
# do we need to bump out space
if x > mnemonic_col_x-min_space
buf << " "*min_space # optimize?
x+=min_space
else
buf << " "*(mnemonic_col_x-x) # optimize ?
x+=mnemonic_col_x-x
end
elsif in_opcode
in_opcode = false
opcode_done = true
# do we need to bump out space
if x > operand_col_x-min_space
buf << " "*min_space
x+=min_space
else
buf << " "*(operand_col_x-x)
x+=operand_col_x-x
end
elsif in_operand
in_operand = false
operand_done = true
# do we need to bump out space
if x > comment_col_x-min_space
buf << " "*min_space
x+=min_space
else
buf << " "*(comment_col_x-x)
x+=comment_col_x-x
end
end
next
else
chars_started = true
# see if we are starting a quote
if c == '"' || c == "'"
quote_char = c
in_quote = true
buf << c
# see if we are starting a line with a comment
elsif (c == ';' || c == '*') && i == 0
in_comment = true
buf << c
x+=1
# found a semi-colon not in an operand (macro!danger)
# (and not in quote or comment)
elsif c == ';' && !in_operand
in_comment = true
# protect against "negative" spacing
spaces = 1 > (comment_col_x-x) ? 1 : (comment_col_x-x)
buf << " "*spaces
x+=comment_col_x-x
buf << c
x+=1
# found asterisk preceded only by whitespace
elsif c == '*' && line[0..i-1].strip.empty?
in_comment = true
buf << c
x+=1
# real label!
elsif i == 0
buf << ""
in_label = true
buf << c
x+=1
# already in label?
elsif in_label
buf << c
x+=1
# real opcode!
elsif label_done && !opcode_done
in_opcode = true
buf << c
x+=1
# already in opcode
elsif in_opcode
buf << c
x+=1
# real operand!
elsif opcode_done && !operand_done
in_operand = true
buf << c
x+=1
# already in operand
elsif in_operand
buf << c
x+=1
end
end
end
rescue Exception => ex
puts "An error of type #{ex.class} happened, message is #{ex.message}"
abort("We failed to parse on line #{linenum}")
end
linenum+=1
# move line to buffer, stripping trailing spaces
output_buf << buf.rstrip << "\n"
end