cleaning out the cruft

This commit is contained in:
Sami Samhuri 2010-01-19 23:32:30 -08:00
parent 0c21d1abc6
commit 7aa6fa7d15
4 changed files with 0 additions and 370 deletions

119
cradle.rb
View file

@ -1,119 +0,0 @@
# A compiler skeleton, or cradle, as described by Jack Crenshaw in his
# famous book "Let's Build a Compiler". At least in the beginning,
# this code will closely reflect the Pascal code written by Jack.
# Over time it may become more idiomatic, however this is an academic
# exercise.
class ParseError < StandardError; end
class Compiler
def initialize(input=STDIN)
@look = '' # next lookahead char
@input = input # stream to read from
# seed the lexer
get_char
end
# Read the next character from the input stream
def get_char
@look = @input.getc
@look = @look.chr if @look
end
# Report error and halt
def abort(msg)
raise ParseError, msg
end
# Report what was expected
def expected(what)
if eof?
raise ParseError, "Premature end of file, expected: #{what}."
else
raise ParseError, "Expected: #{what}, got: #{@look}."
end
end
# Match a specific input character
def match(char)
if @look == char
get_char
else
expected("'#{char}'")
end
end
# Recognize an alphabetical character
def is_alpha(char)
('A'..'Z') === char.upcase
end
# Recognize a decimal digit
def is_digit(char)
('0'..'9') === char
end
# Get an identifier
def get_name
expected('identifier') unless is_alpha(@look)
c = @look
get_char
return c
end
# Get a number
def get_num
expected('integer') unless is_digit(@look)
c = @look
get_char
return c
end
# Print a tab followed by a string and a newline
def emit(s)
puts "\t#{s}"
end
# Parse and translate a single mathematical term. Result is in eax.
def term
emit("mov eax, #{get_num}")
end
# Parse an addition operator and the 2nd term. The 1st term is
# expected in ebx, and is added to the 2nd term leaving the result
# in eax.
def add
match('+')
term # result in eax
emit("add eax, ebx")
end
# Parse a subtraction operator and the 2nd term (b). The 1st term
# (a) is expected in ebx, and the b is subtracted from a
# leaving the result in eax.
def subtract
match('-')
term # result in eax (b)
emit("sub eax, ebx") # subtract a from b (this is backwards)
emit("neg eax") # fix things up. -(b-a) == a-b
end
# Parse and translate a mathematical expression of terms. Result is
# in eax.
def expression
term # result is in eax
emit("mov ebx, eax") # move 1st term to ebx (expected by
# add & subtract)
case @look
when '+': add
when '-': subtract
else
expected('Addition or subtraction operator (+ or -)')
end
end
def eof?
@input.eof? && @look.nil?
end
end

View file

@ -1,227 +0,0 @@
# An interpreter as described by Jack Crenshaw in his famous book
# "Let's Build a Compiler". At least in the beginning, this code will
# closely reflect the Pascal code written by Jack. Over time it may
# become more idiomatic, however this is an academic exercise.
#
# sjs
# may 2009
class ParseError < StandardError; end
class Interpreter
def initialize(input=STDIN)
@look = '' # next lookahead char
@input = input # stream to read from
@vars = Hash.new(0)
# seed the lexer
get_char
end
def run
statement until eof? || @look == '.'
end
# Read the next character from the input stream
def get_char
@look = if @input.eof?
nil
else
@input.readbyte.chr
end
end
# Report error and halt
def abort(msg)
raise ParseError, msg
end
# Report what was expected
def expected(what)
msg = if eof?
"Premature end of file, expected: #{what}."
else
"Expected: #{what}, got: #{@look}."
end
abort(msg)
end
# Define a variable.
def define(name, value=nil)
abort("already defined '#{name}'") if @vars.has_key?(name)
set(name, value)
end
# Set the value of a variable.
def set(name, value)
@vars[name] = value
end
# Retrieve the value of a variable.
def get(name)
abort("undefined variable '#{name}'") unless @vars.has_key?(name)
@vars[name]
end
# Recognize an alphabetical character.
def alpha?(char)
('A'..'Z') === char.upcase
end
# Recognize a decimal digit.
def digit?(char)
('0'..'9') === char
end
# Recognize an alphanumeric character.
def alnum?(char)
alpha?(char) || digit?(char)
end
def whitespace?(char)
char == ' ' || char == '\t'
end
# Match a specific input character.
def match(char)
expected("'#{char}'") unless @look == char
get_char
skip_whitespace
end
# Parse zero or more consecutive characters for which the test is
# true.
def many(test)
token = ''
while test.call(@look)
token << @look
get_char
end
skip_whitespace
token
end
# Get an identifier.
def get_name
expected('identifier') unless alpha?(@look)
many(method(:alpha?))
end
# Get a number.
def get_num
expected('integer') unless digit?(@look)
many(method(:digit?)).to_i
end
# Skip all leading whitespace.
def skip_whitespace
get_char while whitespace?(@look)
end
# Parse and evaluate a factor.
def factor
if @look == '('
match('(')
value = expression
match(')')
elsif alpha?(@look)
value = get(get_name)
else
value = get_num
end
value
end
# Parse and evaluate a term.
def term
value = factor
while mulop?
case @look
when '*'
match('*')
value *= factor
when '/'
match('/')
value /= factor
end
end
value
end
# Parse and evaluate a mathematical expression.
def expression
# Fake unary plus and minus by prepending a 0 to them.
value = if addop? then 0 else term end
while addop?
case @look
when '+'
match('+')
value += term
when '-'
match('-')
value -= term
end
end
value
end
# Parse one or more newlines.
def newline
if @look == "\n" || @look == "\r"
get_char while @look == "\n" || @look == "\r"
else
expected('newline')
end
end
# Parse and evaluate an assignment statement.
def assignment
name = get_name
match('=')
set(name, expression)
end
# Parse and evaluate any kind of statement.
def statement
value = case @look
when '?': input
when '!': output
else
assignment
end
newline
value
end
# Read and store a number from standard input.
def input
match('?')
set(get_name, gets.to_i)
end
# Print a value to standard output.
def output
match('!')
puts(get(get_name))
end
private
def eof?
@input.eof? && @look.nil?
end
def addop?
@look == '+' || @look == '-'
end
def mulop?
@look == '*' || @look == '/'
end
end

View file

@ -1,11 +0,0 @@
BITS 32
GLOBAL _main
SECTION .data
{data}
SECTION .bss
{bss}
SECTION .text
_main:
{code}
;; The result in eax is the exit code, just return.
ret

View file

@ -1,13 +0,0 @@
BITS 32
GLOBAL _start
SECTION .data
{data}
SECTION .bss
{bss}
SECTION .text
_start:
{code}
;; The result in eax is the exit code, move it to ebx.
mov ebx, eax
mov eax, 1 ; _exit syscall
int 0x80 ; call Linux