Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions compiler/codegen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,24 @@ def generate(node)
]

when IfNode
body_code =
if node.body.is_a?(Array)
node.body.map { |n| generate (n) }.join("\n")
else
generate(node.body)
compiled = ""

first = node.condition
compiled << "if #{generate(first)} then\n"
compiled << node.body.map { |n| generate (n) }.join("\n")

node.elif_blocks.each do |c|
compiled << "\nelseif #{generate(c.condition)} then\n"
compiled << c.body.map { |n| generate (n) }.join("\n")
end

"if %s then \n %s \nend" % [
generate(node.statement),
body_code
]
if node.else_body
compiled << "\nelse\n"
compiled << node.else_body.map { |n| generate (n) }.join("\n")
end

compiled << "\nend"
compiled

when WhileNode
body_code =
Expand All @@ -44,6 +51,24 @@ def generate(node)
generate(node.statement),
body_code
]

when SwitchNode
compiled = ""
node.cases.each_with_index do |c, i|
if i == 0
compiled << "if #{generate(c.match)} == #{generate(node.value)} then\n"
else
compiled << "elseif #{generate(c.match)} == #{generate(node.value)} then\n"
end

body_code = c.body.map { |b| generate(b) }.join("\n")
compiled << " #{body_code}\n"

end
compiled << "end"
compiled


when CallNode
"%s(%s)" % [
node.name,
Expand Down
102 changes: 90 additions & 12 deletions compiler/parser.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
DefNode = Struct.new(:name, :args, :body)
IfNode = Struct.new(:statement, :body)

IfNode = Struct.new(:condition, :body, :elif_blocks, :else_body)
ElifBlock = Struct.new(:condition, :body)

WhileNode = Struct.new(:statement, :body)
IntegerNode = Struct.new(:value)
StringNode = Struct.new(:value)
Expand All @@ -11,6 +14,8 @@
PrintNode = Struct.new(:args)
ReturnNode = Struct.new(:statement)
AndOrListNode = Struct.new(:items)
SwitchNode = Struct.new(:value, :cases)
CaseNode = Struct.new(:match, :body)

LoveCallNode = Struct.new(:namespace, :name, :args)

Expand Down Expand Up @@ -86,26 +91,71 @@ def parse_return
end

def parse_if

consume(:if)
condition = parse_expr
skip_newlines
if_body = []
while !peek(:elif) && !peek(:else) && !peek(:end)
if_body << parse_statement
skip_newlines
end


elif_blocks = []
while peek(:elif)
consume(:elif)
elif_condition = parse_expr
skip_newlines

elif_body = []
while !peek(:elif) && !peek(:else) && !peek(:end)
elif_body << parse_statement
skip_newlines
end

elif_blocks << ElifBlock.new(elif_condition, elif_body)

if peek(:oparen)
consume(:oparen)
statement = parse_expr
consume(:cparen)
else
statement = parse_expr
end
skip_newlines
body = []

until peek(:end)
body << parse_statement
else_body = nil
if peek(:else)
consume(:else)
skip_newlines

else_body = []
while !peek(:end)
else_body << parse_statement
skip_newlines
end
end

consume(:end)
IfNode.new(statement, body)

IfNode.new(condition, if_body, elif_blocks, else_body)


end

# consume(:if)

# if peek(:oparen)
# consume(:oparen)
# statement = parse_expr
# consume(:cparen)
# else
# statement = parse_expr
# end
# skip_newlines
# body = []

# until peek(:elif) peek(:end)
# body << parse_statement
# skip_newlines
# end
# consume(:end)
# IfNode.new(statement, body)

def parse_while
consume(:while)

Expand All @@ -129,6 +179,32 @@ def parse_while
WhileNode.new(statement, body)
end

def parse_switch
consume(:switch)
value = parse_expr
skip_newlines

cases = []

while peek(:to)
consume(:to)
match = parse_expr
skip_newlines

body = []

until peek(:to) || peek(:end)
body << parse_statement
skip_newlines
end

cases << CaseNode.new(match, body)
end

consume(:end)
SwitchNode.new(value, cases)
end


def parse_print
consume(:print)
Expand All @@ -148,6 +224,8 @@ def parse_statement
parse_if
elsif peek(:while)
parse_while
elsif peek(:switch)
parse_switch
elsif peek(:print)
parse_print
elsif peek(:local)
Expand Down
6 changes: 5 additions & 1 deletion compiler/tokenizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ class Tokenizer
[:def, /\bcall\b/],
[:end, /\bdone\b/],
[:if, /\bif\b/],
[:elif, /\belif\b/],
[:else, /\belse\b/],
[:while, /\bwhen\b/],
[:print, /\bprint\b/],
[:return, /\breturn\b/],
[:or, /\bor\b/],
[:and, /\band\b/],
[:switch, /\bswitch\b/],
[:to, /\bto\b/],

#love
[:lgraphics, /-G:/],
Expand All @@ -38,7 +42,7 @@ class Tokenizer
[:greater, />/],
[:lesser, /</],
[:grequal, />=/],
[:lequal, /<=/]
[:lequal, /<=/],
[:equal, /=/],
[:divide, /\//],
[:multiply, /\*/],
Expand Down
10 changes: 10 additions & 0 deletions examples/main.lat
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ nat multiplier = 2

if (-K:isDown("space"))
incrementCoin(3)
elif (-K:isDown("w"))
incrementCoin(3)
done


Expand All @@ -16,5 +18,13 @@ when (true)

done

switch score
to 10
print("perfect")
to 5
print("ok")

done


print(coins)
11 changes: 9 additions & 2 deletions test.lua
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
local coins = 250
local incrementVal = 20
local multiplier = 2
if love.keyboard.isDown("space") then
incrementCoin(3)
if love.keyboard.isDown("space") then
incrementCoin(3)
elseif love.keyboard.isDown("w") then
incrementCoin(3)
end
function incrementCoin(externalMultiplier)
coins = (coins + ((incrementVal * multiplier) * externalMultiplier))
return coins
end
while true do

end
if 10 == score then
print("perfect")
elseif 5 == score then
print("ok")
end
print(coins)
Loading