mirror of
https://github.com/samsonjs/compiler.git
synced 2026-03-25 08:45:52 +00:00
[NEW] do statement, d 10 a = a * a e
This commit is contained in:
parent
dd6d342dd4
commit
f7e63cbe21
2 changed files with 72 additions and 49 deletions
97
compiler.rb
97
compiler.rb
|
|
@ -26,13 +26,11 @@ class Compiler
|
|||
@vars = {} # symbol table
|
||||
@num_labels = 0 # used to generate unique labels
|
||||
@num_labels_with_suffix = Hash.new(0)
|
||||
@num_conditions = 0
|
||||
@break_stack = [] # for breaking out of loops
|
||||
|
||||
# reserved words (... constant?)
|
||||
#
|
||||
# if, else, end, while, until, repeat, break
|
||||
@keywords = %w[i l e w u r b]
|
||||
# if, else, end, while, until, repeat, for, do, break
|
||||
@keywords = %w[i l e w u r f d b]
|
||||
|
||||
# seed the lexer
|
||||
get_char
|
||||
|
|
@ -133,53 +131,48 @@ class Compiler
|
|||
x86_mov("dword [#{name}]", :eax)
|
||||
end
|
||||
|
||||
# Parse a statement.
|
||||
def statement
|
||||
case @look
|
||||
when 'i'
|
||||
if_else_stmt
|
||||
when 'w'
|
||||
while_stmt
|
||||
when 'u'
|
||||
until_stmt
|
||||
when 'r'
|
||||
repeat_stmt
|
||||
when 'f'
|
||||
for_stmt
|
||||
when 'b'
|
||||
break_stmt
|
||||
else
|
||||
assignment
|
||||
newline
|
||||
end
|
||||
end
|
||||
|
||||
# Parse a code block.
|
||||
def block(label=nil)
|
||||
@break_stack.push(label) if label
|
||||
until @look == 'l' || @look == 'e' || eof?
|
||||
statement
|
||||
case @look
|
||||
when 'i'
|
||||
if_else_stmt(label)
|
||||
when 'w'
|
||||
while_stmt
|
||||
when 'u'
|
||||
until_stmt
|
||||
when 'r'
|
||||
repeat_stmt
|
||||
when 'f'
|
||||
for_stmt
|
||||
when 'd'
|
||||
do_stmt
|
||||
when 'b'
|
||||
break_stmt(label)
|
||||
else
|
||||
assignment
|
||||
newline
|
||||
end
|
||||
skip_any_whitespace
|
||||
end
|
||||
@break_stack.pop if label
|
||||
end
|
||||
|
||||
# Parse an if-else statement.
|
||||
def if_else_stmt
|
||||
def if_else_stmt(label)
|
||||
match('i')
|
||||
condition
|
||||
skip_any_whitespace
|
||||
else_label = unique_label(:end_or_else)
|
||||
end_label = else_label # only generated if else clause present
|
||||
x86_jz(else_label)
|
||||
block
|
||||
block(label)
|
||||
if @look == 'l'
|
||||
match('l')
|
||||
skip_any_whitespace
|
||||
end_label = unique_label(:endif) # now we need the 2nd label
|
||||
x86_jmp(end_label)
|
||||
emit_label(else_label)
|
||||
block
|
||||
block(label)
|
||||
end
|
||||
match('e')
|
||||
emit_label(end_label)
|
||||
|
|
@ -257,19 +250,41 @@ class Compiler
|
|||
x86_add(:esp, 4) # clean up the stack
|
||||
end
|
||||
|
||||
def break_stmt
|
||||
# d 5
|
||||
# ...
|
||||
# e
|
||||
def do_stmt
|
||||
match('d')
|
||||
start_label = unique_label(:do)
|
||||
end_label = unique_label(:enddo)
|
||||
expression
|
||||
skip_any_whitespace
|
||||
x86_mov(:ecx, :eax)
|
||||
x86_push(:ecx)
|
||||
counter = '[esp]'
|
||||
emit_label(start_label)
|
||||
x86_mov(counter, :ecx)
|
||||
block(end_label)
|
||||
x86_mov(:ecx, counter)
|
||||
match('e')
|
||||
x86_loop(start_label)
|
||||
x86_sub(:esp, 4)
|
||||
emit_label(end_label)
|
||||
x86_add(:esp, 4)
|
||||
end
|
||||
|
||||
def break_stmt(label)
|
||||
match('b')
|
||||
if @break_stack.empty?
|
||||
if label
|
||||
x86_jmp(label)
|
||||
else
|
||||
expected(:'break to be somewhere useful',
|
||||
:got => :'a break without a loop')
|
||||
:got => :'a break outside a loop')
|
||||
end
|
||||
x86_jmp(@break_stack.last)
|
||||
end
|
||||
|
||||
# Evaluates any expression for now. There are no boolean operators.
|
||||
def condition
|
||||
# @num_conditions += 1
|
||||
# emit("<condition ##{@num_conditions}>")
|
||||
expression
|
||||
x86_cmp(:eax, 0) # 0 is false, anything else is true
|
||||
skip_whitespace
|
||||
|
|
@ -415,7 +430,7 @@ class Compiler
|
|||
end
|
||||
|
||||
|
||||
# Get an identifier.
|
||||
# Parse a name (identifier).
|
||||
def get_name
|
||||
expected(:identifier) unless alpha?(@look)
|
||||
name = many(method(:alnum?))
|
||||
|
|
@ -425,7 +440,7 @@ class Compiler
|
|||
name
|
||||
end
|
||||
|
||||
# Get a number.
|
||||
# Parse a number.
|
||||
def get_num
|
||||
expected(:integer) unless digit?(@look)
|
||||
many(method(:digit?))
|
||||
|
|
@ -539,4 +554,8 @@ class Compiler
|
|||
def x86_cmp(a, b)
|
||||
emit("cmp #{a}, #{b}")
|
||||
end
|
||||
|
||||
def x86_loop(label)
|
||||
emit("loop #{label}")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
24
test.code
24
test.code
|
|
@ -3,28 +3,28 @@ aa=10
|
|||
somethinglong=65536
|
||||
x=5*(3-5)
|
||||
c=a-1
|
||||
d=-1
|
||||
g=x*2+2
|
||||
h=g-27/9
|
||||
j=h-8/2
|
||||
k=j-4*(5+5+5)
|
||||
m=k+85
|
||||
g=-1
|
||||
h=x*2+2
|
||||
j=h-27/9
|
||||
k=j-8/2
|
||||
m=k-4*(5+5+5)
|
||||
n=m+85
|
||||
|
||||
i 1
|
||||
d=3
|
||||
x=3
|
||||
i 1 c=4
|
||||
e
|
||||
e
|
||||
i1d=3
|
||||
i1x=3
|
||||
i1c=4
|
||||
ee
|
||||
|
||||
i 1
|
||||
d=3
|
||||
x=3
|
||||
i 1 c=4
|
||||
e
|
||||
l
|
||||
d=2
|
||||
x=2
|
||||
e
|
||||
|
||||
w 0
|
||||
|
|
@ -50,4 +50,8 @@ f x = 1 >> 5
|
|||
s = s + x
|
||||
e
|
||||
|
||||
d 10
|
||||
a = a * a
|
||||
e
|
||||
|
||||
xitcode=a-a
|
||||
|
|
|
|||
Loading…
Reference in a new issue