Completed
Push — master ( 386907...166bd7 )
by Nico
01:52
created

Parser::getExpression()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @license     http://opensource.org/licenses/mit-license.php MIT
7
 * @link        https://github.com/nicoSWD
8
 * @author      Nicolas Oelgart <[email protected]>
9
 */
10
namespace nicoSWD\Rules;
11
12
use nicoSWD\Rules\Expressions\ExpressionFactory;
13
use nicoSWD\Rules\Tokens\BaseToken;
14
use SplStack;
15
16
class Parser
17
{
18
    /** @var AST */
19
    private $ast;
20
21
    /** @var ExpressionFactory */
22
    private $expressionFactory;
23
24
    /** @var Compiler */
25
    private $compiler;
26
27
    /** @var null|BaseToken */
28
    private $operator = null;
29
30 224
    public function __construct(AST $ast, ExpressionFactory $expressionFactory, Compiler $compiler)
31
    {
32 224
        $this->ast = $ast;
33 224
        $this->expressionFactory = $expressionFactory;
34 224
        $this->compiler = $compiler;
35 224
    }
36
37 220
    public function parse(string $rule): string
38
    {
39 220
        $values = new SplStack();
40 220
        $this->compiler->clear();
41 220
        $this->operator = null;
42
43 220
        foreach ($this->ast->getStream($rule) as $token) {
44 182
            switch ($token->getType()) {
45 182
                case TokenType::VALUE:
46 178
                    $values->push($token->getValue());
47 178
                    break;
48 182
                case TokenType::LOGICAL:
49 36
                    $this->compiler->addLogical($token);
50 36
                    continue 2;
51 182
                case TokenType::PARENTHESIS:
52 22
                    $this->compiler->addParentheses($token);
53 20
                    continue 2;
54 182
                case TokenType::OPERATOR:
55 178
                    $this->assignOperator($token, $values);
56 176
                    continue 2;
57 180
                case TokenType::COMMENT:
58 180
                case TokenType::SPACE:
59 178
                    continue 2;
60
                default:
61 6
                    throw Exceptions\ParserException::unknownToken($token);
62
            }
63
64 178
            $this->evaluateExpression($values);
65
        }
66
67 160
        return $this->compiler->getCompiledRule();
68
    }
69
70 178
    private function assignOperator(BaseToken $token, SplStack $values)
71
    {
72 178
        if (isset($this->operator)) {
73 2
            throw Exceptions\ParserException::unexpectedToken($token);
74 178
        } elseif ($values->isEmpty()) {
75 2
            throw Exceptions\ParserException::incompleteExpression($token);
76
        }
77
78 176
        $this->operator = $token;
79 176
    }
80
81 178
    private function evaluateExpression(SplStack $values)
82
    {
83 178
        if (!isset($this->operator) || $values->count() !== 2) {
84 178
            return;
85
        }
86
87 174
        list ($rightValue, $leftValue) = $values;
88
89
        try {
90 174
            $expression = $this->expressionFactory->createFromOperator($this->operator);
91
92 174
            $this->compiler->addBoolean(
93 174
                $expression->evaluate($leftValue, $rightValue)
94
            );
95 4
        } catch (Exceptions\MissingOperatorException $e) {
96 2
            throw new Exceptions\ParserException('Missing operator');
97
        }
98
99 172
        while (!$values->isEmpty()) {
100 172
            $values->pop();
101
        }
102
103 172
        unset($this->operator);
104 172
    }
105
}
106