diff --git a/src/StrictObject.php b/src/StrictObject.php index 0d531dc4..9090e75a 100644 --- a/src/StrictObject.php +++ b/src/StrictObject.php @@ -2,7 +2,7 @@ namespace Smuuf\Primi; -class StrictObject { +abstract class StrictObject { /** * Used when trying to access undeclared or inaccessible property. diff --git a/src/exceptions/InternalArgumentCountException.php b/src/exceptions/InternalArgumentCountException.php index b17f3393..b55bee86 100644 --- a/src/exceptions/InternalArgumentCountException.php +++ b/src/exceptions/InternalArgumentCountException.php @@ -16,12 +16,12 @@ public function __construct(int $passed = null, int $expected = null) { } - public function getPassedCount() { - $this->passedCount; + public function getPassedCount(): int { + return $this->passedCount; } - public function getExpectedCount() { - $this->expectedCount; + public function getExpectedCount(): int { + return $this->expectedCount; } } diff --git a/src/exceptions/InternalBinaryOperationxception.php b/src/exceptions/InternalBinaryOperationxception.php index fd794666..ee33a969 100644 --- a/src/exceptions/InternalBinaryOperationxception.php +++ b/src/exceptions/InternalBinaryOperationxception.php @@ -4,7 +4,7 @@ use \Smuuf\Primi\Structures\Value; -class InternalBinaryOperationxception extends InternalException { +class InternalBinaryOperationException extends InternalException { protected $op; protected $left; diff --git a/src/exceptions/InternalUndefinedTruthnessException.php b/src/exceptions/InternalUndefinedTruthnessException.php new file mode 100644 index 00000000..0db9c6b0 --- /dev/null +++ b/src/exceptions/InternalUndefinedTruthnessException.php @@ -0,0 +1,7 @@ +value); + shuffle($copy->value); - return $arr; + return $copy; } diff --git a/src/extensions/psl/CastingExtension.php b/src/extensions/psl/CastingExtension.php index dc7e25c4..1cadb728 100644 --- a/src/extensions/psl/CastingExtension.php +++ b/src/extensions/psl/CastingExtension.php @@ -50,12 +50,7 @@ public static function to_bool(Value $value): BoolValue { BoolValue::class ); - // Only empty string is considered falsey ("" -> false, "0" -> true). - if ($value instanceof StringValue) { - return new BoolValue($value->value !== ""); - } - - return new BoolValue((bool) $value->value); + return new BoolValue(Common::isTruthy($value)); } diff --git a/src/handlers/Addition.php b/src/handlers/Addition.php index 56c45d66..cf4112f5 100644 --- a/src/handlers/Addition.php +++ b/src/handlers/Addition.php @@ -2,13 +2,13 @@ namespace Smuuf\Primi\Handlers; -use \Smuuf\Primi\InternalBinaryOperationxception; +use \Smuuf\Primi\InternalBinaryOperationException; use \Smuuf\Primi\ErrorException; use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Context; use \Smuuf\Primi\Helpers\Common; -use \Smuuf\Primi\Helpers\BinaryOpHandler; +use \Smuuf\Primi\Helpers\BinaryLTR; /** * Node fields: @@ -21,9 +21,9 @@ public static function handle(array $node, Context $context) { try { - return BinaryOpHandler::handle($node, $context); + return BinaryLTR::handle($node, $context); - } catch (InternalBinaryOperationxception $e) { + } catch (InternalBinaryOperationException $e) { throw new ErrorException(sprintf( "Cannot use operator '%s' with '%s' and '%s'", @@ -40,7 +40,7 @@ public static function reduce(array $node) { // No need to represent this kind of node as Addition when there's only one operand. // Take the only operand here and subtitute the Addition node with it. - if (isset($node['operands']['name'])) { + if (!isset($node['ops'])) { return $node['operands']; } diff --git a/src/handlers/ChainedFunction.php b/src/handlers/ChainedFunction.php index 838f84f6..a89be249 100644 --- a/src/handlers/ChainedFunction.php +++ b/src/handlers/ChainedFunction.php @@ -17,7 +17,7 @@ public static function chain( ) { // 1) We'll extract the function name directly from the "fn" child node. - $name = $node['fn']['text']; + $name = $node['fn']['core']['text']; // 2) We'll try to find type-matching function first. // That is: A function which name is prepended by the subject's type diff --git a/src/handlers/Comparison.php b/src/handlers/Comparison.php index 3944c5f7..5a57c26f 100644 --- a/src/handlers/Comparison.php +++ b/src/handlers/Comparison.php @@ -3,6 +3,8 @@ namespace Smuuf\Primi\Handlers; use \Smuuf\Primi\Structures\Value; +use \Smuuf\Primi\Helpers\ComparisonLTR; +use \Smuuf\Primi\InternalBinaryOperationException; use \Smuuf\Primi\ISupportsComparison; use \Smuuf\Primi\ErrorException; use \Smuuf\Primi\HandlerFactory; @@ -13,37 +15,34 @@ * left: A "+" or "-" sign signalling the 'side' of the first operand. * right: List of operand nodes. */ -class Comparison extends \Smuuf\Primi\StrictObject implements IHandler { +class Comparison extends \Smuuf\Primi\StrictObject implements IHandler, IReducer { public static function handle(array $node, Context $context) { - // Execute the left-hand node and get its return value. - $leftHandler = HandlerFactory::get($node['left']['name']); - $leftReturn = $leftHandler::handle($node['left'], $context); - - $rightHandler = HandlerFactory::get($node['right']['name']); - $rightReturn = $rightHandler::handle($node['right'], $context); - - $op = $node['op']['text']; - try { - if ($leftReturn instanceof ISupportsComparison && $rightReturn instanceof Value) { - return $leftReturn->doComparison($op, $rightReturn); - } else { - throw new \TypeError; - } + return ComparisonLTR::handle($node, $context); - } catch (\TypeError $e) { + } catch (InternalBinaryOperationException $e) { throw new ErrorException(sprintf( - "Cannot compare '%s' and '%s'", - $leftReturn::TYPE, - $rightReturn::TYPE + "Cannot compare '%s' with '%s'", + ($e->getLeft())::TYPE, + ($e->getRight())::TYPE ), $node); } } + public static function reduce(array $node) { + + // If there is no operator, that means there's only one operand. + // In that case, return only the operand node inside. + if (!isset($node['ops'])) { + return $node['operands']; + } + + } + } diff --git a/src/handlers/IfStatement.php b/src/handlers/IfStatement.php index f5ab44a0..892fe3b4 100644 --- a/src/handlers/IfStatement.php +++ b/src/handlers/IfStatement.php @@ -2,6 +2,7 @@ namespace Smuuf\Primi\Handlers; +use \Smuuf\Primi\Helpers\Common; use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Context; @@ -20,7 +21,7 @@ public static function handle(array $node, Context $context) { // If the result of the left hand equals to truthy value, // execute the code branch stored in the right-hand node. - if ($return->getInternalValue()) { + if (Common::isTruthy($return)) { $rightHandler = HandlerFactory::get($node['right']['name']); $rightHandler::handle($node['right'], $context); } diff --git a/src/handlers/LogicalAnd.php b/src/handlers/LogicalAnd.php new file mode 100644 index 00000000..63cca7af --- /dev/null +++ b/src/handlers/LogicalAnd.php @@ -0,0 +1,30 @@ +getMessage(), $node); + } + + } + + public static function reduce(array $node) { + + if (!isset($node['ops'])) { + return $node['operands']; + } + + } + +} diff --git a/src/handlers/LogicalOr.php b/src/handlers/LogicalOr.php new file mode 100644 index 00000000..f59f60c1 --- /dev/null +++ b/src/handlers/LogicalOr.php @@ -0,0 +1,30 @@ +getMessage(), $node); + } + + } + + public static function reduce(array $node) { + + if (!isset($node['ops'])) { + return $node['operands']; + } + + } + +} diff --git a/src/handlers/Multiplication.php b/src/handlers/Multiplication.php index f8646070..36640ca6 100644 --- a/src/handlers/Multiplication.php +++ b/src/handlers/Multiplication.php @@ -2,13 +2,13 @@ namespace Smuuf\Primi\Handlers; -use \Smuuf\Primi\InternalBinaryOperationxception; +use \Smuuf\Primi\InternalBinaryOperationException; use \Smuuf\Primi\ErrorException; use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Context; use \Smuuf\Primi\Helpers\Common; -use \Smuuf\Primi\Helpers\BinaryOpHandler; +use \Smuuf\Primi\Helpers\BinaryLTR; /** * Node fields: @@ -21,9 +21,9 @@ public static function handle(array $node, Context $context) { try { - return BinaryOpHandler::handle($node, $context); + return BinaryLTR::handle($node, $context); - } catch (InternalBinaryOperationxception $e) { + } catch (InternalBinaryOperationException $e) { throw new ErrorException(sprintf( "Cannot use operator '%s' with '%s' and '%s'", @@ -40,7 +40,7 @@ public static function reduce(array $node) { // No need to represent this kind of node as Multiplication when there's only one operand. // Take the only operand here and subtitute the Multiplication node with it. - if (isset($node['operands']['name'])) { + if (!isset($node['ops'])) { return $node['operands']; } diff --git a/src/handlers/Negation.php b/src/handlers/Negation.php index b18a5dc3..d88a390a 100644 --- a/src/handlers/Negation.php +++ b/src/handlers/Negation.php @@ -2,6 +2,7 @@ namespace Smuuf\Primi\Handlers; +use \Smuuf\Primi\Helpers\Common; use \Smuuf\Primi\Structures\BoolValue; use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Context; @@ -10,35 +11,30 @@ class Negation extends \Smuuf\Primi\StrictObject implements IHandler, IReducer { public static function handle(array $node, Context $context) { - $negation = isset($node['not']); - $handler = HandlerFactory::get($node['core']['name']); $value = $handler::handle($node['core'], $context); - // Should we even handle negation? - if ($negation) { - - // If so, let's determine truthness using PHP's own rules (at least - // for now). - $truthness = (bool) $value->getInternalValue(); - $value = new BoolValue(!$truthness); + // The final truthness is (at least for now) based on PHP's own rules. + $truthness = Common::isTruthy($value); - } + // Should we even handle negation? If there's an even number of negation + // operators, the result would always have the same truthness as its + // input. + Common::ensureIndexed($node['nots']); + $isNegation = count($node['nots'] ?? []) % 2; - return $value; + return new BoolValue($isNegation ? !$truthness : $truthness); } public static function reduce(array $node) { // If this truly has a negation, do not reduce this node. - if (isset($node['not'])) { - return; + // If not, return only core. + if (!isset($node['nots'])) { + return $node['core']; } - // Otherwise reduce it to just the core node. - return $node['core']; - } } diff --git a/src/handlers/UnaryOperator.php b/src/handlers/UnaryOperator.php index 528773e5..dbf28c06 100644 --- a/src/handlers/UnaryOperator.php +++ b/src/handlers/UnaryOperator.php @@ -23,7 +23,7 @@ public static function handle(array $node, Context $context) { throw new InternalException("Handling unary operator without unary node"); } - $variableName = $node['core']['text']; + $variableName = $node['core']['core']['text']; $value = HandlerFactory ::get($node['core']['name']) ::handle($node['core'], $context); diff --git a/src/handlers/WhileStatement.php b/src/handlers/WhileStatement.php index 01e867d4..97369046 100644 --- a/src/handlers/WhileStatement.php +++ b/src/handlers/WhileStatement.php @@ -2,6 +2,7 @@ namespace Smuuf\Primi\Handlers; +use \Smuuf\Primi\Helpers\Common; use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Context; @@ -15,10 +16,10 @@ class WhileStatement extends \Smuuf\Primi\StrictObject implements IHandler { public static function handle(array $node, Context $context) { // Execute the left-hand node and get its return value. - $conditionHandler = HandlerFactory::get($node['left']['name']); + $condHandler = HandlerFactory::get($node['left']['name']); $blockHandler = HandlerFactory::get($node['right']['name']); - while ($conditionHandler::handle($node['left'], $context)->getInternalValue()) { + while (Common::isTruthy($condHandler::handle($node['left'], $context))) { $blockHandler::handle($node['right'], $context); } diff --git a/src/helpers/BinaryLTR.php b/src/helpers/BinaryLTR.php new file mode 100644 index 00000000..37d27a8f --- /dev/null +++ b/src/helpers/BinaryLTR.php @@ -0,0 +1,49 @@ +doAddition($right); + case $op === "-" && $left instanceof ISupportsSubtraction: + return $left->doSubtraction($right); + case $op === "*" && $left instanceof ISupportsMultiplication: + return $left->doMultiplication($right); + case $op === "/" && $left instanceof ISupportsDivision: + return $left->doDivision($right); + default: + // We're not throwing InternalBinaryOperationException + // because we want to unify handling of wrong "op" with + // whatever type errors might be thrown from inside the + // value's operator methods. + throw new \TypeError; + } + + } catch (\TypeError $e) { + + // Handle all type errors in one place. + throw new InternalBinaryOperationException($op, $left, $right); + + } + + } + +} + diff --git a/src/helpers/BinaryOpHandler.php b/src/helpers/BinaryOpHandler.php deleted file mode 100644 index a210e319..00000000 --- a/src/helpers/BinaryOpHandler.php +++ /dev/null @@ -1,84 +0,0 @@ -doAddition($right); - case $op === "-" && $left instanceof ISupportsSubtraction: - return $left->doSubtraction($right); - case $op === "*" && $left instanceof ISupportsMultiplication: - return $left->doMultiplication($right); - case $op === "/" && $left instanceof ISupportsDivision: - return $left->doDivision($right); - default: - // We're not throwing InternalBinaryOperationxception - // because we want to unify handling of wrong "op" with - // whatever type errors might be thrown from inside the - // value's operator methods. - throw new \TypeError; - } - - } catch (\TypeError $e) { - - // Handle all type errors in one place. - throw new InternalBinaryOperationxception($op, $left, $right); - - } - - } - - public static function handle(array $node, Context $context): Value { - - // Make sure even a single operand can be processed via foreach. - Common::ensureIndexed($node['ops']); - - $operands = $node['operands']; - - $firstOperand = array_shift($operands); - $handler = HandlerFactory::get($firstOperand['name']); - $result = $handler::handle($firstOperand, $context); - - // Go through each of the operands and continuously calculate the result - // value combining the operand's value with the result-so-far. The - // operator determining the operands's effect on the result has always - // the "n" index. (It would be "n-1" but we shifted the first operand - // already.) - foreach ($operands as $index => $operandNode) { - - $handler = HandlerFactory::get($operandNode['name']); - $tmp = $handler::handle($operandNode, $context); - - // Extract the text of the assigned operator node. - $op = $node['ops'][$index]['text']; - $result = self::evaluate($op, $result, $tmp); - - } - - return $result; - - } - -} - diff --git a/src/helpers/Common.php b/src/helpers/Common.php index af4ca374..0f67a6f1 100644 --- a/src/helpers/Common.php +++ b/src/helpers/Common.php @@ -2,10 +2,35 @@ namespace Smuuf\Primi\Helpers; +use \Smuuf\Primi\Structures\StringValue; +use \Smuuf\Primi\Structures\BoolValue; +use \Smuuf\Primi\Structures\NumberValue; +use \Smuuf\Primi\Structures\ArrayValue; use \Smuuf\Primi\Structures\Value; +use \Smuuf\Primi\InternalUndefinedTruthnessException; abstract class Common extends \Smuuf\Primi\StrictObject { + public static function isTruthy(Value $value): bool { + + $v = $value->getInternalValue(); + + switch (true) { + case $value instanceof StringValue: + return $v !== ""; + case $value instanceof BoolValue: + return $v; + case $value instanceof NumberValue: + return (bool) $v; + case $value instanceof ArrayValue: + return (bool) $v; + } + + $msg = sprintf("Cannot determine truthness of type '%s'", $value::TYPE); + throw new InternalUndefinedTruthnessException($msg); + + } + public static function objectHash($o): string { return substr(md5(spl_object_hash($o)), 0, 6); } @@ -22,13 +47,11 @@ public static function objectHash($o): string { */ public static function allowTypes(?Value $value, string ...$types) { + // If any of the "instanceof" checks is true, + // the type is allowed - return without throwing exception. foreach ($types as $type) { if ($value instanceof $type) { - - // If any of the "instanceof" checks is true, - // the type is allowed. return; - } } diff --git a/src/helpers/ComparisonEvaluation.php b/src/helpers/ComparisonEvaluation.php new file mode 100644 index 00000000..2684ee01 --- /dev/null +++ b/src/helpers/ComparisonEvaluation.php @@ -0,0 +1,70 @@ +doComparison($op, $right); + } catch (\TypeError $e) { + throw new InternalBinaryOperationException($op, $left, $right); + } + + } + + public static function handle(array $node, Context $context): BoolValue { + + // Make sure even a single operand can be processed via foreach. + Common::ensureIndexed($node['ops']); + + $operands = $node['operands']; + $result = true; + + foreach ($node['ops'] as $index => $opNode) { + + $lOperandNode = $operands[$index]; + $rOperandNode = $operands[$index + 1]; + + $left = HandlerFactory + ::get($lOperandNode['name']) + ::handle($lOperandNode, $context); + + $right = HandlerFactory + ::get($rOperandNode['name']) + ::handle($rOperandNode, $context); + + // Extract the text of the assigned operator node. + $op = $opNode['text']; + + $resultValue = static::evaluate($op, $left, $right); + $result &= Common::isTruthy($resultValue); + + // Short-circuiting, if any of the results is already false. + if (!$result) { + return new BoolValue(false); + } + + } + + return new BoolValue((bool) $result); + + } + +} + diff --git a/src/helpers/LeftToRightEvaluation.php b/src/helpers/LeftToRightEvaluation.php new file mode 100644 index 00000000..2eeaae2b --- /dev/null +++ b/src/helpers/LeftToRightEvaluation.php @@ -0,0 +1,55 @@ + $operandNode) { + + $handler = HandlerFactory::get($operandNode['name']); + $next = $handler::handle($operandNode, $context); + + // Extract the text of the assigned operator node. + $op = $node['ops'][$index]['text']; + $result = static::evaluate($op, $result, $next); + + if (static::SHORT_CIRCUIT && !Common::isTruthy($result)) { + return $result; + } + + } + + return $result; + + } + +} + diff --git a/src/helpers/LogicalLTR.php b/src/helpers/LogicalLTR.php new file mode 100644 index 00000000..7e79d098 --- /dev/null +++ b/src/helpers/LogicalLTR.php @@ -0,0 +1,36 @@ +construct($matchrule, $matchrule, \null); - if (\substr($this->string,$this->pos,1) === '!') { - $this->pos += 1; - $result["text"] .= '!'; - return $this->finalise($result); - } - else { return \false; } -} - - /* AddOperator: "+" | "-" */ protected $match_AddOperator_typestack = array('AddOperator'); function match_AddOperator ($stack = []) { $matchrule = "AddOperator"; $result = $this->construct($matchrule, $matchrule, \null); - $_139 = \null; + $_138 = \null; do { - $res_136 = $result; - $pos_136 = $this->pos; + $res_135 = $result; + $pos_135 = $this->pos; if (\substr($this->string,$this->pos,1) === '+') { $this->pos += 1; $result["text"] .= '+'; - $_139 = \true; break; + $_138 = \true; break; } - $result = $res_136; - $this->pos = $pos_136; + $result = $res_135; + $this->pos = $pos_135; if (\substr($this->string,$this->pos,1) === '-') { $this->pos += 1; $result["text"] .= '-'; - $_139 = \true; break; + $_138 = \true; break; } - $result = $res_136; - $this->pos = $pos_136; - $_139 = \false; break; + $result = $res_135; + $this->pos = $pos_135; + $_138 = \false; break; } while(0); - if( $_139 === \true ) { return $this->finalise($result); } - if( $_139 === \false) { return \false; } + if( $_138 === \true ) { return $this->finalise($result); } + if( $_138 === \false) { return \false; } } @@ -836,29 +823,29 @@ function match_AddOperator ($stack = []) { protected $match_MultiplyOperator_typestack = array('MultiplyOperator'); function match_MultiplyOperator ($stack = []) { $matchrule = "MultiplyOperator"; $result = $this->construct($matchrule, $matchrule, \null); - $_144 = \null; + $_143 = \null; do { - $res_141 = $result; - $pos_141 = $this->pos; + $res_140 = $result; + $pos_140 = $this->pos; if (\substr($this->string,$this->pos,1) === '*') { $this->pos += 1; $result["text"] .= '*'; - $_144 = \true; break; + $_143 = \true; break; } - $result = $res_141; - $this->pos = $pos_141; + $result = $res_140; + $this->pos = $pos_140; if (\substr($this->string,$this->pos,1) === '/') { $this->pos += 1; $result["text"] .= '/'; - $_144 = \true; break; + $_143 = \true; break; } - $result = $res_141; - $this->pos = $pos_141; - $_144 = \false; break; + $result = $res_140; + $this->pos = $pos_140; + $_143 = \false; break; } while(0); - if( $_144 === \true ) { return $this->finalise($result); } - if( $_144 === \false) { return \false; } + if( $_143 === \true ) { return $this->finalise($result); } + if( $_143 === \false) { return \false; } } @@ -879,93 +866,130 @@ function match_AssignmentOperator ($stack = []) { protected $match_ComparisonOperator_typestack = array('ComparisonOperator'); function match_ComparisonOperator ($stack = []) { $matchrule = "ComparisonOperator"; $result = $this->construct($matchrule, $matchrule, \null); - $_166 = \null; + $_165 = \null; do { - $res_147 = $result; - $pos_147 = $this->pos; + $res_146 = $result; + $pos_146 = $this->pos; if (( $subres = $this->literal( '==' ) ) !== \false) { $result["text"] .= $subres; - $_166 = \true; break; + $_165 = \true; break; } - $result = $res_147; - $this->pos = $pos_147; - $_164 = \null; + $result = $res_146; + $this->pos = $pos_146; + $_163 = \null; do { - $res_149 = $result; - $pos_149 = $this->pos; + $res_148 = $result; + $pos_148 = $this->pos; if (( $subres = $this->literal( '!=' ) ) !== \false) { $result["text"] .= $subres; - $_164 = \true; break; + $_163 = \true; break; } - $result = $res_149; - $this->pos = $pos_149; - $_162 = \null; + $result = $res_148; + $this->pos = $pos_148; + $_161 = \null; do { - $res_151 = $result; - $pos_151 = $this->pos; + $res_150 = $result; + $pos_150 = $this->pos; if (( $subres = $this->literal( '>=' ) ) !== \false) { $result["text"] .= $subres; - $_162 = \true; break; + $_161 = \true; break; } - $result = $res_151; - $this->pos = $pos_151; - $_160 = \null; + $result = $res_150; + $this->pos = $pos_150; + $_159 = \null; do { - $res_153 = $result; - $pos_153 = $this->pos; + $res_152 = $result; + $pos_152 = $this->pos; if (( $subres = $this->literal( '<=' ) ) !== \false) { $result["text"] .= $subres; - $_160 = \true; break; + $_159 = \true; break; } - $result = $res_153; - $this->pos = $pos_153; - $_158 = \null; + $result = $res_152; + $this->pos = $pos_152; + $_157 = \null; do { - $res_155 = $result; - $pos_155 = $this->pos; + $res_154 = $result; + $pos_154 = $this->pos; if (\substr($this->string,$this->pos,1) === '>') { $this->pos += 1; $result["text"] .= '>'; - $_158 = \true; break; + $_157 = \true; break; } - $result = $res_155; - $this->pos = $pos_155; + $result = $res_154; + $this->pos = $pos_154; if (\substr($this->string,$this->pos,1) === '<') { $this->pos += 1; $result["text"] .= '<'; - $_158 = \true; break; + $_157 = \true; break; } - $result = $res_155; - $this->pos = $pos_155; - $_158 = \false; break; + $result = $res_154; + $this->pos = $pos_154; + $_157 = \false; break; } while(0); - if( $_158 === \true ) { $_160 = \true; break; } - $result = $res_153; - $this->pos = $pos_153; - $_160 = \false; break; + if( $_157 === \true ) { $_159 = \true; break; } + $result = $res_152; + $this->pos = $pos_152; + $_159 = \false; break; } while(0); - if( $_160 === \true ) { $_162 = \true; break; } - $result = $res_151; - $this->pos = $pos_151; - $_162 = \false; break; + if( $_159 === \true ) { $_161 = \true; break; } + $result = $res_150; + $this->pos = $pos_150; + $_161 = \false; break; } while(0); - if( $_162 === \true ) { $_164 = \true; break; } - $result = $res_149; - $this->pos = $pos_149; - $_164 = \false; break; + if( $_161 === \true ) { $_163 = \true; break; } + $result = $res_148; + $this->pos = $pos_148; + $_163 = \false; break; } while(0); - if( $_164 === \true ) { $_166 = \true; break; } - $result = $res_147; - $this->pos = $pos_147; - $_166 = \false; break; + if( $_163 === \true ) { $_165 = \true; break; } + $result = $res_146; + $this->pos = $pos_146; + $_165 = \false; break; } while(0); - if( $_166 === \true ) { return $this->finalise($result); } - if( $_166 === \false) { return \false; } + if( $_165 === \true ) { return $this->finalise($result); } + if( $_165 === \false) { return \false; } +} + + +/* AndOperator: "and" */ +protected $match_AndOperator_typestack = array('AndOperator'); +function match_AndOperator ($stack = []) { + $matchrule = "AndOperator"; $result = $this->construct($matchrule, $matchrule, \null); + if (( $subres = $this->literal( 'and' ) ) !== \false) { + $result["text"] .= $subres; + return $this->finalise($result); + } + else { return \false; } +} + + +/* OrOperator: "or" */ +protected $match_OrOperator_typestack = array('OrOperator'); +function match_OrOperator ($stack = []) { + $matchrule = "OrOperator"; $result = $this->construct($matchrule, $matchrule, \null); + if (( $subres = $this->literal( 'or' ) ) !== \false) { + $result["text"] .= $subres; + return $this->finalise($result); + } + else { return \false; } +} + + +/* NegationOperator: "!" */ +protected $match_NegationOperator_typestack = array('NegationOperator'); +function match_NegationOperator ($stack = []) { + $matchrule = "NegationOperator"; $result = $this->construct($matchrule, $matchrule, \null); + if (\substr($this->string,$this->pos,1) === '!') { + $this->pos += 1; + $result["text"] .= '!'; + return $this->finalise($result); + } + else { return \false; } } @@ -973,170 +997,162 @@ function match_ComparisonOperator ($stack = []) { protected $match_UnaryOperator_typestack = array('UnaryOperator'); function match_UnaryOperator ($stack = []) { $matchrule = "UnaryOperator"; $result = $this->construct($matchrule, $matchrule, \null); - $_171 = \null; + $_173 = \null; do { - $res_168 = $result; - $pos_168 = $this->pos; + $res_170 = $result; + $pos_170 = $this->pos; if (( $subres = $this->literal( '++' ) ) !== \false) { $result["text"] .= $subres; - $_171 = \true; break; + $_173 = \true; break; } - $result = $res_168; - $this->pos = $pos_168; + $result = $res_170; + $this->pos = $pos_170; if (( $subres = $this->literal( '--' ) ) !== \false) { $result["text"] .= $subres; - $_171 = \true; break; + $_173 = \true; break; } - $result = $res_168; - $this->pos = $pos_168; - $_171 = \false; break; + $result = $res_170; + $this->pos = $pos_170; + $_173 = \false; break; } while(0); - if( $_171 === \true ) { return $this->finalise($result); } - if( $_171 === \false) { return \false; } + if( $_173 === \true ) { return $this->finalise($result); } + if( $_173 === \false) { return \false; } } -/* Expression: skip:AnonymousFunction | skip:Assignment | skip:Comparison | skip:Addition */ +/* Expression: skip:AnonymousFunction | skip:Assignment | skip:LogicalOr */ protected $match_Expression_typestack = array('Expression'); function match_Expression ($stack = []) { $matchrule = "Expression"; $result = $this->construct($matchrule, $matchrule, \null); - $_184 = \null; + $_182 = \null; do { - $res_173 = $result; - $pos_173 = $this->pos; + $res_175 = $result; + $pos_175 = $this->pos; $matcher = 'match_'.'AnonymousFunction'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_184 = \true; break; + $_182 = \true; break; } - $result = $res_173; - $this->pos = $pos_173; - $_182 = \null; + $result = $res_175; + $this->pos = $pos_175; + $_180 = \null; do { - $res_175 = $result; - $pos_175 = $this->pos; + $res_177 = $result; + $pos_177 = $this->pos; $matcher = 'match_'.'Assignment'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_182 = \true; break; + $_180 = \true; break; } - $result = $res_175; - $this->pos = $pos_175; - $_180 = \null; - do { - $res_177 = $result; - $pos_177 = $this->pos; - $matcher = 'match_'.'Comparison'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { - $this->store( $result, $subres, "skip" ); - $_180 = \true; break; - } - $result = $res_177; - $this->pos = $pos_177; - $matcher = 'match_'.'Addition'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { - $this->store( $result, $subres, "skip" ); - $_180 = \true; break; - } - $result = $res_177; - $this->pos = $pos_177; - $_180 = \false; break; + $result = $res_177; + $this->pos = $pos_177; + $matcher = 'match_'.'LogicalOr'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "skip" ); + $_180 = \true; break; } - while(0); - if( $_180 === \true ) { $_182 = \true; break; } - $result = $res_175; - $this->pos = $pos_175; - $_182 = \false; break; + $result = $res_177; + $this->pos = $pos_177; + $_180 = \false; break; } while(0); - if( $_182 === \true ) { $_184 = \true; break; } - $result = $res_173; - $this->pos = $pos_173; - $_184 = \false; break; + if( $_180 === \true ) { $_182 = \true; break; } + $result = $res_175; + $this->pos = $pos_175; + $_182 = \false; break; } while(0); - if( $_184 === \true ) { return $this->finalise($result); } - if( $_184 === \false) { return \false; } + if( $_182 === \true ) { return $this->finalise($result); } + if( $_182 === \false) { return \false; } } -/* Comparison: left:Addition __ op:ComparisonOperator __ right:Addition */ -protected $match_Comparison_typestack = array('Comparison'); -function match_Comparison ($stack = []) { - $matchrule = "Comparison"; $result = $this->construct($matchrule, $matchrule, \null); - $_191 = \null; +/* Assignment: left:Mutable __ AssignmentOperator __ right:Expression */ +protected $match_Assignment_typestack = array('Assignment'); +function match_Assignment ($stack = []) { + $matchrule = "Assignment"; $result = $this->construct($matchrule, $matchrule, \null); + $_189 = \null; do { - $matcher = 'match_'.'Addition'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Mutable'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "left" ); } - else { $_191 = \false; break; } + else { $_189 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_191 = \false; break; } - $matcher = 'match_'.'ComparisonOperator'; $key = $matcher; $pos = $this->pos; + else { $_189 = \false; break; } + $matcher = 'match_'.'AssignmentOperator'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { - $this->store( $result, $subres, "op" ); - } - else { $_191 = \false; break; } + if ($subres !== \false) { $this->store( $result, $subres ); } + else { $_189 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_191 = \false; break; } - $matcher = 'match_'.'Addition'; $key = $matcher; $pos = $this->pos; + else { $_189 = \false; break; } + $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "right" ); } - else { $_191 = \false; break; } - $_191 = \true; break; + else { $_189 = \false; break; } + $_189 = \true; break; } while(0); - if( $_191 === \true ) { return $this->finalise($result); } - if( $_191 === \false) { return \false; } + if( $_189 === \true ) { return $this->finalise($result); } + if( $_189 === \false) { return \false; } } -/* Assignment: left:Mutable __ op:AssignmentOperator __ right:Expression */ -protected $match_Assignment_typestack = array('Assignment'); -function match_Assignment ($stack = []) { - $matchrule = "Assignment"; $result = $this->construct($matchrule, $matchrule, \null); +/* LogicalOr: operands:LogicalAnd ( ] ops:OrOperator ] operands:LogicalAnd )* */ +protected $match_LogicalOr_typestack = array('LogicalOr'); +function match_LogicalOr ($stack = []) { + $matchrule = "LogicalOr"; $result = $this->construct($matchrule, $matchrule, \null); $_198 = \null; do { - $matcher = 'match_'.'Mutable'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { - $this->store( $result, $subres, "left" ); - } - else { $_198 = \false; break; } - $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_198 = \false; break; } - $matcher = 'match_'.'AssignmentOperator'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'LogicalAnd'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { - $this->store( $result, $subres, "op" ); + $this->store( $result, $subres, "operands" ); } else { $_198 = \false; break; } - $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_198 = \false; break; } - $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { - $this->store( $result, $subres, "right" ); + while (\true) { + $res_197 = $result; + $pos_197 = $this->pos; + $_196 = \null; + do { + if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } + else { $_196 = \false; break; } + $matcher = 'match_'.'OrOperator'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "ops" ); + } + else { $_196 = \false; break; } + if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } + else { $_196 = \false; break; } + $matcher = 'match_'.'LogicalAnd'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "operands" ); + } + else { $_196 = \false; break; } + $_196 = \true; break; + } + while(0); + if( $_196 === \false) { + $result = $res_197; + $this->pos = $pos_197; + unset( $res_197 ); + unset( $pos_197 ); + break; + } } - else { $_198 = \false; break; } $_198 = \true; break; } while(0); @@ -1145,13 +1161,13 @@ function match_Assignment ($stack = []) { } -/* Addition: operands:Multiplication ( __ ops:AddOperator __ operands:Multiplication)* */ -protected $match_Addition_typestack = array('Addition'); -function match_Addition ($stack = []) { - $matchrule = "Addition"; $result = $this->construct($matchrule, $matchrule, \null); +/* LogicalAnd: operands:Comparison ( ] ops:AndOperator ] operands:Comparison )* */ +protected $match_LogicalAnd_typestack = array('LogicalAnd'); +function match_LogicalAnd ($stack = []) { + $matchrule = "LogicalAnd"; $result = $this->construct($matchrule, $matchrule, \null); $_207 = \null; do { - $matcher = 'match_'.'Multiplication'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Comparison'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "operands" ); @@ -1162,21 +1178,17 @@ function match_Addition ($stack = []) { $pos_206 = $this->pos; $_205 = \null; do { - $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { $this->store( $result, $subres ); } + if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } else { $_205 = \false; break; } - $matcher = 'match_'.'AddOperator'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'AndOperator'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "ops" ); } else { $_205 = \false; break; } - $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; - $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); - if ($subres !== \false) { $this->store( $result, $subres ); } + if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } else { $_205 = \false; break; } - $matcher = 'match_'.'Multiplication'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Comparison'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "operands" ); @@ -1201,13 +1213,13 @@ function match_Addition ($stack = []) { } -/* Multiplication: operands:Negation ( __ ops:MultiplyOperator __ operands:Negation)* */ -protected $match_Multiplication_typestack = array('Multiplication'); -function match_Multiplication ($stack = []) { - $matchrule = "Multiplication"; $result = $this->construct($matchrule, $matchrule, \null); +/* Comparison: operands:Addition ( __ ops:ComparisonOperator __ operands:Addition )* */ +protected $match_Comparison_typestack = array('Comparison'); +function match_Comparison ($stack = []) { + $matchrule = "Comparison"; $result = $this->construct($matchrule, $matchrule, \null); $_216 = \null; do { - $matcher = 'match_'.'Negation'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Addition'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "operands" ); @@ -1222,7 +1234,7 @@ function match_Multiplication ($stack = []) { $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } else { $_214 = \false; break; } - $matcher = 'match_'.'MultiplyOperator'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'ComparisonOperator'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "ops" ); @@ -1232,7 +1244,7 @@ function match_Multiplication ($stack = []) { $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } else { $_214 = \false; break; } - $matcher = 'match_'.'Negation'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Addition'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "operands" ); @@ -1257,36 +1269,157 @@ function match_Multiplication ($stack = []) { } -/* Negation: not:NotOperator? core:Operand */ -protected $match_Negation_typestack = array('Negation'); -function match_Negation ($stack = []) { - $matchrule = "Negation"; $result = $this->construct($matchrule, $matchrule, \null); - $_220 = \null; +/* Addition: operands:Multiplication ( __ ops:AddOperator __ operands:Multiplication )* */ +protected $match_Addition_typestack = array('Addition'); +function match_Addition ($stack = []) { + $matchrule = "Addition"; $result = $this->construct($matchrule, $matchrule, \null); + $_225 = \null; do { - $res_218 = $result; - $pos_218 = $this->pos; - $matcher = 'match_'.'NotOperator'; $key = $matcher; $pos = $this->pos; + $matcher = 'match_'.'Multiplication'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { - $this->store( $result, $subres, "not" ); + $this->store( $result, $subres, "operands" ); } - else { - $result = $res_218; - $this->pos = $pos_218; - unset( $res_218 ); - unset( $pos_218 ); + else { $_225 = \false; break; } + while (\true) { + $res_224 = $result; + $pos_224 = $this->pos; + $_223 = \null; + do { + $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { $this->store( $result, $subres ); } + else { $_223 = \false; break; } + $matcher = 'match_'.'AddOperator'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "ops" ); + } + else { $_223 = \false; break; } + $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { $this->store( $result, $subres ); } + else { $_223 = \false; break; } + $matcher = 'match_'.'Multiplication'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "operands" ); + } + else { $_223 = \false; break; } + $_223 = \true; break; + } + while(0); + if( $_223 === \false) { + $result = $res_224; + $this->pos = $pos_224; + unset( $res_224 ); + unset( $pos_224 ); + break; + } + } + $_225 = \true; break; + } + while(0); + if( $_225 === \true ) { return $this->finalise($result); } + if( $_225 === \false) { return \false; } +} + + +/* Multiplication: operands:Negation ( __ ops:MultiplyOperator __ operands:Negation )* */ +protected $match_Multiplication_typestack = array('Multiplication'); +function match_Multiplication ($stack = []) { + $matchrule = "Multiplication"; $result = $this->construct($matchrule, $matchrule, \null); + $_234 = \null; + do { + $matcher = 'match_'.'Negation'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "operands" ); + } + else { $_234 = \false; break; } + while (\true) { + $res_233 = $result; + $pos_233 = $this->pos; + $_232 = \null; + do { + $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { $this->store( $result, $subres ); } + else { $_232 = \false; break; } + $matcher = 'match_'.'MultiplyOperator'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "ops" ); + } + else { $_232 = \false; break; } + $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { $this->store( $result, $subres ); } + else { $_232 = \false; break; } + $matcher = 'match_'.'Negation'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "operands" ); + } + else { $_232 = \false; break; } + $_232 = \true; break; + } + while(0); + if( $_232 === \false) { + $result = $res_233; + $this->pos = $pos_233; + unset( $res_233 ); + unset( $pos_233 ); + break; + } + } + $_234 = \true; break; + } + while(0); + if( $_234 === \true ) { return $this->finalise($result); } + if( $_234 === \false) { return \false; } +} + + +/* Negation: ( nots:NegationOperator )* core:Operand */ +protected $match_Negation_typestack = array('Negation'); +function match_Negation ($stack = []) { + $matchrule = "Negation"; $result = $this->construct($matchrule, $matchrule, \null); + $_240 = \null; + do { + while (\true) { + $res_238 = $result; + $pos_238 = $this->pos; + $_237 = \null; + do { + $matcher = 'match_'.'NegationOperator'; $key = $matcher; $pos = $this->pos; + $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); + if ($subres !== \false) { + $this->store( $result, $subres, "nots" ); + } + else { $_237 = \false; break; } + $_237 = \true; break; + } + while(0); + if( $_237 === \false) { + $result = $res_238; + $this->pos = $pos_238; + unset( $res_238 ); + unset( $pos_238 ); + break; + } } $matcher = 'match_'.'Operand'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); } - else { $_220 = \false; break; } - $_220 = \true; break; + else { $_240 = \false; break; } + $_240 = \true; break; } while(0); - if( $_220 === \true ) { return $this->finalise($result); } - if( $_220 === \false) { return \false; } + if( $_240 === \true ) { return $this->finalise($result); } + if( $_240 === \false) { return \false; } } @@ -1294,102 +1427,102 @@ function match_Negation ($stack = []) { protected $match_Operand_typestack = array('Operand'); function match_Operand ($stack = []) { $matchrule = "Operand"; $result = $this->construct($matchrule, $matchrule, \null); - $_240 = \null; + $_260 = \null; do { - $res_222 = $result; - $pos_222 = $this->pos; - $_237 = \null; + $res_242 = $result; + $pos_242 = $this->pos; + $_257 = \null; do { - $_234 = \null; + $_254 = \null; do { - $_232 = \null; + $_252 = \null; do { - $res_223 = $result; - $pos_223 = $this->pos; - $_229 = \null; + $res_243 = $result; + $pos_243 = $this->pos; + $_249 = \null; do { if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_229 = \false; break; } + else { $_249 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_229 = \false; break; } + else { $_249 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); } - else { $_229 = \false; break; } + else { $_249 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_229 = \false; break; } + else { $_249 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_229 = \false; break; } - $_229 = \true; break; + else { $_249 = \false; break; } + $_249 = \true; break; } while(0); - if( $_229 === \true ) { $_232 = \true; break; } - $result = $res_223; - $this->pos = $pos_223; + if( $_249 === \true ) { $_252 = \true; break; } + $result = $res_243; + $this->pos = $pos_243; $matcher = 'match_'.'Value'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); - $_232 = \true; break; + $_252 = \true; break; } - $result = $res_223; - $this->pos = $pos_223; - $_232 = \false; break; + $result = $res_243; + $this->pos = $pos_243; + $_252 = \false; break; } while(0); - if( $_232 === \false) { $_234 = \false; break; } - $_234 = \true; break; + if( $_252 === \false) { $_254 = \false; break; } + $_254 = \true; break; } while(0); - if( $_234 === \false) { $_237 = \false; break; } - $res_236 = $result; - $pos_236 = $this->pos; + if( $_254 === \false) { $_257 = \false; break; } + $res_256 = $result; + $pos_256 = $this->pos; $matcher = 'match_'.'Chain'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "chain" ); } else { - $result = $res_236; - $this->pos = $pos_236; - unset( $res_236 ); - unset( $pos_236 ); + $result = $res_256; + $this->pos = $pos_256; + unset( $res_256 ); + unset( $pos_256 ); } - $_237 = \true; break; + $_257 = \true; break; } while(0); - if( $_237 === \true ) { $_240 = \true; break; } - $result = $res_222; - $this->pos = $pos_222; + if( $_257 === \true ) { $_260 = \true; break; } + $result = $res_242; + $this->pos = $pos_242; $matcher = 'match_'.'Value'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_240 = \true; break; + $_260 = \true; break; } - $result = $res_222; - $this->pos = $pos_222; - $_240 = \false; break; + $result = $res_242; + $this->pos = $pos_242; + $_260 = \false; break; } while(0); - if( $_240 === \true ) { return $this->finalise($result); } - if( $_240 === \false) { return \false; } + if( $_260 === \true ) { return $this->finalise($result); } + if( $_260 === \false) { return \false; } } @@ -1397,74 +1530,74 @@ function match_Operand ($stack = []) { protected $match_Chain_typestack = array('Chain'); function match_Chain ($stack = []) { $matchrule = "Chain"; $result = $this->construct($matchrule, $matchrule, \null); - $_254 = \null; + $_274 = \null; do { - $_251 = \null; + $_271 = \null; do { - $_249 = \null; + $_269 = \null; do { - $res_242 = $result; - $pos_242 = $this->pos; + $res_262 = $result; + $pos_262 = $this->pos; $matcher = 'match_'.'Dereference'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); - $_249 = \true; break; + $_269 = \true; break; } - $result = $res_242; - $this->pos = $pos_242; - $_247 = \null; + $result = $res_262; + $this->pos = $pos_262; + $_267 = \null; do { - $res_244 = $result; - $pos_244 = $this->pos; + $res_264 = $result; + $pos_264 = $this->pos; $matcher = 'match_'.'Invocation'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); - $_247 = \true; break; + $_267 = \true; break; } - $result = $res_244; - $this->pos = $pos_244; + $result = $res_264; + $this->pos = $pos_264; $matcher = 'match_'.'ChainedFunction'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "core" ); - $_247 = \true; break; + $_267 = \true; break; } - $result = $res_244; - $this->pos = $pos_244; - $_247 = \false; break; + $result = $res_264; + $this->pos = $pos_264; + $_267 = \false; break; } while(0); - if( $_247 === \true ) { $_249 = \true; break; } - $result = $res_242; - $this->pos = $pos_242; - $_249 = \false; break; + if( $_267 === \true ) { $_269 = \true; break; } + $result = $res_262; + $this->pos = $pos_262; + $_269 = \false; break; } while(0); - if( $_249 === \false) { $_251 = \false; break; } - $_251 = \true; break; + if( $_269 === \false) { $_271 = \false; break; } + $_271 = \true; break; } while(0); - if( $_251 === \false) { $_254 = \false; break; } - $res_253 = $result; - $pos_253 = $this->pos; + if( $_271 === \false) { $_274 = \false; break; } + $res_273 = $result; + $pos_273 = $this->pos; $matcher = 'match_'.'Chain'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "chain" ); } else { - $result = $res_253; - $this->pos = $pos_253; - unset( $res_253 ); - unset( $pos_253 ); + $result = $res_273; + $this->pos = $pos_273; + unset( $res_273 ); + unset( $pos_273 ); } - $_254 = \true; break; + $_274 = \true; break; } while(0); - if( $_254 === \true ) { return $this->finalise($result); } - if( $_254 === \false) { return \false; } + if( $_274 === \true ) { return $this->finalise($result); } + if( $_274 === \false) { return \false; } } @@ -1472,37 +1605,37 @@ function match_Chain ($stack = []) { protected $match_Dereference_typestack = array('Dereference'); function match_Dereference ($stack = []) { $matchrule = "Dereference"; $result = $this->construct($matchrule, $matchrule, \null); - $_261 = \null; + $_281 = \null; do { if (\substr($this->string,$this->pos,1) === '[') { $this->pos += 1; $result["text"] .= '['; } - else { $_261 = \false; break; } + else { $_281 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_261 = \false; break; } + else { $_281 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "key" ); } - else { $_261 = \false; break; } + else { $_281 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_261 = \false; break; } + else { $_281 = \false; break; } if (\substr($this->string,$this->pos,1) === ']') { $this->pos += 1; $result["text"] .= ']'; } - else { $_261 = \false; break; } - $_261 = \true; break; + else { $_281 = \false; break; } + $_281 = \true; break; } while(0); - if( $_261 === \true ) { return $this->finalise($result); } - if( $_261 === \false) { return \false; } + if( $_281 === \true ) { return $this->finalise($result); } + if( $_281 === \false) { return \false; } } @@ -1510,44 +1643,44 @@ function match_Dereference ($stack = []) { protected $match_Invocation_typestack = array('Invocation'); function match_Invocation ($stack = []) { $matchrule = "Invocation"; $result = $this->construct($matchrule, $matchrule, \null); - $_268 = \null; + $_288 = \null; do { if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_268 = \false; break; } + else { $_288 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_268 = \false; break; } - $res_265 = $result; - $pos_265 = $this->pos; + else { $_288 = \false; break; } + $res_285 = $result; + $pos_285 = $this->pos; $matcher = 'match_'.'ArgumentList'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "args" ); } else { - $result = $res_265; - $this->pos = $pos_265; - unset( $res_265 ); - unset( $pos_265 ); + $result = $res_285; + $this->pos = $pos_285; + unset( $res_285 ); + unset( $pos_285 ); } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_268 = \false; break; } + else { $_288 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_268 = \false; break; } - $_268 = \true; break; + else { $_288 = \false; break; } + $_288 = \true; break; } while(0); - if( $_268 === \true ) { return $this->finalise($result); } - if( $_268 === \false) { return \false; } + if( $_288 === \true ) { return $this->finalise($result); } + if( $_288 === \false) { return \false; } } @@ -1555,29 +1688,29 @@ function match_Invocation ($stack = []) { protected $match_ChainedFunction_typestack = array('ChainedFunction'); function match_ChainedFunction ($stack = []) { $matchrule = "ChainedFunction"; $result = $this->construct($matchrule, $matchrule, \null); - $_273 = \null; + $_293 = \null; do { $matcher = 'match_'.'ObjectResolutionOperator'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_273 = \false; break; } + else { $_293 = \false; break; } $matcher = 'match_'.'Variable'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "fn" ); } - else { $_273 = \false; break; } + else { $_293 = \false; break; } $matcher = 'match_'.'Invocation'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "invo" ); } - else { $_273 = \false; break; } - $_273 = \true; break; + else { $_293 = \false; break; } + $_293 = \true; break; } while(0); - if( $_273 === \true ) { return $this->finalise($result); } - if( $_273 === \false) { return \false; } + if( $_293 === \true ) { return $this->finalise($result); } + if( $_293 === \false) { return \false; } } @@ -1585,54 +1718,54 @@ function match_ChainedFunction ($stack = []) { protected $match_ArgumentList_typestack = array('ArgumentList'); function match_ArgumentList ($stack = []) { $matchrule = "ArgumentList"; $result = $this->construct($matchrule, $matchrule, \null); - $_282 = \null; + $_302 = \null; do { $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "args" ); } - else { $_282 = \false; break; } + else { $_302 = \false; break; } while (\true) { - $res_281 = $result; - $pos_281 = $this->pos; - $_280 = \null; + $res_301 = $result; + $pos_301 = $this->pos; + $_300 = \null; do { $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_280 = \false; break; } + else { $_300 = \false; break; } if (\substr($this->string,$this->pos,1) === ',') { $this->pos += 1; $result["text"] .= ','; } - else { $_280 = \false; break; } + else { $_300 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_280 = \false; break; } + else { $_300 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "args" ); } - else { $_280 = \false; break; } - $_280 = \true; break; + else { $_300 = \false; break; } + $_300 = \true; break; } while(0); - if( $_280 === \false) { - $result = $res_281; - $this->pos = $pos_281; - unset( $res_281 ); - unset( $pos_281 ); + if( $_300 === \false) { + $result = $res_301; + $this->pos = $pos_301; + unset( $res_301 ); + unset( $pos_301 ); break; } } - $_282 = \true; break; + $_302 = \true; break; } while(0); - if( $_282 === \true ) { return $this->finalise($result); } - if( $_282 === \false) { return \false; } + if( $_302 === \true ) { return $this->finalise($result); } + if( $_302 === \false) { return \false; } } @@ -1640,54 +1773,54 @@ function match_ArgumentList ($stack = []) { protected $match_FunctionDefinitionArgumentList_typestack = array('FunctionDefinitionArgumentList'); function match_FunctionDefinitionArgumentList ($stack = []) { $matchrule = "FunctionDefinitionArgumentList"; $result = $this->construct($matchrule, $matchrule, \null); - $_291 = \null; + $_311 = \null; do { $matcher = 'match_'.'VariableName'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); } - else { $_291 = \false; break; } + else { $_311 = \false; break; } while (\true) { - $res_290 = $result; - $pos_290 = $this->pos; - $_289 = \null; + $res_310 = $result; + $pos_310 = $this->pos; + $_309 = \null; do { $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_289 = \false; break; } + else { $_309 = \false; break; } if (\substr($this->string,$this->pos,1) === ',') { $this->pos += 1; $result["text"] .= ','; } - else { $_289 = \false; break; } + else { $_309 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_289 = \false; break; } + else { $_309 = \false; break; } $matcher = 'match_'.'VariableName'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); } - else { $_289 = \false; break; } - $_289 = \true; break; + else { $_309 = \false; break; } + $_309 = \true; break; } while(0); - if( $_289 === \false) { - $result = $res_290; - $this->pos = $pos_290; - unset( $res_290 ); - unset( $pos_290 ); + if( $_309 === \false) { + $result = $res_310; + $this->pos = $pos_310; + unset( $res_310 ); + unset( $pos_310 ); break; } } - $_291 = \true; break; + $_311 = \true; break; } while(0); - if( $_291 === \true ) { return $this->finalise($result); } - if( $_291 === \false) { return \false; } + if( $_311 === \true ) { return $this->finalise($result); } + if( $_311 === \false) { return \false; } } @@ -1695,68 +1828,68 @@ function match_FunctionDefinitionArgumentList ($stack = []) { protected $match_FunctionDefinition_typestack = array('FunctionDefinition'); function match_FunctionDefinition ($stack = []) { $matchrule = "FunctionDefinition"; $result = $this->construct($matchrule, $matchrule, \null); - $_304 = \null; + $_324 = \null; do { if (( $subres = $this->literal( 'function' ) ) !== \false) { $result["text"] .= $subres; } - else { $_304 = \false; break; } + else { $_324 = \false; break; } if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } - else { $_304 = \false; break; } + else { $_324 = \false; break; } $matcher = 'match_'.'VariableName'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "function" ); } - else { $_304 = \false; break; } + else { $_324 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_304 = \false; break; } + else { $_324 = \false; break; } if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_304 = \false; break; } + else { $_324 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_304 = \false; break; } - $res_299 = $result; - $pos_299 = $this->pos; + else { $_324 = \false; break; } + $res_319 = $result; + $pos_319 = $this->pos; $matcher = 'match_'.'FunctionDefinitionArgumentList'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "args" ); } else { - $result = $res_299; - $this->pos = $pos_299; - unset( $res_299 ); - unset( $pos_299 ); + $result = $res_319; + $this->pos = $pos_319; + unset( $res_319 ); + unset( $pos_319 ); } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_304 = \false; break; } + else { $_324 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_304 = \false; break; } + else { $_324 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_304 = \false; break; } + else { $_324 = \false; break; } $matcher = 'match_'.'Block'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "body" ); } - else { $_304 = \false; break; } - $_304 = \true; break; + else { $_324 = \false; break; } + $_324 = \true; break; } while(0); - if( $_304 === \true ) { return $this->finalise($result); } - if( $_304 === \false) { return \false; } + if( $_324 === \true ) { return $this->finalise($result); } + if( $_324 === \false) { return \false; } } @@ -1764,59 +1897,59 @@ function match_FunctionDefinition ($stack = []) { protected $match_IfStatement_typestack = array('IfStatement'); function match_IfStatement ($stack = []) { $matchrule = "IfStatement"; $result = $this->construct($matchrule, $matchrule, \null); - $_317 = \null; + $_337 = \null; do { if (( $subres = $this->literal( 'if' ) ) !== \false) { $result["text"] .= $subres; } - else { $_317 = \false; break; } + else { $_337 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_317 = \false; break; } + else { $_337 = \false; break; } if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_317 = \false; break; } + else { $_337 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_317 = \false; break; } + else { $_337 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "left" ); } - else { $_317 = \false; break; } + else { $_337 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_317 = \false; break; } + else { $_337 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_317 = \false; break; } + else { $_337 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_317 = \false; break; } - $_315 = \null; + else { $_337 = \false; break; } + $_335 = \null; do { $matcher = 'match_'.'Block'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "right" ); } - else { $_315 = \false; break; } - $_315 = \true; break; + else { $_335 = \false; break; } + $_335 = \true; break; } while(0); - if( $_315 === \false) { $_317 = \false; break; } - $_317 = \true; break; + if( $_335 === \false) { $_337 = \false; break; } + $_337 = \true; break; } while(0); - if( $_317 === \true ) { return $this->finalise($result); } - if( $_317 === \false) { return \false; } + if( $_337 === \true ) { return $this->finalise($result); } + if( $_337 === \false) { return \false; } } @@ -1824,59 +1957,59 @@ function match_IfStatement ($stack = []) { protected $match_WhileStatement_typestack = array('WhileStatement'); function match_WhileStatement ($stack = []) { $matchrule = "WhileStatement"; $result = $this->construct($matchrule, $matchrule, \null); - $_330 = \null; + $_350 = \null; do { if (( $subres = $this->literal( 'while' ) ) !== \false) { $result["text"] .= $subres; } - else { $_330 = \false; break; } + else { $_350 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_330 = \false; break; } + else { $_350 = \false; break; } if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_330 = \false; break; } + else { $_350 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_330 = \false; break; } + else { $_350 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "left" ); } - else { $_330 = \false; break; } + else { $_350 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_330 = \false; break; } + else { $_350 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_330 = \false; break; } + else { $_350 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_330 = \false; break; } - $_328 = \null; + else { $_350 = \false; break; } + $_348 = \null; do { $matcher = 'match_'.'Block'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "right" ); } - else { $_328 = \false; break; } - $_328 = \true; break; + else { $_348 = \false; break; } + $_348 = \true; break; } while(0); - if( $_328 === \false) { $_330 = \false; break; } - $_330 = \true; break; + if( $_348 === \false) { $_350 = \false; break; } + $_350 = \true; break; } while(0); - if( $_330 === \true ) { return $this->finalise($result); } - if( $_330 === \false) { return \false; } + if( $_350 === \true ) { return $this->finalise($result); } + if( $_350 === \false) { return \false; } } @@ -1884,75 +2017,75 @@ function match_WhileStatement ($stack = []) { protected $match_ForeachStatement_typestack = array('ForeachStatement'); function match_ForeachStatement ($stack = []) { $matchrule = "ForeachStatement"; $result = $this->construct($matchrule, $matchrule, \null); - $_347 = \null; + $_367 = \null; do { if (( $subres = $this->literal( 'foreach' ) ) !== \false) { $result["text"] .= $subres; } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } if (\substr($this->string,$this->pos,1) === '(') { $this->pos += 1; $result["text"] .= '('; } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "left" ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } if (( $subres = $this->literal( 'as' ) ) !== \false) { $result["text"] .= $subres; } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'VariableName'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "item" ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } + else { $_367 = \false; break; } if (\substr($this->string,$this->pos,1) === ')') { $this->pos += 1; $result["text"] .= ')'; } - else { $_347 = \false; break; } + else { $_367 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_347 = \false; break; } - $_345 = \null; + else { $_367 = \false; break; } + $_365 = \null; do { $matcher = 'match_'.'Block'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "right" ); } - else { $_345 = \false; break; } - $_345 = \true; break; + else { $_365 = \false; break; } + $_365 = \true; break; } while(0); - if( $_345 === \false) { $_347 = \false; break; } - $_347 = \true; break; + if( $_365 === \false) { $_367 = \false; break; } + $_367 = \true; break; } while(0); - if( $_347 === \true ) { return $this->finalise($result); } - if( $_347 === \false) { return \false; } + if( $_367 === \true ) { return $this->finalise($result); } + if( $_367 === \false) { return \false; } } @@ -1960,31 +2093,31 @@ function match_ForeachStatement ($stack = []) { protected $match_CommandStatements_typestack = array('CommandStatements'); function match_CommandStatements ($stack = []) { $matchrule = "CommandStatements"; $result = $this->construct($matchrule, $matchrule, \null); - $_352 = \null; + $_372 = \null; do { - $res_349 = $result; - $pos_349 = $this->pos; + $res_369 = $result; + $pos_369 = $this->pos; $matcher = 'match_'.'EchoStatement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_352 = \true; break; + $_372 = \true; break; } - $result = $res_349; - $this->pos = $pos_349; + $result = $res_369; + $this->pos = $pos_369; $matcher = 'match_'.'ReturnStatement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_352 = \true; break; + $_372 = \true; break; } - $result = $res_349; - $this->pos = $pos_349; - $_352 = \false; break; + $result = $res_369; + $this->pos = $pos_369; + $_372 = \false; break; } while(0); - if( $_352 === \true ) { return $this->finalise($result); } - if( $_352 === \false) { return \false; } + if( $_372 === \true ) { return $this->finalise($result); } + if( $_372 === \false) { return \false; } } @@ -1992,23 +2125,23 @@ function match_CommandStatements ($stack = []) { protected $match_EchoStatement_typestack = array('EchoStatement'); function match_EchoStatement ($stack = []) { $matchrule = "EchoStatement"; $result = $this->construct($matchrule, $matchrule, \null); - $_357 = \null; + $_377 = \null; do { if (( $subres = $this->literal( 'echo' ) ) !== \false) { $result["text"] .= $subres; } - else { $_357 = \false; break; } + else { $_377 = \false; break; } if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } - else { $_357 = \false; break; } + else { $_377 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "subject" ); } - else { $_357 = \false; break; } - $_357 = \true; break; + else { $_377 = \false; break; } + $_377 = \true; break; } while(0); - if( $_357 === \true ) { return $this->finalise($result); } - if( $_357 === \false) { return \false; } + if( $_377 === \true ) { return $this->finalise($result); } + if( $_377 === \false) { return \false; } } @@ -2016,36 +2149,36 @@ function match_EchoStatement ($stack = []) { protected $match_ReturnStatement_typestack = array('ReturnStatement'); function match_ReturnStatement ($stack = []) { $matchrule = "ReturnStatement"; $result = $this->construct($matchrule, $matchrule, \null); - $_364 = \null; + $_384 = \null; do { if (( $subres = $this->literal( 'return' ) ) !== \false) { $result["text"] .= $subres; } - else { $_364 = \false; break; } - $res_363 = $result; - $pos_363 = $this->pos; - $_362 = \null; + else { $_384 = \false; break; } + $res_383 = $result; + $pos_383 = $this->pos; + $_382 = \null; do { if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } - else { $_362 = \false; break; } + else { $_382 = \false; break; } $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "subject" ); } - else { $_362 = \false; break; } - $_362 = \true; break; + else { $_382 = \false; break; } + $_382 = \true; break; } while(0); - if( $_362 === \false) { - $result = $res_363; - $this->pos = $pos_363; - unset( $res_363 ); - unset( $pos_363 ); + if( $_382 === \false) { + $result = $res_383; + $this->pos = $pos_383; + unset( $res_383 ); + unset( $pos_383 ); } - $_364 = \true; break; + $_384 = \true; break; } while(0); - if( $_364 === \true ) { return $this->finalise($result); } - if( $_364 === \false) { return \false; } + if( $_384 === \true ) { return $this->finalise($result); } + if( $_384 === \false) { return \false; } } @@ -2053,91 +2186,91 @@ function match_ReturnStatement ($stack = []) { protected $match_BlockStatements_typestack = array('BlockStatements'); function match_BlockStatements ($stack = []) { $matchrule = "BlockStatements"; $result = $this->construct($matchrule, $matchrule, \null); - $_382 = \null; + $_402 = \null; do { - $res_366 = $result; - $pos_366 = $this->pos; + $res_386 = $result; + $pos_386 = $this->pos; if (( $subres = $this->rx( '/[A-Za-z]/' ) ) !== \false) { $result["text"] .= $subres; - $result = $res_366; - $this->pos = $pos_366; + $result = $res_386; + $this->pos = $pos_386; } else { - $result = $res_366; - $this->pos = $pos_366; - $_382 = \false; break; + $result = $res_386; + $this->pos = $pos_386; + $_402 = \false; break; } - $_380 = \null; + $_400 = \null; do { - $_378 = \null; + $_398 = \null; do { - $res_367 = $result; - $pos_367 = $this->pos; + $res_387 = $result; + $pos_387 = $this->pos; $matcher = 'match_'.'IfStatement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_378 = \true; break; + $_398 = \true; break; } - $result = $res_367; - $this->pos = $pos_367; - $_376 = \null; + $result = $res_387; + $this->pos = $pos_387; + $_396 = \null; do { - $res_369 = $result; - $pos_369 = $this->pos; + $res_389 = $result; + $pos_389 = $this->pos; $matcher = 'match_'.'WhileStatement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_376 = \true; break; + $_396 = \true; break; } - $result = $res_369; - $this->pos = $pos_369; - $_374 = \null; + $result = $res_389; + $this->pos = $pos_389; + $_394 = \null; do { - $res_371 = $result; - $pos_371 = $this->pos; + $res_391 = $result; + $pos_391 = $this->pos; $matcher = 'match_'.'ForeachStatement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_374 = \true; break; + $_394 = \true; break; } - $result = $res_371; - $this->pos = $pos_371; + $result = $res_391; + $this->pos = $pos_391; $matcher = 'match_'.'FunctionDefinition'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_374 = \true; break; + $_394 = \true; break; } - $result = $res_371; - $this->pos = $pos_371; - $_374 = \false; break; + $result = $res_391; + $this->pos = $pos_391; + $_394 = \false; break; } while(0); - if( $_374 === \true ) { $_376 = \true; break; } - $result = $res_369; - $this->pos = $pos_369; - $_376 = \false; break; + if( $_394 === \true ) { $_396 = \true; break; } + $result = $res_389; + $this->pos = $pos_389; + $_396 = \false; break; } while(0); - if( $_376 === \true ) { $_378 = \true; break; } - $result = $res_367; - $this->pos = $pos_367; - $_378 = \false; break; + if( $_396 === \true ) { $_398 = \true; break; } + $result = $res_387; + $this->pos = $pos_387; + $_398 = \false; break; } while(0); - if( $_378 === \false) { $_380 = \false; break; } - $_380 = \true; break; + if( $_398 === \false) { $_400 = \false; break; } + $_400 = \true; break; } while(0); - if( $_380 === \false) { $_382 = \false; break; } - $_382 = \true; break; + if( $_400 === \false) { $_402 = \false; break; } + $_402 = \true; break; } while(0); - if( $_382 === \true ) { return $this->finalise($result); } - if( $_382 === \false) { return \false; } + if( $_402 === \true ) { return $this->finalise($result); } + if( $_402 === \false) { return \false; } } @@ -2145,73 +2278,73 @@ function match_BlockStatements ($stack = []) { protected $match_Statement_typestack = array('Statement'); function match_Statement ($stack = []) { $matchrule = "Statement"; $result = $this->construct($matchrule, $matchrule, \null); - $_396 = \null; + $_416 = \null; do { - $res_384 = $result; - $pos_384 = $this->pos; + $res_404 = $result; + $pos_404 = $this->pos; if (( $subres = $this->rx( '/[\s\{\};]/' ) ) !== \false) { $result["text"] .= $subres; - $result = $res_384; - $this->pos = $pos_384; - $_396 = \false; break; + $result = $res_404; + $this->pos = $pos_404; + $_416 = \false; break; } else { - $result = $res_384; - $this->pos = $pos_384; + $result = $res_404; + $this->pos = $pos_404; } - $_394 = \null; + $_414 = \null; do { - $_392 = \null; + $_412 = \null; do { - $res_385 = $result; - $pos_385 = $this->pos; + $res_405 = $result; + $pos_405 = $this->pos; $matcher = 'match_'.'BlockStatements'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_392 = \true; break; + $_412 = \true; break; } - $result = $res_385; - $this->pos = $pos_385; - $_390 = \null; + $result = $res_405; + $this->pos = $pos_405; + $_410 = \null; do { - $res_387 = $result; - $pos_387 = $this->pos; + $res_407 = $result; + $pos_407 = $this->pos; $matcher = 'match_'.'CommandStatements'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_390 = \true; break; + $_410 = \true; break; } - $result = $res_387; - $this->pos = $pos_387; + $result = $res_407; + $this->pos = $pos_407; $matcher = 'match_'.'Expression'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); - $_390 = \true; break; + $_410 = \true; break; } - $result = $res_387; - $this->pos = $pos_387; - $_390 = \false; break; + $result = $res_407; + $this->pos = $pos_407; + $_410 = \false; break; } while(0); - if( $_390 === \true ) { $_392 = \true; break; } - $result = $res_385; - $this->pos = $pos_385; - $_392 = \false; break; + if( $_410 === \true ) { $_412 = \true; break; } + $result = $res_405; + $this->pos = $pos_405; + $_412 = \false; break; } while(0); - if( $_392 === \false) { $_394 = \false; break; } - $_394 = \true; break; + if( $_412 === \false) { $_414 = \false; break; } + $_414 = \true; break; } while(0); - if( $_394 === \false) { $_396 = \false; break; } - $_396 = \true; break; + if( $_414 === \false) { $_416 = \false; break; } + $_416 = \true; break; } while(0); - if( $_396 === \true ) { return $this->finalise($result); } - if( $_396 === \false) { return \false; } + if( $_416 === \true ) { return $this->finalise($result); } + if( $_416 === \false) { return \false; } } @@ -2219,46 +2352,46 @@ function match_Statement ($stack = []) { protected $match_Block_typestack = array('Block'); function match_Block ($stack = []) { $matchrule = "Block"; $result = $this->construct($matchrule, $matchrule, \null); - $_404 = \null; + $_424 = \null; do { if (\substr($this->string,$this->pos,1) === '{') { $this->pos += 1; $result["text"] .= '{'; } - else { $_404 = \false; break; } + else { $_424 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_404 = \false; break; } - $res_402 = $result; - $pos_402 = $this->pos; - $_401 = \null; + else { $_424 = \false; break; } + $res_422 = $result; + $pos_422 = $this->pos; + $_421 = \null; do { $matcher = 'match_'.'Program'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres, "skip" ); } - else { $_401 = \false; break; } - $_401 = \true; break; + else { $_421 = \false; break; } + $_421 = \true; break; } while(0); - if( $_401 === \false) { - $result = $res_402; - $this->pos = $pos_402; - unset( $res_402 ); - unset( $pos_402 ); + if( $_421 === \false) { + $result = $res_422; + $this->pos = $pos_422; + unset( $res_422 ); + unset( $pos_422 ); } if (\substr($this->string,$this->pos,1) === '}') { $this->pos += 1; $result["text"] .= '}'; } - else { $_404 = \false; break; } - $_404 = \true; break; + else { $_424 = \false; break; } + $_424 = \true; break; } while(0); - if( $_404 === \true ) { return $this->finalise($result); } - if( $_404 === \false) { return \false; } + if( $_424 === \true ) { return $this->finalise($result); } + if( $_424 === \false) { return \false; } } @@ -2290,100 +2423,96 @@ function match_NL ($stack = []) { protected $match_SEP_typestack = array('SEP'); function match_SEP ($stack = []) { $matchrule = "SEP"; $result = $this->construct($matchrule, $matchrule, \null); - $_411 = \null; + $_431 = \null; do { - $res_408 = $result; - $pos_408 = $this->pos; + $res_428 = $result; + $pos_428 = $this->pos; if (\substr($this->string,$this->pos,1) === ';') { $this->pos += 1; $result["text"] .= ';'; - $_411 = \true; break; + $_431 = \true; break; } - $result = $res_408; - $this->pos = $pos_408; + $result = $res_428; + $this->pos = $pos_428; $matcher = 'match_'.'NL'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); - $_411 = \true; break; + $_431 = \true; break; } - $result = $res_408; - $this->pos = $pos_408; - $_411 = \false; break; + $result = $res_428; + $this->pos = $pos_428; + $_431 = \false; break; } while(0); - if( $_411 === \true ) { return $this->finalise($result); } - if( $_411 === \false) { return \false; } + if( $_431 === \true ) { return $this->finalise($result); } + if( $_431 === \false) { return \false; } } -/* Program: ( !/$/ __ Statement? > SEP )+ __ */ +/* Program: ( !/$/ __ Statement? > SEP )* __ */ protected $match_Program_typestack = array('Program'); function match_Program ($stack = []) { $matchrule = "Program"; $result = $this->construct($matchrule, $matchrule, \null); - $_421 = \null; + $_441 = \null; do { - $count = 0; while (\true) { - $res_419 = $result; - $pos_419 = $this->pos; - $_418 = \null; + $res_439 = $result; + $pos_439 = $this->pos; + $_438 = \null; do { - $res_413 = $result; - $pos_413 = $this->pos; + $res_433 = $result; + $pos_433 = $this->pos; if (( $subres = $this->rx( '/$/' ) ) !== \false) { $result["text"] .= $subres; - $result = $res_413; - $this->pos = $pos_413; - $_418 = \false; break; + $result = $res_433; + $this->pos = $pos_433; + $_438 = \false; break; } else { - $result = $res_413; - $this->pos = $pos_413; + $result = $res_433; + $this->pos = $pos_433; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_418 = \false; break; } - $res_415 = $result; - $pos_415 = $this->pos; + else { $_438 = \false; break; } + $res_435 = $result; + $pos_435 = $this->pos; $matcher = 'match_'.'Statement'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } else { - $result = $res_415; - $this->pos = $pos_415; - unset( $res_415 ); - unset( $pos_415 ); + $result = $res_435; + $this->pos = $pos_435; + unset( $res_435 ); + unset( $pos_435 ); } if (( $subres = $this->whitespace( ) ) !== \false) { $result["text"] .= $subres; } $matcher = 'match_'.'SEP'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_418 = \false; break; } - $_418 = \true; break; + else { $_438 = \false; break; } + $_438 = \true; break; } while(0); - if( $_418 === \false) { - $result = $res_419; - $this->pos = $pos_419; - unset( $res_419 ); - unset( $pos_419 ); + if( $_438 === \false) { + $result = $res_439; + $this->pos = $pos_439; + unset( $res_439 ); + unset( $pos_439 ); break; } - $count++; } - if ($count >= 1) { } - else { $_421 = \false; break; } $matcher = 'match_'.'__'; $key = $matcher; $pos = $this->pos; $subres = ( $this->packhas( $key, $pos ) ? $this->packread( $key, $pos ) : $this->packwrite( $key, $pos, $this->$matcher(\array_merge($stack, array($result))) ) ); if ($subres !== \false) { $this->store( $result, $subres ); } - else { $_421 = \false; break; } - $_421 = \true; break; + else { $_441 = \false; break; } + $_441 = \true; break; } while(0); - if( $_421 === \true ) { return $this->finalise($result); } - if( $_421 === \false) { return \false; } + if( $_441 === \true ) { return $this->finalise($result); } + if( $_441 === \false) { return \false; } } diff --git a/src/parser/Grammar.peg b/src/parser/Grammar.peg index b330ee42..619657b1 100644 --- a/src/parser/Grammar.peg +++ b/src/parser/Grammar.peg @@ -43,20 +43,28 @@ Vector: ( "[" __ ( arrayKey:Expression | arrayKey:Nothing ) __ "]" ) vector:Vect Mutable: skip:VariableVector | skip:VariableName ObjectResolutionOperator: "." -NotOperator: "!" AddOperator: "+" | "-" MultiplyOperator: "*" | "/" AssignmentOperator: "=" ComparisonOperator: "==" | "!=" | ">=" | "<=" | ">" | "<" +AndOperator: "and" +OrOperator: "or" +NegationOperator: "!" UnaryOperator: "++" | "--" -Expression: skip:AnonymousFunction | skip:Assignment | skip:Comparison | skip:Addition -Comparison: left:Addition __ op:ComparisonOperator __ right:Addition -Assignment: left:Mutable __ op:AssignmentOperator __ right:Expression -Addition: operands:Multiplication ( __ ops:AddOperator __ operands:Multiplication)* -Multiplication: operands:Negation ( __ ops:MultiplyOperator __ operands:Negation)* -Negation: not:NotOperator? core:Operand +Expression: skip:AnonymousFunction | skip:Assignment | skip:LogicalOr +Assignment: left:Mutable __ AssignmentOperator __ right:Expression + +# The order of how these rules are nested is very important, as it defines +# their priority. We also need that they all are left-associative. +LogicalOr: operands:LogicalAnd ( ] ops:OrOperator ] operands:LogicalAnd )* +LogicalAnd: operands:Comparison ( ] ops:AndOperator ] operands:Comparison )* +Comparison: operands:Addition ( __ ops:ComparisonOperator __ operands:Addition )* +Addition: operands:Multiplication ( __ ops:AddOperator __ operands:Multiplication )* +Multiplication: operands:Negation ( __ ops:MultiplyOperator __ operands:Negation )* +Negation: ( nots:NegationOperator )* core:Operand Operand: ( ( "(" __ core:Expression __ ")" | core:Value ) chain:Chain? ) | skip:Value + Chain: ( core:Dereference | core:Invocation | core:ChainedFunction ) chain:Chain? Dereference: "[" __ key:Expression __ "]" Invocation: "(" __ args:ArgumentList? __ ")" @@ -92,7 +100,7 @@ NL: / (?:\/\/[^\n]*)?\n / SEP: ";" | NL # "!/$/" Ensures we won't try to find statements at EOF. -Program: ( !/$/ __ Statement? > SEP )+ __ +Program: ( !/$/ __ Statement? > SEP )* __ */ diff --git a/src/parser/ParserHandler.php b/src/parser/ParserHandler.php index 68b22dfe..e326bb6f 100644 --- a/src/parser/ParserHandler.php +++ b/src/parser/ParserHandler.php @@ -4,6 +4,7 @@ use \Smuuf\Primi\HandlerFactory; use \Smuuf\Primi\Helpers\Common; +use \Smuuf\Primi\Handlers\IReducer; use \hafriedlander\Peg\Parser; @@ -122,7 +123,7 @@ protected static function reduceNode(array $node) { $handler = HandlerFactory::get($name); $reducers[$name] = false; - if (\is_subclass_of($handler, '\Smuuf\Primi\Handlers\IReducer')) { + if (\is_subclass_of($handler, IReducer::class)) { $reducers[$name] = $handler; if ($reduced = $handler::reduce($node)) { return self::reduceNode($reduced); diff --git a/src/structures/ArrayInsertionProxy.php b/src/structures/ArrayInsertionProxy.php index bdee66ef..4faf5d42 100644 --- a/src/structures/ArrayInsertionProxy.php +++ b/src/structures/ArrayInsertionProxy.php @@ -11,11 +11,8 @@ public function commit(Value $value) { try { $this->target->arraySet($this->key, $value); } catch (\TypeError $e) { - throw new ErrorException(sprintf( - "Cannot insert '%s' into '%s'", - $value::TYPE, - $this->target::TYPE - )); + $msg = sprintf("Cannot insert '%s' into '%s'", $value::TYPE, $this->target::TYPE); + throw new ErrorException($msg); } } diff --git a/src/structures/BoolValue.php b/src/structures/BoolValue.php index 3973aa8a..d7511c3e 100644 --- a/src/structures/BoolValue.php +++ b/src/structures/BoolValue.php @@ -4,6 +4,7 @@ use \Smuuf\Primi\ISupportsComparison; use \Smuuf\Primi\Helpers\Common; +use \Smuuf\Primi\Structures\NumberValue; use \Smuuf\Primi\Structures\NullValue; class BoolValue extends Value implements ISupportsComparison { @@ -18,15 +19,23 @@ public function getStringValue(): string { return $this->value ? 'true' : 'false'; } - public function doComparison(string $op, Value $rightOperand): BoolValue { + public function doComparison(string $op, Value $right): BoolValue { - Common::allowTypes($rightOperand, self::class, NullValue::class); + Common::allowTypes( + $right, + self::class, + NumberValue::class, + NullValue::class + ); + + $l = $this->value; + $r = Common::isTruthy($right); switch ($op) { case "==": - return new BoolValue($this->value == $rightOperand->value); + return new BoolValue($l === $r); case "!=": - return new BoolValue($this->value != $rightOperand->value); + return new BoolValue($l !== $r); default: throw new \TypeError; } diff --git a/src/structures/NumberValue.php b/src/structures/NumberValue.php index 893f8a91..20edfaa6 100644 --- a/src/structures/NumberValue.php +++ b/src/structures/NumberValue.php @@ -51,45 +51,45 @@ public static function isNumeric(string $input): bool { && (int) $input !== \PHP_INT_MIN; } - public function doAddition(Value $rightOperand): Value { + public function doAddition(Value $right): Value { - Common::allowTypes($rightOperand, self::class); - return new self($this->value + $rightOperand->value); + Common::allowTypes($right, self::class); + return new self($this->value + $right->value); } - public function doSubtraction(Value $rightOperand): self { - Common::allowTypes($rightOperand, self::class); - return new self($this->value - $rightOperand->value); + public function doSubtraction(Value $right): self { + Common::allowTypes($right, self::class); + return new self($this->value - $right->value); } - public function doMultiplication(Value $rightOperand) { + public function doMultiplication(Value $right) { - Common::allowTypes($rightOperand, self::class, StringValue::class); + Common::allowTypes($right, self::class, StringValue::class); - if ($rightOperand instanceof StringValue) { + if ($right instanceof StringValue) { $multiplier = $this->value; if (\is_int($multiplier) && $multiplier >= 0) { - $new = \str_repeat($rightOperand->value, $multiplier); + $new = \str_repeat($right->value, $multiplier); return new StringValue($new); } throw new \TypeError; } - return new self($this->value * $rightOperand->value); + return new self($this->value * $right->value); } - public function doDivision(Value $rightOperand): self { + public function doDivision(Value $right): self { - Common::allowTypes($rightOperand, self::class); + Common::allowTypes($right, self::class); // Avoid division by zero. - if ($rightOperand->value === 0) { + if ($right->value === 0) { throw new \Smuuf\Primi\ErrorException("Division by zero"); } - return new self($this->value / $rightOperand->value); + return new self($this->value / $right->value); } @@ -106,33 +106,56 @@ public function doUnary(string $op): self { } - public function doComparison(string $op, Value $rightOperand): BoolValue { - - Common::allowTypes($rightOperand, self::class, StringValue::class); + public function doComparison(string $op, Value $right): BoolValue { + + Common::allowTypes( + $right, + self::class, + BoolValue::class, + StringValue::class + ); + + // Numbers and strings can only be compared for equality - never equal. + if ($right instanceof StringValue) { + switch ($op) { + case "==": + return new BoolValue(false); + case "!=": + return new BoolValue(true); + } + throw new \TypeError; + } - // Numbers and strings can be only compared for equality. - // And are never equal. - if ($rightOperand instanceof StringValue) { - if ($op !== "==" && $op !== "!=") { - throw new \TypeError; + // Numbers and bools can only be compared for equality. + if ($right instanceof BoolValue) { + $leftTruth = Common::isTruthy($this); + switch ($op) { + case "==": + return new BoolValue($leftTruth === $right->value); + case "!=": + return new BoolValue($leftTruth !== $right->value); } + throw new \TypeError; } + $l = $this->value; + $r = $right->value; + switch ($op) { case "==": - // Don't do strict - wrong comparison of float and int. - return new BoolValue($this->value == $rightOperand->value); + // Don't do strict comparison - it's wrong for floats and ints. + return new BoolValue($l == $r); case "!=": - // Don't do strict - wrong comparison of float and int. - return new BoolValue($this->value != $rightOperand->value); + // Don't do strict comparison - it's wrong for floats and ints. + return new BoolValue($l != $r); case ">": - return new BoolValue($this->value > $rightOperand->value); + return new BoolValue($l > $r); case "<": - return new BoolValue($this->value < $rightOperand->value); + return new BoolValue($l < $r); case ">=": - return new BoolValue($this->value >= $rightOperand->value); + return new BoolValue($l >= $r); case "<=": - return new BoolValue($this->value <= $rightOperand->value); + return new BoolValue($l <= $r); default: throw new \TypeError; } diff --git a/tests/language/common.php b/tests/language/common.php index f4859172..430e0233 100644 --- a/tests/language/common.php +++ b/tests/language/common.php @@ -19,30 +19,49 @@ function test_dir(string $dir) { } -function run_test($file) { +function run_test(string $file) { $context = new \Smuuf\Primi\Context; $interpreter = new \Smuuf\Primi\Interpreter($context); $outputFile = dirname($file) . "/" . basename($file, ".primi") . ".expect"; - ob_start(); - - try { + $src = normalize(file_get_contents($file)); + $options = parse_pragmas($src); - // Run interpreter - $interpreter->run(file_get_contents($file)); + ob_start(); - } catch (\Smuuf\Primi\ErrorException $e) { + // Run interpreter. Do whole source at once or one-line-at-a-time, + // based on the "one_liners" pragma option. - printf("EX:%s\n", get_class($e)); + if (empty($options["one_liners"])) { - } finally { + try { + $interpreter->run($src); + } catch (\Smuuf\Primi\ErrorException $e) { + printf("EX:%s\n", get_class($e)); + } $vars = $context->getVariables(); array_walk($vars, function($x, $k) { printf("%s:%s:%s\n", $k, main_class($x), $x->getStringValue()); }); + } else { + + $lines = explode("\n", $src); + foreach ($lines as $line) { + try { + $context->reset(); + $interpreter->run($line); + $vars = $context->getVariables(); + array_walk($vars, function($x, $k) { + printf("%s:%s:%s\n", $k, main_class($x), $x->getStringValue()); + }); + } catch (\Smuuf\Primi\ErrorException $e) { + printf("EX:%s\n", get_class($e)); + } + } + } $output = normalize(ob_get_clean()); @@ -59,3 +78,26 @@ function normalize(string $string) { function main_class($instance) { return basename(str_replace('\\', '/', get_class($instance))); } + +function parse_pragmas(string $src) { + + $options = [ + "one_liners" => false, + ]; + + $lines = explode("\n", $src); + foreach ($lines as $line) { + if (preg_match("~^// pragma:(.*)$~", $line, $m)) { + + $name = $m[1]; + + if ($name === "one_liners") { + $options["one_liners"] = true; + } + + } + } + + return $options; + +} diff --git a/tests/language/extensions.phpt b/tests/language/extensions.phpt new file mode 100644 index 00000000..c20484a6 --- /dev/null +++ b/tests/language/extensions.phpt @@ -0,0 +1,4 @@ + { return 1;}) // [0: 1, 1: 1] +x_contains_true = a.contains("bbb") // true +x_contains_false = a.contains("ccc") // false +x_number_of_yes = a.number_of("aaa") // 1 +x_number_of_no = a.number_of("ccc") // 0 +x_popped = a.copy().pop() // "bbb" diff --git a/tests/language/suites/structures/valuemethods.strings.expect b/tests/language/suites/extensions/ext.string.expect similarity index 83% rename from tests/language/suites/structures/valuemethods.strings.expect rename to tests/language/suites/extensions/ext.string.expect index f75497d6..0572c4ee 100644 --- a/tests/language/suites/structures/valuemethods.strings.expect +++ b/tests/language/suites/extensions/ext.string.expect @@ -9,3 +9,6 @@ h:NumberValue:11 i:NumberValue:3 j:StringValue:"you can now format strings, you rascal!" k:StringValue:"1 2 3" +l:BoolValue:true +m:BoolValue:true +n:BoolValue:false diff --git a/tests/language/suites/structures/valuemethods.strings.primi b/tests/language/suites/extensions/ext.string.primi similarity index 64% rename from tests/language/suites/structures/valuemethods.strings.primi rename to tests/language/suites/extensions/ext.string.primi index e916a99f..18fb01f7 100644 --- a/tests/language/suites/structures/valuemethods.strings.primi +++ b/tests/language/suites/extensions/ext.string.primi @@ -1,10 +1,9 @@ - // First, last. a = "ahoj 123, jak se máš? 123"; -b = a.string_find_first("j"); -c = a.string_find_last("a"); -d = a.string_find_first(12); -e = a.string_find_last(23); // After multi-byte characters "áš" +b = a.find_first("j"); +c = a.find_last("a"); +d = a.find_first(12); +e = a.find_last(23); // After multi-byte characters "áš" // Length. f = "if you have a one gigawatt coal plant, you need an eighty car train full of coal every day to provide fuel.".length(); @@ -17,3 +16,7 @@ i = "1 gigawattová elektrárna každý den spotřebuje osmdesát vagonů uhlí. // Formatting. j = "{} can now {} strings, {1} rascal!".format("you", "format"); k = "{3} {2} {1}".format(3, "2", 1); + +l = "if you have a one gigawatt coal plant, you need an eighty car train full of coal every day to provide fuel.".contains("gigawatt"); +m = "ahoj ahoj ahoj!".contains(r"(ahoj ){2}!?") +n = "ahoj ahoj ahoj!".contains(r"(čau ){2}!?") diff --git a/tests/language/suites/operations/addition.primi b/tests/language/suites/operations/addition.primi index 41535641..34bd089e 100644 --- a/tests/language/suites/operations/addition.primi +++ b/tests/language/suites/operations/addition.primi @@ -1,3 +1,4 @@ +// pragma:one_liners // Numbers and numerical strings. a = 1 + 2; // 3 b = "1" + "2"; // "12" diff --git a/tests/language/suites/operations/casting.expect b/tests/language/suites/operations/casting.expect new file mode 100644 index 00000000..0c424bb9 --- /dev/null +++ b/tests/language/suites/operations/casting.expect @@ -0,0 +1,31 @@ +x_number_to_number:NumberValue:1 +x_number_to_string:StringValue:"1" +x_number_to_bool:BoolValue:true +EX:Smuuf\Primi\ErrorException +x_number_to_regex:RegexValue:r"1" +x_string_to_number:NumberValue:0 +x_string_to_string:StringValue:"a" +x_string_to_bool:BoolValue:true +EX:Smuuf\Primi\ErrorException +x_string_to_regex:RegexValue:r"a" +x_bool_true_to_number:NumberValue:1 +x_bool_true_to_string:StringValue:"1" +x_bool_true_to_bool:BoolValue:true +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +x_bool_false_to_number:NumberValue:0 +x_bool_false_to_string:StringValue:"" +x_bool_false_to_bool:BoolValue:false +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +x_array_to_bool:BoolValue:true +x_array_empty_to_bool:BoolValue:false +x_array_to_array:ArrayValue:[0: "a"] +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +x_regex_to_string:StringValue:"a" +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +x_regex_to_regex:RegexValue:r"a" diff --git a/tests/language/suites/operations/casting.primi b/tests/language/suites/operations/casting.primi new file mode 100644 index 00000000..30977078 --- /dev/null +++ b/tests/language/suites/operations/casting.primi @@ -0,0 +1,37 @@ +// pragma:one_liners +x_number_to_number = 1.to_number() // 1 +x_number_to_string = 1.to_string() // "1" +x_number_to_bool = 1.to_bool() // true +x_number_to_array = 1.to_array() // EX +x_number_to_regex = 1.to_regex() // r"1" + +x_string_to_number = "a".to_number() // 0 +x_string_to_string = "a".to_string() // "a" +x_string_to_bool = "a".to_bool() // true +x_string_to_array = "a".to_array() // EX +x_string_to_regex = "a".to_regex() // r"a" + +x_bool_true_to_number = true.to_number() // 1 +x_bool_true_to_string = true.to_string() // "1" +x_bool_true_to_bool = true.to_bool() // true +x_bool_true_to_array = true.to_array() // EX +x_bool_true_to_regex = true.to_regex() // EX + +x_bool_false_to_number = false.to_number() // 0 +x_bool_false_to_string = false.to_string() // "" +x_bool_false_to_bool = false.to_bool() // false +x_bool_false_to_array = false.to_array() // EX +x_bool_false_to_regex = false.to_regex() // EX + +x_array_to_number = ["a"].to_number() // EX +x_array_to_string = ["a"].to_string() // EX +x_array_to_bool = ["a"].to_bool() // true +x_array_empty_to_bool = [].to_bool() // false +x_array_to_array = ["a"].to_array() // [0: "a"] +x_array_to_regex = ["a"].to_regex() // EX + +x_regex_to_number = r"a".to_number() // EX +x_regex_to_string = r"a".to_string() // "a" +x_regex_to_bool = r"a".to_bool() // EX +x_regex_to_array = r"a".to_array() // EX +x_regex_to_regex = r"a".to_regex() // r"a" diff --git a/tests/language/suites/operations/comparison.expect b/tests/language/suites/operations/comparison.expect new file mode 100644 index 00000000..5d2c2b26 --- /dev/null +++ b/tests/language/suites/operations/comparison.expect @@ -0,0 +1,28 @@ +a:BoolValue:true +b:BoolValue:false +c:BoolValue:false +d:BoolValue:true +e:BoolValue:true +f:BoolValue:false +g:BoolValue:true +h:BoolValue:false +i:BoolValue:true +j:BoolValue:false +k:BoolValue:true +l:BoolValue:false +m:BoolValue:false +n:BoolValue:false +o:BoolValue:false +p:BoolValue:false +q:BoolValue:true +r:BoolValue:true +s:BoolValue:true +t:BoolValue:false +u:BoolValue:true +v:BoolValue:true +w:BoolValue:true +x:BoolValue:true +y:BoolValue:true +z:BoolValue:false +aa:BoolValue:false +ab:BoolValue:true diff --git a/tests/language/suites/operations/comparison.primi b/tests/language/suites/operations/comparison.primi new file mode 100644 index 00000000..55c01f08 --- /dev/null +++ b/tests/language/suites/operations/comparison.primi @@ -0,0 +1,32 @@ +a = 0 < 2; // true +b = 2 < 0; // false +c = -2 > 0; // false +d = -2 < 0; // true +e = 0 > -2; // true +f = 0 < -2; // false + +g = 1 < 2; // true +h = 2 < 1; // false +i = 2 > 1; // true +j = 1 > 2; // false + +k = 0 == 0; // true +l = 0 == 1; // false +m = 0 == -1; // false +n = 1 == -1; // false + +o = 0 != 0; // false +p = 1 != 1; // false +q = 1 != 0; // true +r = 0 != 1; // true + +s = 1 < 2 < 3; // true +t = 2 < 1 < 3; // false +u = -1 < 0 < 1; // true +v = 4 < 40 < 400; // true +w = 400 > 40 > 4; // true +x = 5 > 3 < 4; // true +y = 5 > -3 < 4; // true +z = 5 < 3 < 4; // false +aa = 5 < 3 > 4; // false +ab = 1 > 0 < 1; // true diff --git a/tests/language/suites/operations/comparison_bool.expect b/tests/language/suites/operations/comparison_bool.expect new file mode 100644 index 00000000..09aad575 --- /dev/null +++ b/tests/language/suites/operations/comparison_bool.expect @@ -0,0 +1,26 @@ +aa:BoolValue:true +ab:BoolValue:false +ac:BoolValue:false +ad:BoolValue:true +ae:BoolValue:false +af:BoolValue:true +ag:BoolValue:true +ah:BoolValue:false +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +bg:BoolValue:true +bh:BoolValue:false +bi:BoolValue:true +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +EX:Smuuf\Primi\ErrorException +cg:BoolValue:true +ch:BoolValue:false +ci:BoolValue:true diff --git a/tests/language/suites/operations/comparison_bool.primi b/tests/language/suites/operations/comparison_bool.primi new file mode 100644 index 00000000..9dcca0bd --- /dev/null +++ b/tests/language/suites/operations/comparison_bool.primi @@ -0,0 +1,29 @@ +// pragma:one_liners +aa = true == true; // true +ab = true == false; // false +ac = false == true; // false +ad = false == false; // true +ae = true != true; // false +af = true != false; // true +ag = false != true; // true +ah = false != false; // false + +ba = true > 0 // EX +bb = true < 0 // EX +bc = true > 1 // EX +bd = true < 1 // EX +be = true > -1 // EX +bf = true < -1 // EX +bg = true == 1 // true +bh = true == 0 // false +bi = true == -1 // true + +ca = 0 > true // EX +cb = 0 < true // EX +cc = 1 > true // EX +cd = 1 < true // EX +ce = -1 > true // EX +cf = -1 < true // EX +cg = 1 == true // true +ch = 0 == true // false +ci = -1 == true // true diff --git a/tests/language/suites/operations/invocation.expect b/tests/language/suites/operations/invocation.expect new file mode 100644 index 00000000..4d62442b --- /dev/null +++ b/tests/language/suites/operations/invocation.expect @@ -0,0 +1,7 @@ +fn:FuncValue:__function__ +a:NumberValue:1 +fn:FuncValue:__function__ +b:NumberValue:2 +EX:Smuuf\Primi\ErrorException +fn:FuncValue:__function__ +d:NumberValue:4 diff --git a/tests/language/suites/operations/invocation.primi b/tests/language/suites/operations/invocation.primi new file mode 100644 index 00000000..30ff827d --- /dev/null +++ b/tests/language/suites/operations/invocation.primi @@ -0,0 +1,5 @@ +// pragma:one_liners +fn = () => { return 1; }; a = fn(1); // 1 +fn = (a) => { return 1 + a; }; b = fn(1); // 2 +fn = (a, b) => { return (1 + a) * b; }; c = fn(1); // EX +fn = (a, b) => { return (1 + a) * b; }; d = fn(1, 2); // 4 diff --git a/tests/language/suites/operations/logical.expect b/tests/language/suites/operations/logical.expect new file mode 100644 index 00000000..c1f65893 --- /dev/null +++ b/tests/language/suites/operations/logical.expect @@ -0,0 +1,9 @@ +a:BoolValue:true +b:BoolValue:false +c:BoolValue:false +d:BoolValue:false +e:BoolValue:true +f:BoolValue:true +g:BoolValue:true +h:BoolValue:false + diff --git a/tests/language/suites/operations/logical.primi b/tests/language/suites/operations/logical.primi new file mode 100644 index 00000000..bd799afc --- /dev/null +++ b/tests/language/suites/operations/logical.primi @@ -0,0 +1,9 @@ +a = true and true; // true +b = true and false; // false +c = false and true; // false +d = false and false; // false +e = true or true; // true +f = true or false; // true +g = false or true; // true +h = false or false; // false + diff --git a/tests/language/suites/structures/valuemethods.expect b/tests/language/suites/structures/valuemethods.expect deleted file mode 100644 index 227509ef..00000000 --- a/tests/language/suites/structures/valuemethods.expect +++ /dev/null @@ -1,11 +0,0 @@ -a:StringValue:"ahojkyacauky" -b:StringValue:"xxxhojkyxxxcxxxuky" -c:StringValue:"volejoasijakprase" -d:StringValue:"volejourčitějakprase" -e:StringValue:"ab_____hijklmn" -_definitions:ArrayValue:["á": "a", "č": "c", "ě": "e"] -f:StringValue:"radoby cau" -g:StringValue:"lilek" -h:StringValue:"cislo je 1" -i:StringValue:"kokot je ee" -j:StringValue:"whatevs" diff --git a/tests/language/suites/structures/valuemethods.primi b/tests/language/suites/structures/valuemethods.primi deleted file mode 100644 index 4ed9af17..00000000 --- a/tests/language/suites/structures/valuemethods.primi +++ /dev/null @@ -1,21 +0,0 @@ -a = "ahojkyacauky"; -b = a.string_replace("a", "xxx"); -c = "voleneasijakprase".string_replace("ne", "jo"); -d = c.string_replace("asi", "určitě"); -e = "abcdefghijklmn".string_replace(r"[c-g]", "_"); - -_definitions = [ - "á": "a", - "č": "c", - "ě": "e" -]; - -f = "rádoby čau".string_replace(_definitions); - -// Method chaining -g = "vole".string_replace("v", "l").string_replace("o", "i") + "k"; -h = ("číslo je " + 000.cos().to_string()).string_replace(["č": "c", "í": "i"]); -i = "kokot je " + "oo".string_replace("o", "e"); - -// Only first two "a"s should be replaced. -j = "aaa".string_replace("aa", "c").string_replace("a", "x").string_replace("cx", "whatevs"); diff --git a/tests/unit/parser.comments.phpt b/tests/unit/parser.comments.phpt index 4e0b458d..afaac6a8 100644 --- a/tests/unit/parser.comments.phpt +++ b/tests/unit/parser.comments.phpt @@ -67,14 +67,6 @@ function get_ast_array_simple(string $text) { 'line' => 1, 'pos' => 0, ), - 'op' => - array( - 'name' => 'AssignmentOperator', - 'text' => '=', - 'offset' => 2, - 'line' => 1, - 'pos' => 2, - ), 'right' => array( 'name' => 'NumberLiteral', diff --git a/tests/unit/repl.phpt b/tests/unit/repl.phpt index 9a97e528..b7154044 100644 --- a/tests/unit/repl.phpt +++ b/tests/unit/repl.phpt @@ -9,7 +9,10 @@ $commands = [ 'a', 'a = 1', 'b', - 'a', + 'a', + '?', + 'c = \\', + '"xxx"', 'exit', ]; @@ -19,6 +22,8 @@ $expected = [ "1", "ERR: Undefined variable 'b' @ line 1, position 0, code: b", "1", + "a: 1", + '"xxx"', ]; $driver = new class implements \Smuuf\Primi\IReadlineDriver { diff --git a/tests/unit/strictobject.phpt b/tests/unit/strictobject.phpt new file mode 100644 index 00000000..f01dd7bb --- /dev/null +++ b/tests/unit/strictobject.phpt @@ -0,0 +1,17 @@ +undefined; +}, \LogicException::class, '~read~'); + +Assert::exception(function() use ($object) { + $object->undefined = 1; +}, \LogicException::class, '~write~'); diff --git a/tests/unit/value.array.phpt b/tests/unit/value.array.phpt index 2ddd32ef..17fb2210 100644 --- a/tests/unit/value.array.phpt +++ b/tests/unit/value.array.phpt @@ -83,11 +83,6 @@ $arr = new ArrayValue([$num1, $num2, $num3]); $val = $fns['array_random']->invoke([$arr]); Assert::true($val === $num1 || $val === $num2 || $val === $num3); -$items = get_val($fns['array_shuffle']->invoke([$arr])); -foreach ($items as $item) { - Assert::contains($item, get_val($arr)); -} - // Test cloning the array. $copy = $fns['array_copy']->invoke([$arr]); Assert::notSame($arr, $copy);