|
@@ -34,6 +34,8 @@ asm: "asm" "(" STRING+ ")"
|
|
|
?op: block
|
|
|
| label
|
|
|
| goto ";"
|
|
|
+ | break ";"
|
|
|
+ | continue ";"
|
|
|
| vardec ";"
|
|
|
| arrdec ";"
|
|
|
| varinit ";"
|
|
@@ -50,14 +52,16 @@ asm: "asm" "(" STRING+ ")"
|
|
|
| return ";"
|
|
|
label: NAME ":"
|
|
|
goto: "goto" NAME
|
|
|
+break: "break"
|
|
|
+continue: "continue"
|
|
|
if: "if" "(" expr ")" op ("else" op)?
|
|
|
while: "while" "(" expr ")" op
|
|
|
for: "for" "(" vardec ";" expr ";" (inc|dec|vardec|funcall) ")" op
|
|
|
return: "return" expr
|
|
|
-inc: NAME "++"
|
|
|
-dec: NAME "--"
|
|
|
-rinc: "++" NAME
|
|
|
-rdec: "--" NAME
|
|
|
+inc: NAME ("[" expr "]")? "++"
|
|
|
+dec: NAME ("[" expr "]")? "--"
|
|
|
+rinc: "++" NAME ("[" expr "]")?
|
|
|
+rdec: "--" NAME ("[" expr "]")?
|
|
|
|
|
|
funcall: NAME "(" args ")"
|
|
|
args:
|
|
@@ -245,6 +249,8 @@ class WMC:
|
|
|
|
|
|
self.parser = lark.Lark(GRAMMAR)
|
|
|
|
|
|
+ self.loops = []
|
|
|
+
|
|
|
def record_usage(self, name):
|
|
|
if name in self.used_symbols:
|
|
|
self.used_symbols[name].add(self.where)
|
|
@@ -707,6 +713,9 @@ class WMC:
|
|
|
)
|
|
|
)
|
|
|
elif node.data == "inc":
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -720,6 +729,9 @@ class WMC:
|
|
|
name
|
|
|
)
|
|
|
elif node.data == "dec":
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -732,6 +744,9 @@ class WMC:
|
|
|
name
|
|
|
)
|
|
|
elif node.data == "rinc":
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -745,6 +760,9 @@ class WMC:
|
|
|
name
|
|
|
)
|
|
|
elif node.data == "rdec":
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -921,6 +939,22 @@ class WMC:
|
|
|
"jmp {}",
|
|
|
self.scope.get_label(node.children[0].value)
|
|
|
)
|
|
|
+ elif node.data == "break":
|
|
|
+ if len(self.loops) < 1:
|
|
|
+ raise Exception("'break` outside of a loop.")
|
|
|
+
|
|
|
+ buffer.emit(
|
|
|
+ "jmp {}",
|
|
|
+ self.loops[-1][1]
|
|
|
+ )
|
|
|
+ elif node.data == "continue":
|
|
|
+ if len(self.loops) < 1:
|
|
|
+ raise Exception("'continue` outside of a loop.")
|
|
|
+
|
|
|
+ buffer.emit(
|
|
|
+ "jmp {}",
|
|
|
+ self.loops[-1][0]
|
|
|
+ )
|
|
|
elif node.data == "varinit":
|
|
|
name = node.children[0].value
|
|
|
|
|
@@ -945,6 +979,9 @@ class WMC:
|
|
|
self.compile_arrdec(node)
|
|
|
)
|
|
|
elif node.data in ("inc", "rinc"):
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -954,6 +991,9 @@ class WMC:
|
|
|
name
|
|
|
)
|
|
|
elif node.data == ("dec", "rdec"):
|
|
|
+ if len(node.children) == 2:
|
|
|
+ raise Exception(f"Not implemented: {node}")
|
|
|
+
|
|
|
name = self.scope[node.children[0].value]
|
|
|
|
|
|
self.record_usage(name)
|
|
@@ -1024,6 +1064,8 @@ class WMC:
|
|
|
loop_label = self.make_label()
|
|
|
exit_label = self.make_label()
|
|
|
|
|
|
+ self.loops.append((loop_label, exit_label))
|
|
|
+
|
|
|
buffer.emit(
|
|
|
"{}:",
|
|
|
loop_label
|
|
@@ -1046,6 +1088,8 @@ class WMC:
|
|
|
)
|
|
|
)
|
|
|
|
|
|
+ self.loops.pop()
|
|
|
+
|
|
|
buffer.emit(
|
|
|
"jmp {}",
|
|
|
loop_label
|
|
@@ -1058,6 +1102,8 @@ class WMC:
|
|
|
loop_label = self.make_label()
|
|
|
exit_label = self.make_label()
|
|
|
|
|
|
+ self.loops.append((loop_label, exit_label))
|
|
|
+
|
|
|
self.scope.new()
|
|
|
|
|
|
buffer.emit(
|
|
@@ -1096,6 +1142,8 @@ class WMC:
|
|
|
|
|
|
self.scope.leave()
|
|
|
|
|
|
+ self.loops.pop()
|
|
|
+
|
|
|
buffer.emit(
|
|
|
"jmp {}",
|
|
|
loop_label
|