move some unused parse related classes out of the way

This commit is contained in:
Torsten Ruger
2014-04-16 12:10:58 +03:00
parent 69b0f7a0e3
commit 8e0494f410
7 changed files with 2 additions and 2 deletions

View File

@ -1,4 +1,4 @@
require "asm/parser"
require "asm/nodes"
module Asm
module Arm

View File

@ -1,7 +1,7 @@
require 'asm/arm/arm_assembler'
require 'asm/arm/instruction'
require 'asm/label_object'
require 'asm/parser'
require 'asm/nodes'
require 'stream_reader'
require 'stringio'

View File

@ -1,149 +0,0 @@
require_relative 'parser'
require_relative 'assembler'
require_relative 'objectwriter'
require 'optparse'
require 'ostruct'
module Asm
class CommandLine
def initialize
options = OpenStruct.new
options.output_file = "a.out"
options.target = :arm
opts = OptionParser.new do |opts|
opts.banner = "Usage: as [options] <input file>"
opts.separator ""
opts.separator "Options:"
opts.on("-t", "--target TARGET",
"Specify target architecture (arm [default], ttk91)") { |o|
options.target = o.to_sym
if (not [:arm, :ttk91].include?(options.target))
puts opts
exit
end
}
opts.on("-o", "--output FILENAME",
"Specify output filename for object file") { |o|
options.output_file = o
}
opts.on("-s", "--show-ast",
"Show parse tree") { |o|
options.show_ast = true
}
opts.on_tail("-h", "--help", "Show this message") {
puts opts
exit
}
end
opts.parse!(ARGV)
options.input_file = ARGV.shift
if (not options.input_file)
puts opts
exit
end
@options = options
end
attr_reader :options
def run
begin
if (options.input_file == '-')
code = $stdin.read
else
code = File.read(options.input_file)
end
rescue => err
puts 'as: could not read input file: ' + err.message
exit 2
end
begin
ast = Asm::Parser.parse(code)
rescue Asm::ParseError => err
puts 'as: parse error on line %d, column %d' % [err.line+1, err.column+1]
line = code.split("\n")[err.line]
puts line.gsub(/\s/, ' ')
puts ' ' * (err.column-1) + '^'
puts ' ' + err.message
exit 3
end
if (options.show_ast)
require 'pp'
pp ast
exit 0
end
case options.target
when :arm
require_relative 'arm_assembler.rb'
as_module = Asm::Arm
as_target = Elf::Constants::TARGET_ARM
when :ttk91
require_relative 'ttk91_assembler.rb'
as_module = Asm::TTK91
as_target = Elf::Constants::TARGET_TTK91
end
asm = Asm::AstAssembler.new(as_module)
begin
asm.load_ast ast
data = StringIO.new
asm.assemble(data)
symbols = asm.symbols
rescue Asm::AssemblyError => err
if (err.node)
puts 'as: assembly error on line %d, column %d' % [
err.node.line+1, err.node.column+1]
line = code.split("\n")[err.node.line]
puts line.gsub(/\s/, ' ')
puts ' ' * (err.node.column-1) + '^'
puts ' ' + err.message
else
puts 'as: ' + err.message
end
exit 4
end
writer = Asm::ObjectWriter.new(as_target)
writer.set_text data.string
reloc_name_ref = {}
symbols.each { |symbol|
label = symbol[:label]
if (label.extern?)
reloc_name_ref[label] = symbol[:name]
writer.add_reloc_symbol symbol[:name]
else
writer.add_symbol symbol[:name], symbol[:label].address, symbol[:linkage]
end
}
asm.relocations.each { |reloc|
writer.add_reloc reloc.position, reloc_name_ref[reloc.label], reloc.type
}
begin
writer.save(options.output_file)
rescue => err
puts 'as: cannot save output file: ' + err.message
end
end
end
end
if (__FILE__ == $0)
Asm::CommandLine.new.run
end

View File

@ -1,204 +0,0 @@
require_relative 'str_scanner'
require_relative 'nodes'
module Asm
class Parser
def initialize(str)
scanner = Asm::Scanner.new(str)
@ast = parse_toplevel scanner
end
attr_reader :ast
def self.parse(str)
new(str).ast
end
def parse_toplevel(s)
node = ToplevelNode.new(s)
node.children = []
while (not s.eos?)
node.children << parse(s)
end
node
end
def parse(s)
s.scan /\s*/
node = nil
%w(comment directive label instruction).each { |em|
if (node = send('parse_'+em, s))
break
end
}
raise Asm::ParseError.new('could not parse element', s) unless node
s.scan /\s*/
node
end
def parse_comment(s)
if (s.scan(/;.*?$/))
CommentNode.new(s)
end
end
def parse_directive(s)
if (m = s.scan(/\.(\w+)(?:(?!$)\s+(.+)\s*?$)?/))
DirectiveNode.new(s) { |n|
n.name = m[0]
n.value = m[1]
}
end
end
def parse_label(s)
if (m = s.scan(/(\/*\w+):/))
LabelNode.new(s) { |n|
n.name = m[0]
}
end
end
def parse_instruction(s)
if (m = s.scan(/(\w+)/))
node = InstructionNode.new(s) { |n|
n.opcode = m[0]
n.args = []
}
if (not s.scan(/\s*($|;)/))
loop {
arg = parse_arg(s)
node.args << arg
break if not s.scan(/\s*,/)
}
end
node
end
end
def parse_arg(s)
s.scan /\s*/
node = nil
%w(reference register register_list num_literal label_ref).each { |em|
if (node = send('parse_'+em, s))
break
end
}
raise Asm::ParseError.new('expected argument but none found', s) unless node
if (node2 = parse_arg_op(s))
node2.argument = node
node = node2
end
s.scan /\s*/
node
end
def parse_arg_op(s)
s.scan /\s*/
node = nil
%w(shift math).each do |em|
if (node = send('parse_'+em, s))
break
end
end
s.scan /\s*/
node
end
def parse_shift(s)
if (m = s.scan(/(lsl|lsr|asr|ror|rrx)\s+/i))
op = m[0].downcase
if (op == 'rrx' or arg = parse_arg(s))
ShiftNode.new(s) { |n|
n.type = m[0].downcase
n.value = arg
}
else
nil
end
end
end
def parse_math(s)
if (m = s.scan_str(/[\+\-]/))
if (arg1 = parse_arg(s))
MathNode.new(s) do |n|
n.right = arg1
n.op = m
end
else
raise Asm::ParseError.new('expected right side for arithmetic op', s)
end
end
end
REGISTER_REGEXP = Regexp.union(*%w(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12
r13 r14 r15 a1 a2 a3 a4 v1 v2 v3 v4 v5 v6
rfp sl fp ip sp lr pc
))
def parse_register(s)
if (m = s.scan_str(REGISTER_REGEXP))
RegisterArgNode.new(s) { |n|
n.name = m
}
end
end
def parse_register_list(s)
if (m = s.scan(/\{/))
node = RegisterListArgNode.new(s) do |n|
n.registers = []
end
loop do
s.scan /\s*/
reg = parse_register(s)
if (not reg)
return nil
end
s.scan /\s*,?/
node.registers << reg
if (s.scan(/\}/))
break
end
end
node
end
end
def parse_num_literal(s)
if (m = s.scan(/(=?)#(-?(?:0x)?[0-9A-Fa-f]+)/))
(m[0] == '=' ? NumEquivAddrArgNode : NumLiteralArgNode).new(s) { |n|
n.value = Integer(m[1])
}
end
end
def parse_label_ref(s)
if (m = s.scan(/(=?)(\/*\w+)/))
(m[0] == '=' ? LabelEquivAddrArgNode : LabelRefArgNode).new(s) { |n|
n.label = m[1]
}
end
end
def parse_reference(s)
if (m = s.scan(/\[/))
arg = parse_arg(s)
if (arg and s.scan(/\]/))
ReferenceArgNode.new(s) do |n|
n.argument = arg
end
end
end
end
end
end
if (__FILE__ == $0)
p Asm::Parser.parse ARGV[0]
end

View File

@ -1,65 +0,0 @@
module AS; end
if (not defined? RUBY_ENGINE or not RUBY_ENGINE == 'rbx')
class Regexp
def match_start(str, idx)
Regexp.compile('\A(?:'+source+')').match(str[idx..-1])
end
end
end
class Asm::Scanner
def initialize(str)
@string = str
@pos = 0
@line = 0
@column = 0
end
attr_accessor :string, :pos, :line, :column, :prev_line, :prev_column
def rest
string[pos..-1]
end
def advance_str(str)
self.prev_line = line
self.prev_column = column
self.pos += str.length
self.line += str.count("\n")
if (str.include?("\n"))
self.column = str.length - str.rindex("\n")
else
self.column += str.length
end
end
def scan(regexp)
if (match = regexp.match_start(rest, 0))
advance_str match.to_s
match.captures
else
nil
end
end
def scan_str(regexp)
if (match = regexp.match_start(rest, 0))
advance_str match.to_s
match.to_s
else
nil
end
end
def lookahead(regexp)
if (match = regexp.match_start(rest, 0))
true
else
false
end
end
def eos?
pos == string.length
end
end