Chris@13: loopDepth = 0; Chris@13: } Chris@13: Chris@13: /** Chris@13: * @throws FatalErrorException if the node is a break or continue in a non-loop or switch context Chris@13: * @throws FatalErrorException if the node is trying to break out of more nested structures than exist Chris@13: * @throws FatalErrorException if the node is a break or continue and has a non-numeric argument Chris@13: * @throws FatalErrorException if the node is a break or continue and has an argument less than 1 Chris@13: * Chris@13: * @param Node $node Chris@13: */ Chris@13: public function enterNode(Node $node) Chris@13: { Chris@13: switch (true) { Chris@13: case $node instanceof Do_: Chris@13: case $node instanceof For_: Chris@13: case $node instanceof Foreach_: Chris@13: case $node instanceof Switch_: Chris@13: case $node instanceof While_: Chris@13: $this->loopDepth++; Chris@13: break; Chris@13: Chris@13: case $node instanceof Break_: Chris@13: case $node instanceof Continue_: Chris@13: $operator = $node instanceof Break_ ? 'break' : 'continue'; Chris@13: Chris@13: if ($this->loopDepth === 0) { Chris@17: $msg = \sprintf("'%s' not in the 'loop' or 'switch' context", $operator); Chris@13: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@13: } Chris@13: Chris@13: if ($node->num instanceof LNumber || $node->num instanceof DNumber) { Chris@13: $num = $node->num->value; Chris@13: if ($node->num instanceof DNumber || $num < 1) { Chris@17: $msg = \sprintf("'%s' operator accepts only positive numbers", $operator); Chris@13: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@13: } Chris@13: Chris@13: if ($num > $this->loopDepth) { Chris@17: $msg = \sprintf("Cannot '%s' %d levels", $operator, $num); Chris@13: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@13: } Chris@13: } elseif ($node->num) { Chris@17: $msg = \sprintf("'%s' operator with non-constant operand is no longer supported", $operator); Chris@13: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@13: } Chris@13: break; Chris@13: } Chris@13: } Chris@13: Chris@13: /** Chris@13: * @param Node $node Chris@13: */ Chris@13: public function leaveNode(Node $node) Chris@13: { Chris@13: switch (true) { Chris@13: case $node instanceof Do_: Chris@13: case $node instanceof For_: Chris@13: case $node instanceof Foreach_: Chris@13: case $node instanceof Switch_: Chris@13: case $node instanceof While_: Chris@13: $this->loopDepth--; Chris@13: break; Chris@13: } Chris@13: } Chris@13: }