aboutsummaryrefslogtreecommitdiff
path: root/NXP
diff options
context:
space:
mode:
authorzhukv <zhuk2205@gmail.com>2013-08-03 14:47:47 +0400
committerzhukv <zhuk2205@gmail.com>2013-08-03 14:47:47 +0400
commiteb9c3651614dd5e5aef067880092e9f622c264df (patch)
treee093d7928420255e986acb44d4ab34634f601c52 /NXP
parent253fb694a3fcafa3f9ea6da6681f0b176cdec1f4 (diff)
Fix to PSR standart, fix tokenizer, fix function executor.
Diffstat (limited to 'NXP')
-rw-r--r--NXP/Classes/Func.php41
-rw-r--r--NXP/Classes/Operand.php85
-rw-r--r--NXP/Classes/Token.php53
-rw-r--r--NXP/Classes/TokenParser.php159
-rw-r--r--NXP/MathExecutor.php264
-rw-r--r--NXP/Tests/MathTest.php64
6 files changed, 0 insertions, 666 deletions
diff --git a/NXP/Classes/Func.php b/NXP/Classes/Func.php
deleted file mode 100644
index b3e5b93..0000000
--- a/NXP/Classes/Func.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 17.03.13
- * Time: 4:30
- */
-
-namespace NXP\Classes;
-
-
-class Func {
- /**
- * @var string
- */
- private $name;
-
- /**
- * @var callable
- */
- private $callback;
-
- /**
- * @param $name
- * @param $callback
- */
- function __construct($name, $callback)
- {
- $this->name = $name;
- $this->callback = $callback;
- }
-
- public function getName()
- {
- return $this->name;
- }
-
- public function getCallback()
- {
- return $this->callback;
- }
-} \ No newline at end of file
diff --git a/NXP/Classes/Operand.php b/NXP/Classes/Operand.php
deleted file mode 100644
index 3329679..0000000
--- a/NXP/Classes/Operand.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 17.03.13
- * Time: 4:27
- */
-
-namespace NXP\Classes;
-
-
-class Operand {
- const LEFT_ASSOCIATED = 'LEFT_ASSOCIATED';
- const RIGHT_ASSOCIATED = 'RIGHT_ASSOCIATED';
- const ASSOCIATED = 'ASSOCIATED';
-
- const UNARY = 'UNARY';
- const BINARY = 'BINARY';
-
- /**
- * @var string
- */
- private $symbol;
-
- /**
- * @var int
- */
- private $priority;
-
- /**
- * @var string
- */
- private $association;
-
- /**
- * @var string
- */
- private $type;
-
- /**
- * @var callable
- */
- private $callback;
-
- /**
- * @param $symbol
- * @param $priority
- * @param $association
- * @param $type
- * @param $callback
- */
- function __construct($symbol, $priority, $association, $type, $callback)
- {
- $this->association = $association;
- $this->symbol = $symbol;
- $this->type = $type;
- $this->priority = $priority;
- $this->callback = $callback;
- }
-
- public function getAssociation()
- {
- return $this->association;
- }
-
- public function getSymbol()
- {
- return $this->symbol;
- }
-
- public function getType()
- {
- return $this->type;
- }
-
- public function getCallback()
- {
- return $this->callback;
- }
-
- public function getPriority()
- {
- return $this->priority;
- }
-
-} \ No newline at end of file
diff --git a/NXP/Classes/Token.php b/NXP/Classes/Token.php
deleted file mode 100644
index 28bc736..0000000
--- a/NXP/Classes/Token.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 17.03.13
- * Time: 3:23
- */
-
-namespace NXP\Classes;
-
-
-class Token {
-
- const NOTHING = 'NOTHING';
- const STRING = 'STRING';
- const NUMBER = 'NUMBER';
- const OPERATOR = 'OPERATOR';
- const LEFT_BRACKET = 'LEFT_BRACKET';
- const RIGHT_BRACKET = 'RIGHT_BRACKET';
- const FUNC = 'FUNC';
-
- /**
- * @var string
- */
- protected $value;
-
- /**
- * @var string
- */
- protected $type;
-
- function __construct($type, $value)
- {
- $this->type = $type;
- $this->value = $value;
- }
-
- /**
- * @return string
- */
- public function getType()
- {
- return $this->type;
- }
-
- /**
- * @return string
- */
- public function getValue()
- {
- return $this->value;
- }
-
-} \ No newline at end of file
diff --git a/NXP/Classes/TokenParser.php b/NXP/Classes/TokenParser.php
deleted file mode 100644
index 7b9255f..0000000
--- a/NXP/Classes/TokenParser.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 17.03.13
- * Time: 2:45
- */
-
-namespace NXP\Classes;
-
-
-class TokenParser {
- const DIGIT = 'DIGIT';
- const CHAR = 'CHAR';
- const SPECIAL_CHAR = 'SPECIAL_CHAR';
- const LEFT_BRACKET = 'LEFT_BRACKET';
- const RIGHT_BRACKET = 'RIGHT_BRACKET';
- const SPACE = 'SPACE';
-
- private $terms = [
- self::DIGIT => '[0-9\.]',
- self::CHAR => '[a-z]',
- self::SPECIAL_CHAR => '[\!\@\#\$\%\^\&\*\/\|\-\+\=\~]',
- self::LEFT_BRACKET => '\(',
- self::RIGHT_BRACKET => '\)',
- self::SPACE => '\s'
- ];
-
- const ERROR_STATE = 'ERROR_STATE';
-
- private $transitions = [
- Token::NOTHING => [
- self::DIGIT => Token::NUMBER,
- self::CHAR => Token::STRING,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- Token::STRING => [
- self::DIGIT => Token::STRING,
- self::CHAR => Token::STRING,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- Token::NUMBER => [
- self::DIGIT => Token::NUMBER,
- self::CHAR => self::ERROR_STATE,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- Token::OPERATOR => [
- self::DIGIT => Token::NUMBER,
- self::CHAR => Token::STRING,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- self::ERROR_STATE => [
- self::DIGIT => self::ERROR_STATE,
- self::CHAR => self::ERROR_STATE,
- self::SPECIAL_CHAR => self::ERROR_STATE,
- self::LEFT_BRACKET => self::ERROR_STATE,
- self::RIGHT_BRACKET => self::ERROR_STATE,
- self::SPACE => self::ERROR_STATE
- ],
- Token::LEFT_BRACKET => [
- self::DIGIT => Token::NUMBER,
- self::CHAR => Token::STRING,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- Token::RIGHT_BRACKET => [
- self::DIGIT => Token::NUMBER,
- self::CHAR => Token::STRING,
- self::SPECIAL_CHAR => Token::OPERATOR,
- self::LEFT_BRACKET => Token::LEFT_BRACKET,
- self::RIGHT_BRACKET => Token::RIGHT_BRACKET,
- self::SPACE => Token::NOTHING
- ],
- ];
-
- private $accumulator = '';
-
- private $state = Token::NOTHING;
-
- private $queue = null;
-
- function __construct()
- {
- $this->queue = new \SplQueue();
- }
-
- /**
- * Tokenize math expression
- * @param $expression
- * @return \SplQueue
- * @throws \Exception
- */
- public function tokenize($expression)
- {
- $oldState = null;
- for ($i=0; $i<strlen($expression); $i++) {
- $char = substr($expression, $i, 1);
- $class = $this->getSymbolType($char);
- $oldState = $this->state;
- $this->state = $this->transitions[$this->state][$class];
- if ($this->state == self::ERROR_STATE) {
- throw new \Exception("Parse expression error at $i column (symbol '$char')");
- }
- $this->addToQueue($oldState);
- $this->accumulator .= $char;
- }
- if (!empty($this->accumulator)) {
- $token = new Token($this->state, $this->accumulator);
- $this->queue->push($token);
- }
-
- return $this->queue;
- }
-
- /**
- * @param $symbol
- * @return string
- * @throws \Exception
- */
- private function getSymbolType($symbol)
- {
- foreach ($this->terms as $class => $regex) {
- if (preg_match("/$regex/i", $symbol)) {
- return $class;
- }
- }
-
- throw new \Exception("Unknown char '$symbol'");
- }
-
- /**
- * @param $oldState
- */
- private function addToQueue($oldState)
- {
- if ($oldState == Token::NOTHING) {
- $this->accumulator = '';
- return;
- }
- if (($this->state != $oldState) || ($oldState == Token::LEFT_BRACKET) || ($oldState == Token::RIGHT_BRACKET)) {
- $token = new Token($oldState, $this->accumulator);
- $this->queue->push($token);
- $this->accumulator = '';
- }
- }
-} \ No newline at end of file
diff --git a/NXP/MathExecutor.php b/NXP/MathExecutor.php
deleted file mode 100644
index cc1c187..0000000
--- a/NXP/MathExecutor.php
+++ /dev/null
@@ -1,264 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 14.03.13
- * Time: 1:01
- */
-namespace NXP;
-
-use NXP\Classes\Func;
-use NXP\Classes\Operand;
-use NXP\Classes\Token;
-use NXP\Classes\TokenParser;
-
-/**
- * Class MathExecutor
- * @package NXP
- */
-class MathExecutor {
-
-
- private $operators = [ ];
-
- private $functions = [ ];
-
- private $variables = [ ];
-
- /**
- * @var \SplStack
- */
- private $stack;
-
- /**
- * @var \SplQueue
- */
- private $queue;
-
- /**
- * Base math operators
- */
- public function __construct()
- {
- $this->addOperator(new Operand('+', 1, Operand::LEFT_ASSOCIATED, Operand::BINARY, function ($op1, $op2) { return $op1+$op2; }));
- $this->addOperator(new Operand('-', 1, Operand::LEFT_ASSOCIATED, Operand::BINARY, function ($op1, $op2) { return $op1-$op2; }));
- $this->addOperator(new Operand('*', 2, Operand::LEFT_ASSOCIATED, Operand::BINARY, function ($op1, $op2) { return $op1*$op2; }));
- $this->addOperator(new Operand('/', 2, Operand::LEFT_ASSOCIATED, Operand::BINARY, function ($op1, $op2) { return $op1/$op2; }));
- $this->addOperator(new Operand('^', 3, Operand::LEFT_ASSOCIATED, Operand::BINARY, function ($op1, $op2) { return pow($op1,$op2); }));
-
- $this->addFunction(new Func('sin', function ($arg) { return sin($arg); }));
- $this->addFunction(new Func('cos', function ($arg) { return cos($arg); }));
- $this->addFunction(new Func('tn', function ($arg) { return tan($arg); }));
- $this->addFunction(new Func('asin', function ($arg) { return asin($arg); }));
- $this->addFunction(new Func('acos', function ($arg) { return acos($arg); }));
- $this->addFunction(new Func('atn', function ($arg) { return atan($arg); }));
- }
-
- /**
- * Add operator to executor
- * @param Operand $operator
- */
- public function addOperator(Operand $operator)
- {
- $this->operators[$operator->getSymbol()] = $operator;
- }
-
- /**
- * Add function to executor
- * @param Func $function
- */
- public function addFunction(Func $function)
- {
- $this->functions[$function->getName()] = $function->getCallback();
- }
-
- /**
- * Add variable to executor
- * @param $variable
- * @param $value
- * @throws \Exception
- */
- public function setVar($variable, $value)
- {
- if (!is_numeric($value)) {
- throw new \Exception("Variable value must be a number");
- }
- $this->variables[$variable] = $value;
- }
-
- /**
- * Execute expression
- * @param $expression
- * @return int|float
- */
- public function execute($expression)
- {
- $reversePolishNotation = $this->convertToReversePolishNotation($expression);
- $result = $this->calculateReversePolishNotation($reversePolishNotation);
-
- return $result;
- }
-
- /**
- * Convert expression from normal expression form to RPN
- * @param $expression
- * @return \SplQueue
- * @throws \Exception
- */
- private function convertToReversePolishNotation($expression)
- {
- $this->stack = new \SplStack();
- $this->queue = new \SplQueue();
-
- $tokenParser = new TokenParser();
- $input = $tokenParser->tokenize($expression);
-
- foreach ($input as $token) {
- $this->categorizeToken($token);
- }
-
- while (!$this->stack->isEmpty()) {
- $token = $this->stack->pop();
- if ($token->getType() != Token::OPERATOR) {
- throw new \Exception('Opening bracket without closing bracket');
- }
- $this->queue->push($token);
- }
-
- return $this->queue;
- }
-
- /**
- * @param Token $token
- * @throws \Exception
- */
- private function categorizeToken(Token $token)
- {
- switch ($token->getType()) {
- case Token::NUMBER :
- $this->queue->push($token);
- break;
-
- case Token::STRING:
- if (array_key_exists($token->getValue(), $this->variables)) {
- $this->queue->push(new Token(Token::NUMBER, $this->variables[$token->getValue()]));
- } else {
- $this->stack->push($token);
- }
- break;
-
- case Token::LEFT_BRACKET:
- $this->stack->push($token);
- break;
-
- case Token::RIGHT_BRACKET:
- $previousToken = $this->stack->pop();
- while (!$this->stack->isEmpty() && ($previousToken->getType() != Token::LEFT_BRACKET)) {
- $this->queue->push($previousToken);
- $previousToken = $this->stack->pop();
- }
- if ((!$this->stack->isEmpty()) && ($this->stack->top()->getType() == Token::STRING)) {
- $string = $this->stack->pop()->getValue();
- if (!array_key_exists($string, $this->functions)) {
- throw new \Exception('Unknown function');
- }
- $this->queue->push(new Token(Token::FUNC, $string));
- }
- break;
-
- case Token::OPERATOR:
- if (!array_key_exists($token->getValue(), $this->operators)) {
- throw new \Exception("Unknown operator '{$token->getValue()}'");
- }
-
- $this->proceedOperator($token);
- $this->stack->push($token);
- break;
-
- default:
- throw new \Exception('Unknown token');
- }
- }
-
- /**
- * @param $token
- * @throws \Exception
- */
- private function proceedOperator($token)
- {
- if (!array_key_exists($token->getValue(), $this->operators)) {
- throw new \Exception('Unknown operator');
- }
- /** @var Operand $operator */
- $operator = $this->operators[$token->getValue()];
- while (!$this->stack->isEmpty()) {
- $top = $this->stack->top();
- if ($top->getType() == Token::OPERATOR) {
- $priority = $this->operators[$top->getValue()]->getPriority();
- if ( $operator->getAssociation() == Operand::RIGHT_ASSOCIATED) {
- if (($priority > $operator->getPriority())) {
- $this->queue->push($this->stack->pop());
- } else {
- return;
- }
- } else {
- if (($priority >= $operator->getPriority())) {
- $this->queue->push($this->stack->pop());
- } else {
- return;
- }
- }
- } elseif ($top->getType() == Token::STRING) {
- $this->queue->push($this->stack->pop());
- } else {
- return;
- }
- }
- }
-
- /**
- * @param \SplQueue $expression
- * @return mixed
- * @throws \Exception
- */
- private function calculateReversePolishNotation(\SplQueue $expression)
- {
- $this->stack = new \SplStack();
- /** @val Token $token */
- foreach ($expression as $token) {
- switch ($token->getType()) {
- case Token::NUMBER :
- $this->stack->push($token);
- break;
- case Token::OPERATOR:
- /** @var Operand $operator */
- $operator = $this->operators[$token->getValue()];
- if ($operator->getType() == Operand::BINARY) {
- $arg2 = $this->stack->pop()->getValue();
- $arg1 = $this->stack->pop()->getValue();
- } else {
- $arg2 = null;
- $arg1 = $this->stack->pop()->getValue();
- }
- $callback = $operator->getCallback();
-
-
- $this->stack->push(new Token(Token::NUMBER, ($callback($arg1, $arg2))));
- break;
- case Token::FUNC:
- /** @var Func $function */
- $callback = $this->functions[$token->getValue()];
- $arg = $this->stack->pop()->getValue();
- $this->stack->push(new Token(Token::NUMBER, ($callback($arg))));
- break;
- default:
- throw new \Exception('Unknown token');
- }
- }
- $result = $this->stack->pop()->getValue();
- if (!$this->stack->isEmpty()) {
- throw new \Exception('Incorrect expression');
- }
-
- return $result;
- }
-} \ No newline at end of file
diff --git a/NXP/Tests/MathTest.php b/NXP/Tests/MathTest.php
deleted file mode 100644
index 6bfcf55..0000000
--- a/NXP/Tests/MathTest.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/**
- * Author: Alexander "NeonXP" Kiryukhin
- * Date: 14.03.13
- * Time: 3:41
- */
-namespace NXP\Tests;
-
-use \NXP\MathExecutor;
-
-class MathTest extends \PHPUnit_Framework_TestCase {
- public function setup()
- {
- require '../MathExecutor.php';
- require '../Classes/Func.php';
- require '../Classes/Operand.php';
- require '../Classes/Token.php';
- require '../Classes/TokenParser.php';
- }
- public function testCalculating()
- {
- $calculator = new MathExecutor();
- for ($i = 1; $i <= 10; $i++) {
- $expression = $this->generateExpression();
- print "Test #$i. Expression: '$expression'\t";
-
- eval('$result1 = ' . $expression . ';');
- print "PHP result: $result1 \t";
- $result2 = $calculator->execute($expression);
- print "NXP Math Executor result: $result2\n";
- $this->assertEquals($result1, $result2);
- }
- }
-
- private function generateExpression()
- {
- $operators = [ '+', '-', '*', '/' ];
- $number = true;
- $expression = '';
- $brackets = 0;
- for ($i = 1; $i < rand(1,10)*2; $i++) {
- if ($number) {
- $expression .= rand(1,100)*0.5;
- } else {
- $expression .= $operators[rand(0,3)];
- }
- $number = !$number;
- $rand = rand(1,5);
- if (($rand == 1) && ($number)) {
- $expression .= '(';
- $brackets++;
- } elseif (($rand == 2) && (!$number) && ($brackets > 0)) {
- $expression .= ')';
- $brackets--;
- }
- }
- if ($number) {
- $expression .= rand(1,100)*0.5;
- }
- $expression .= str_repeat(')', $brackets);
-
- return $expression;
- }
-} \ No newline at end of file