summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-27 21:52:48 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-27 21:52:48 +0000
commitfb14c03667552fe558e472056bb0b834a3652d8f (patch)
tree951c465fa67be041d18f783adb5862e4cc138b3e
parent0ac605d5a09ba80615b2e0c151f31741168e6d2d (diff)
downloadpp2cc-fb14c03667552fe558e472056bb0b834a3652d8f.tar.gz
Support for break/continue
-rw-r--r--README6
-rwxr-xr-xpp2cc.py45
2 files changed, 47 insertions, 4 deletions
diff --git a/README b/README
index f695e1a..fe2a379 100644
--- a/README
+++ b/README
@@ -85,9 +85,9 @@ A9.3 Compound statement - supported
A9.4 Selection statements - if and if/else are supported, switch is not
A9.5 Iteration statements - while, do/while and for are supported. A missing
second expression in the for is equivalent to a non-zero constant
-A9.6 Jump statements - goto is unsupported. continue, break are not supported
- yet. return is supported with and without value. The function
- result is undefined for the second case
+A9.6 Jump statements - goto is unsupported. continue, break are supported.
+ return is supported with and without value. The function result is
+ undefined for the second case
A10 External Declarations
A10.1 Function Definitions - unsupported: extern static, parameters. Old style
diff --git a/pp2cc.py b/pp2cc.py
index bc782c3..57c53f3 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -159,6 +159,8 @@ class LinkedNode(object):
self.node = node
self.parent = parent
self.function = None
+ self.break_label = None
+ self.continue_label = None
self.level = 0
# inherit level from parent
if parent:
@@ -181,6 +183,23 @@ class LinkedNode(object):
if hasattr(self.node, "coord"):
return self.node.coord
return "Unknown"
+ def setLoop(self, break_label, continue_label):
+ """Marks this node as a loop with the labels to continue after a jump
+
+ Keywords list:
+ break_label -- The label to continue when using the break keyword
+ continue_label -- The label to continue when using the continue keyword
+ """
+ self.break_label = break_label
+ self.continue_label = continue_label
+ def getLoopNode(self):
+ # continue_label is implied with break_label
+ if self.break_label is not None:
+ return self
+ if self.parent:
+ assert isinstance(self.parent, LinkedNode), "parent is not a LinkedNode!"
+ return self.parent.getLoopNode()
+ return None
class Function(object):
def __init__(self, node):
@@ -739,18 +758,29 @@ class Parse(object):
def parseDoWhile(self, linked_node):
node = linked_node.node
lbl_do = self.uniqLbl("do")
+ # used for supporting continue/break
+ lbl_cond = self.uniqLbl("doCond")
+ lbl_end = self.uniqLbl("doEnd")
+ linked_node.setLoop(lbl_end, lbl_doCond)
+
# provides a way to redo the loop
lines = [self.asm.noop(lbl_do)]
# do { ... }, expect do{/*empty*/} as well
lines += self.parseStatement(node.stmt, linked_node)
# while (...)
+ # used for supporting continue
+ lines.append(self.asm.noop(lbl_cond))
lines += self.parseStatement(node.cond, linked_node)
lines.append(self.asm.branch_op("BNE", lbl_do))
+ # used for supporting break
+ lines.append(self.asm.noop(lbl_end))
return lines
def parseWhile(self, linked_node):
node = linked_node.node
lbl_while = self.uniqLbl("while")
lbl_while_end = self.uniqLbl("whileEnd")
+ # used for supporting break/continue
+ linked_node.setLoop(lbl_while_end, lbl_while)
# while (
lines = [self.asm.noop(lbl_while)]
# ..
@@ -774,6 +804,8 @@ class Parse(object):
lines = []
lbl_for = self.uniqLbl("for")
lbl_for_end = self.uniqLbl("forEnd")
+ # used for supporting break/continue
+ linked_node.setLoop(lbl_for_end, lbl_for)
if node.init: # init;
lines += self.parseStatement(node.init, linked_node)
@@ -838,6 +870,16 @@ class Parse(object):
else:
lines += init_val
return lines
+ def parseBreak(self, linked_node):
+ loop_node = linked_node.getLoopNode()
+ if not loop_node:
+ raise RuntimeError("break not in a loop")
+ return [self.asm.branch_op("BRA", loop_node.break_label)]
+ def parseContinue(self, linked_node):
+ loop_node = linked_node.getLoopNode()
+ if not loop_node:
+ raise RuntimeError("continue not in a loop")
+ return [self.asm.branch_op("BRA", loop_node.continue_label)]
def parseStatement(self, node, parent_linked_node, level_increment=False):
linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment)
self.asm.level = linked_node.level
@@ -850,7 +892,8 @@ class Parse(object):
for entry in ("Compound", "BinaryOp", "If", "Constant", "ID",
"Return", "FuncCall", "UnaryOp", "Cast",
"TernaryOp", "DoWhile", "While", "For", "ExprList",
- "Assignment", "Decl", "FuncDef"):
+ "Assignment", "Decl", "FuncDef", "Break",
+ "Continue"):
if isinstance(node, getattr(c_ast, entry)):
lines += getattr(self, "parse" + entry)(linked_node)
break