1: <?php
2:
3: namespace BN\Compiler\Postfix;
4:
5: use BN\Collections\Queue;
6: use BN\Compiler\Token\Token;
7: use BN\Compiler\Token\TokenType;
8: use BN\Compiler\Grammar\Operators;
9: use BN\Compiler\Postfix\Token\ProcessValue;
10: use BN\Compiler\Postfix\Token\ProcessOperator;
11: use BN\Compiler\Postfix\Token\ProcessUnknown;
12: use BN\Compiler\Postfix\Token\ProcessAssign;
13: use BN\Compiler\Postfix\Token\ProcessConstant;
14:
15: class PostfixEvaluator
16: {
17: private $accumulator;
18: private $calculators;
19: private $tokensQueue;
20: private $variables;
21:
22: public function __construct(CalculatorErrorHandler $errorHandler, Operators $operators, array $constants)
23: {
24: $this->variables = new Variables();
25: $this->accumulator = new StackAccumulator($errorHandler);
26: $processValue = new ProcessValue($this->accumulator);
27: $this->calculators = array(
28: TokenType::NUMBER => $processValue,
29: TokenType::VARIABLE => $processValue,
30: TokenType::CONSTANT => new ProcessConstant($this->accumulator, $constants),
31: TokenType::ASSIGN => new ProcessAssign($this->accumulator, $this->variables),
32: TokenType::OPERATOR => new ProcessOperator($this->accumulator, $operators, $this->variables),
33: TokenType::UNKNOWN => new ProcessUnknown($this->accumulator)
34: );
35: }
36:
37: public function evaluate(Queue $queue, \stdClass $variables)
38: {
39: $this->prepareEvaluator($queue, $variables);
40: while ($this->isTokenInQueue()) {
41: $this->readNextToken();
42: }
43: return $this->evaluateResult();
44: }
45:
46: private function prepareEvaluator($queue, $variables)
47: {
48: $this->accumulator->init();
49: $this->tokensQueue = $queue;
50: $this->variables->setVariables($variables);
51: }
52:
53: private function isTokenInQueue()
54: {
55: return !$this->tokensQueue->isEmpty() && $this->accumulator->continueInCalculation();
56: }
57:
58: private function readNextToken()
59: {
60: $token = $this->tokensQueue->pop();
61: $p = $this->getProcessor($token);
62: $p->process($token);
63: }
64:
65: private function getProcessor(Token $token)
66: {
67: if (array_key_exists($token->type, $this->calculators)) {
68: return $this->calculators[$token->type];
69: } else {
70: return $this->calculators[TokenType::UNKNOWN];
71: }
72: }
73:
74: private function evaluateResult()
75: {
76: return $this->accumulator->getResult();
77: }
78: }
79: