summaryrefslogtreecommitdiff
path: root/src/Calc.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Calc.php')
-rw-r--r--src/Calc.php138
1 files changed, 0 insertions, 138 deletions
diff --git a/src/Calc.php b/src/Calc.php
deleted file mode 100644
index e8dba8d..0000000
--- a/src/Calc.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-
-namespace kch42\ste;
-
-/* Class Calc contains static methods needed by <ste:calc /> */
-class Calc {
- private function __construct() {}
-
- /* We could also just eval() the $infix_math code, but this is much cooler :-D (Parser inception) */
- public static function shunting_yard($infix_math) {
- $operators = array(
- "+" => array("l", 2),
- "-" => array("l", 2),
- "*" => array("l", 3),
- "/" => array("l", 3),
- "^" => array("r", 4),
- "_" => array("r", 5),
- "(" => array("", 0),
- ")" => array("", 0)
- );
-
- preg_match_all("/\s*(?:(?:[+\\-\\*\\/\\^\\(\\)])|(\\d*[\\.]?\\d*))\\s*/s", $infix_math, $tokens, PREG_PATTERN_ORDER);
- $tokens_raw = array_filter(array_map('trim', $tokens[0]), function($x) { return ($x === "0") || (!empty($x)); });
- $output_queue = array();
- $op_stack = array();
-
- $lastpriority = NULL;
- /* Make - unary, if neccessary */
- $tokens = array();
- foreach($tokens_raw as $token) {
- $priority = isset($operators[$token]) ? $operators[$token][1] : -1;
- if(($token == "-") && (($lastpriority === NULL) || ($lastpriority >= 0))) {
- $priority = $operators["_"][1];
- $tokens[] = "_";
- } else {
- $tokens[] = $token;
- }
- $lastpriority = $priority;
- }
-
- while(!empty($tokens)) {
- $token = array_shift($tokens);
- if(is_numeric($token)) {
- $output_queue[] = $token;
- } else if($token == "(") {
- $op_stack[] = $token;
- } else if($token == ")") {
- $lbr_found = false;
- while(!empty($op_stack)) {
- $op = array_pop($op_stack);
- if($op == "(") {
- $lbr_found = true;
- break;
- }
- $output_queue[] = $op;
- }
- if(!$lbr_found) {
- throw new RuntimeError("Bracket mismatch.");
- }
- } else if(!isset($operators[$token])) {
- throw new RuntimeError("Invalid token ($token): Not a number, bracket or operator. Stop.");
- } else {
- $priority = $operators[$token][1];
- if($operators[$token][0] == "l") {
- while((!empty($op_stack)) and ($priority <= $operators[$op_stack[count($op_stack)-1]][1])) {
- $output_queue[] = array_pop($op_stack);
- }
- } else {
- while((!empty($op_stack)) and ($priority < $operators[$op_stack[count($op_stack)-1]][1])) {
- $output_queue[] = array_pop($op_stack);
- }
- }
- $op_stack[] = $token;
- }
- }
-
- while(!empty($op_stack)) {
- $op = array_pop($op_stack);
- if($op == "(") {
- throw new RuntimeError("Bracket mismatch...");
- }
- $output_queue[] = $op;
- }
-
- return $output_queue;
- }
-
- public static function pop2(&$array) {
- $rv = array(array_pop($array), array_pop($array));
- if(array_search(NULL, $rv, true) !== false) {
- throw new RuntimeError("Not enough numbers on stack. Invalid formula.");
- }
- return $rv;
- }
-
- public static function calc_rpn($rpn) {
- $stack = array();
- foreach($rpn as $token) {
- switch($token) {
- case "+":
- list($b, $a) = self::pop2($stack);
- $stack[] = $a + $b;
- break;
- case "-":
- list($b, $a) = self::pop2($stack);
- $stack[] = $a - $b;
- break;
- case "*":
- list($b, $a) = self::pop2($stack);
- $stack[] = $a * $b;
- break;
- case "/":
- list($b, $a) = self::pop2($stack);
- $stack[] = $a / $b;
- break;
- case "^":
- list($b, $a) = self::pop2($stack);
- $stack[] = pow($a, $b);
- break;
- case "_":
- $a = array_pop($stack);
- if($a === NULL) {
- throw new RuntimeError("Not enough numbers on stack. Invalid formula.");
- }
- $stack[] = -$a;
- break;
- default:
- $stack[] = $token;
- break;
- }
- }
- return array_pop($stack);
- }
-
- public static function calc($expr) {
- return self::calc_rpn(self::shunting_yard($expr));
- }
-} \ No newline at end of file