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