Skip to content

Commit

Permalink
make null handling configurable, static interface, typed exception
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan Ackermann committed Apr 17, 2020
1 parent 318c34f commit 66c9ead
Show file tree
Hide file tree
Showing 16 changed files with 493 additions and 201 deletions.
11 changes: 11 additions & 0 deletions lib/MathParser/Exceptions/InvalidSyntaxException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace MathParser\Exceptions;

use RuntimeException;

class InvalidSyntaxException extends RuntimeException
{
}
34 changes: 18 additions & 16 deletions lib/MathParser/Expression.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace MathParser;

use MathParser\Expressions\Addition;
Expand All @@ -21,58 +23,58 @@ public function __construct($value)
$this->value = $value;
}

public static function factory($value)
public static function factory($value): Expression
{
if (is_object($value) && $value instanceof self) {
return $value;
} elseif (is_numeric($value)) {
// +0 => to number conversion (int or float)
return new Number($value + 0);
} elseif ($value == 'u') {
} elseif ($value === 'u') {
return new Unary($value);
} elseif ($value == '+') {
} elseif ($value === '+') {
return new Addition($value);
} elseif ($value == '-') {
} elseif ($value === '-') {
return new Subtraction($value);
} elseif ($value == '*') {
} elseif ($value === '*') {
return new Multiplication($value);
} elseif ($value == '/') {
} elseif ($value === '/') {
return new Division($value);
} elseif (in_array($value, array('(', ')'))) {
} elseif (in_array($value, ['(', ')'], true)) {
return new Parenthesis($value);
} elseif ($value == '^') {
} elseif ($value === '^') {
return new Power($value);
} elseif ($value == '%') {
} elseif ($value === '%') {
return new Modulo($value);
} elseif (strlen($value) >= 2 && $value[0] == '$') {
} elseif (strlen($value) >= 2 && $value[0] === '$') {
return new Variable(substr($value, 1));
}
throw new \RuntimeException('Undefined Value ' . $value);
}

abstract public function operate(array &$stack);
abstract public function operate(array &$stack, array $options);

public function isOperator()
public function isOperator(): bool
{
return false;
}

public function isUnary()
public function isUnary(): bool
{
return false;
}

public function isParenthesis()
public function isParenthesis(): bool
{
return false;
}

public function isNoOp()
public function isNoOp(): bool
{
return false;
}

public function isVariable()
public function isVariable(): bool
{
return false;
}
Expand Down
26 changes: 16 additions & 10 deletions lib/MathParser/Expressions/Addition.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Options\NullHandling;

class Addition extends Operator
{
protected $precedence = 4;
public function getPrecedence(): int
{
return 4;
}

public function operate(array &$stack)
public function operate(array &$stack, array $options)
{
$left = array_pop($stack)->operate($stack);
$right = array_pop($stack)->operate($stack);

if ($left === null || $right === null) {
return null;
}

return $left + $right;
return NullHandling::withNullHandling(
$stack,
$options,
static function ($left, $right) {
return $left + $right;
}
);
}
}
34 changes: 20 additions & 14 deletions lib/MathParser/Expressions/Division.php
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Options\NullHandling;

class Division extends Operator
{
protected $precedence = 5;
public function getPrecedence(): int
{
return 5;
}

public function operate(array &$stack)
public function operate(array &$stack, $options)
{
$left = array_pop($stack)->operate($stack);
$right = array_pop($stack)->operate($stack);

if ($left === null || $right === null) {
return null;
}

if ($left === 0) {
return null;
}

return $right / $left;
return NullHandling::withNullHandling(
$stack,
$options,
static function ($left, $right) {
if ($right === 0) {
return null;
}

return $left / $right;
}
);
}
}
34 changes: 20 additions & 14 deletions lib/MathParser/Expressions/Modulo.php
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Options\NullHandling;

class Modulo extends Operator
{
protected $precedence = 5;
public function getPrecedence(): int
{
return 5;
}

public function operate(array &$stack)
public function operate(array &$stack, array $options)
{
$left = array_pop($stack)->operate($stack);
$right = array_pop($stack)->operate($stack);

if ($left === null || $right === null) {
return null;
}

if ($left === 0) {
return null;
} else {
return $right % $left;
}
return NullHandling::withNullHandling(
$stack,
$options,
static function ($left, $right) {
if ($right === 0) {
return null;
} else {
return $left % $right;
}
}
);
}
}
26 changes: 17 additions & 9 deletions lib/MathParser/Expressions/Multiplication.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Options\NullHandling;

class Multiplication extends Operator
{
protected $precedence = 5;

public function operate(array &$stack)
public function getPrecedence(): int
{
return 5;
}

public function operate(array &$stack, array $options)
{
$left = array_pop($stack)->operate($stack);
$right = array_pop($stack)->operate($stack);
if ($left === null || $right === null) {
return null;
}
return $left * $right;
return NullHandling::withNullHandling(
$stack,
$options,
static function ($left, $right) {
return $left * $right;
}
);
}
}
9 changes: 3 additions & 6 deletions lib/MathParser/Expressions/Number.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Expression;

class Number extends Expression
{
public function __construct($value)
{
parent::__construct($value);
}

public function operate(array &$stack)
public function operate(array &$stack, $options)
{
return $this->value;
}
Expand Down
12 changes: 5 additions & 7 deletions lib/MathParser/Expressions/Operator.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Expression;

abstract class Operator extends Expression
{
protected $precedence = 0;
protected $leftAssoc = true;

public function getPrecedence()
{
return $this->precedence;
}
abstract public function getPrecedence(): int;

public function isLeftAssoc()
public function isLeftAssoc(): bool
{
return $this->leftAssoc;
}

public function isOperator()
public function isOperator(): bool
{
return true;
}
Expand Down
17 changes: 9 additions & 8 deletions lib/MathParser/Expressions/Parenthesis.php
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Expression;

class Parenthesis extends Expression
{
protected $precedence = 6;

public function operate(array &$stack)
public function operate(array &$stack, array $options = [])
{
}

public function getPrecedence()
public function getPrecedence(): int
{
return $this->precedence;
return 6;
}

public function isNoOp()
public function isNoOp(): bool
{
return true;
}

public function isParenthesis()
public function isParenthesis(): bool
{
return true;
}

public function isOpen()
public function isOpen(): bool
{
return $this->value == '(';
return $this->value === '(';
}
}
31 changes: 22 additions & 9 deletions lib/MathParser/Expressions/Power.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
<?php

declare(strict_types=1);

namespace MathParser\Expressions;

use MathParser\Options\NullHandling;

class Power extends Operator
{
protected $precedence = 6;

public function operate(array &$stack)
public function getPrecedence(): int
{
return 6;
}

public function isLeftAssoc(): bool
{
return false;
}

public function operate(array &$stack, array $options)
{
$right = array_pop($stack)->operate($stack);
$left = array_pop($stack)->operate($stack);

if ($left === null || $right === null) {
return null;
}
return pow($left, $right);
return NullHandling::withNullHandling(
$stack,
$options,
static function ($left, $right) {
return $left ** $right;
}
);
}
}
Loading

0 comments on commit 66c9ead

Please sign in to comment.