Enabled product bundles
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
//namespace PHPMathParser;
|
||||
|
||||
class WCJ_Parenthesis extends WCJ_TerminalExpression {
|
||||
|
||||
protected $precedence = 6;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
}
|
||||
|
||||
public function getPrecedence() {
|
||||
return $this->precedence;
|
||||
}
|
||||
|
||||
public function isNoOp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isParenthesis() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isOpen() {
|
||||
return $this->value == '(';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Number extends WCJ_TerminalExpression {
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract class WCJ_Operator extends WCJ_TerminalExpression {
|
||||
|
||||
protected $precedence = 0;
|
||||
protected $leftAssoc = true;
|
||||
|
||||
public function getPrecedence() {
|
||||
return $this->precedence;
|
||||
}
|
||||
|
||||
public function isLeftAssoc() {
|
||||
return $this->leftAssoc;
|
||||
}
|
||||
|
||||
public function isOperator() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Addition extends WCJ_Operator {
|
||||
|
||||
protected $precedence = 4;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
return $stack->pop()->operate($stack) + $stack->pop()->operate($stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Subtraction extends WCJ_Operator {
|
||||
|
||||
protected $precedence = 4;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
$left = $stack->pop()->operate($stack);
|
||||
$right = $stack->pop()->operate($stack);
|
||||
return $right - $left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Multiplication extends WCJ_Operator {
|
||||
|
||||
protected $precedence = 5;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
return $stack->pop()->operate($stack) * $stack->pop()->operate($stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Division extends WCJ_Operator {
|
||||
|
||||
protected $precedence = 5;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
$left = $stack->pop()->operate($stack);
|
||||
$right = $stack->pop()->operate($stack);
|
||||
return $right / $left;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WCJ_Power extends WCJ_Operator {
|
||||
|
||||
protected $precedence = 5;
|
||||
|
||||
public function operate(WCJ_Stack $stack) {
|
||||
$left = $stack->pop()->operate($stack);
|
||||
$right = $stack->pop()->operate($stack);
|
||||
return pow($left,$right);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
//namespace PHPMathParser;
|
||||
|
||||
require_once 'Stack.php';
|
||||
require_once 'TerminalExpression.php';
|
||||
require_once 'Expressions.php';
|
||||
|
||||
class WCJ_Math {
|
||||
|
||||
protected $variables = array();
|
||||
|
||||
public function evaluate($string) {
|
||||
$stack = $this->parse($string);
|
||||
return $this->run($stack);
|
||||
}
|
||||
|
||||
public function parse($string) {
|
||||
$tokens = $this->tokenize($string);
|
||||
$output = new WCJ_Stack();
|
||||
$operators = new WCJ_Stack();
|
||||
foreach ($tokens as $token) {
|
||||
$token = $this->extractVariables($token);
|
||||
$expression = WCJ_TerminalExpression::factory($token);
|
||||
if ($expression->isOperator()) {
|
||||
$this->parseOperator($expression, $output, $operators);
|
||||
} elseif ($expression->isParenthesis()) {
|
||||
$this->parseParenthesis($expression, $output, $operators);
|
||||
} else {
|
||||
$output->push($expression);
|
||||
}
|
||||
}
|
||||
while (($op = $operators->pop())) {
|
||||
if ($op->isParenthesis()) {
|
||||
throw new RuntimeException('Mismatched Parenthesis');
|
||||
}
|
||||
$output->push($op);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function registerVariable($name, $value) {
|
||||
$this->variables[$name] = $value;
|
||||
}
|
||||
|
||||
public function run(WCJ_Stack $stack) {
|
||||
while (($operator = $stack->pop()) && $operator->isOperator()) {
|
||||
$value = $operator->operate($stack);
|
||||
if (!is_null($value)) {
|
||||
$stack->push(WCJ_TerminalExpression::factory($value));
|
||||
}
|
||||
}
|
||||
return $operator ? $operator->render() : $this->render($stack);
|
||||
}
|
||||
|
||||
protected function extractVariables($token) {
|
||||
if ($token[0] == '$') {
|
||||
$key = substr($token, 1);
|
||||
return isset($this->variables[$key]) ? $this->variables[$key] : 0;
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
protected function render(WCJ_Stack $stack) {
|
||||
$output = '';
|
||||
while (($el = $stack->pop())) {
|
||||
$output .= $el->render();
|
||||
}
|
||||
if ($output) {
|
||||
return $output;
|
||||
}
|
||||
throw new RuntimeException('Could not render output');
|
||||
}
|
||||
|
||||
protected function parseParenthesis(WCJ_TerminalExpression $expression, WCJ_Stack $output, WCJ_Stack $operators) {
|
||||
if ($expression->isOpen()) {
|
||||
$operators->push($expression);
|
||||
} else {
|
||||
$clean = false;
|
||||
while (($end = $operators->pop())) {
|
||||
if ($end->isParenthesis()) {
|
||||
$clean = true;
|
||||
break;
|
||||
} else {
|
||||
$output->push($end);
|
||||
}
|
||||
}
|
||||
if (!$clean) {
|
||||
throw new RuntimeException('Mismatched Parenthesis');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseOperator(WCJ_TerminalExpression $expression, WCJ_Stack $output, WCJ_Stack $operators) {
|
||||
$end = $operators->poke();
|
||||
if (!$end) {
|
||||
$operators->push($expression);
|
||||
} elseif ($end->isOperator()) {
|
||||
do {
|
||||
if ($expression->isLeftAssoc() && $expression->getPrecedence() <= $end->getPrecedence()) {
|
||||
$output->push($operators->pop());
|
||||
} elseif (!$expression->isLeftAssoc() && $expression->getPrecedence() < $end->getPrecedence()) {
|
||||
$output->push($operators->pop());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (($end = $operators->poke()) && $end->isOperator());
|
||||
$operators->push($expression);
|
||||
} else {
|
||||
$operators->push($expression);
|
||||
}
|
||||
}
|
||||
|
||||
protected function tokenize($string) {
|
||||
$parts = preg_split('((\f+|\+|-|\(|\)|\*|\^|/)|\s+)', $string, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$parts = array_map('trim', $parts);
|
||||
return $parts;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
//namespace PHPMathParser;
|
||||
|
||||
class WCJ_Stack {
|
||||
|
||||
protected $data = array();
|
||||
|
||||
public function push($element) {
|
||||
$this->data[] = $element;
|
||||
}
|
||||
|
||||
public function poke() {
|
||||
return end($this->data);
|
||||
}
|
||||
|
||||
public function pop() {
|
||||
return array_pop($this->data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
//namespace PHPMathParser;
|
||||
|
||||
abstract class WCJ_TerminalExpression {
|
||||
|
||||
protected $value = '';
|
||||
|
||||
public function __construct($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public static function factory($value) {
|
||||
|
||||
// var_dump($value);
|
||||
if (is_object($value) && $value instanceof WCJ_TerminalExpression) {
|
||||
return $value;
|
||||
} elseif (is_numeric($value)) {
|
||||
return new WCJ_Number($value);
|
||||
} elseif ($value == '+') {
|
||||
return new WCJ_Addition($value);
|
||||
} elseif ($value == '-') {
|
||||
return new WCJ_Subtraction($value);
|
||||
} elseif ($value == '*') {
|
||||
return new WCJ_Multiplication($value);
|
||||
} elseif ($value == '/') {
|
||||
return new WCJ_Division($value);
|
||||
} elseif (in_array($value, array('(', ')'))) {
|
||||
return new WCJ_Parenthesis($value);
|
||||
} elseif ($value == '^') {
|
||||
return new WCJ_Power($value);
|
||||
}
|
||||
throw new Exception('Undefined Value ' . $value);
|
||||
}
|
||||
|
||||
abstract public function operate(WCJ_Stack $stack);
|
||||
|
||||
public function isOperator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isParenthesis() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isNoOp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user