aboutsummaryrefslogtreecommitdiff
path: root/src/NXP/Classes/TokenFactory.php
blob: 924203df5d38daf2e2744bb0bdb2338bff12e32b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
/**
 * This file is part of the MathExecutor package
 *
 * (c) Alexander Kiryukhin
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code
 */

namespace NXP\Classes;

use NXP\Classes\Token\InterfaceToken;
use NXP\Classes\Token\TokenComma;
use NXP\Classes\Token\TokenFunction;
use NXP\Classes\Token\TokenLeftBracket;
use NXP\Classes\Token\TokenNumber;
use NXP\Classes\Token\TokenRightBracket;
use NXP\Exception\UnknownFunctionException;
use NXP\Exception\UnknownOperatorException;
use NXP\Exception\UnknownTokenException;

/**
 * @author Alexander Kiryukhin <alexander@symdev.org>
 */
class TokenFactory
{
    /**
     * Available operators
     *
     * @var array
     */
    protected $operators = array();

    /**
     * Available functions
     *
     * @var array
     */
    protected $functions = array();

    /**
     * @param $name
     * @param $function
     * @param $places
     */
    public function addFunction($name, $function, $places = 1)
    {
        $this->functions[$name] = array($places, $function);
    }

    public function addOperator($operatorClass)
    {
        $class = new \ReflectionClass($operatorClass);

        if (!in_array('NXP\Classes\Token\InterfaceToken', $class->getInterfaceNames())) {
            throw new UnknownOperatorException;
        }

        $this->operators[] = $operatorClass;
        $this->operators = array_unique($this->operators);
    }

    /**
     * @return string
     */
    public function getTokenParserRegex()
    {
        $operatorsRegex = '';
        foreach ($this->operators as $operator) {
            $operatorsRegex .= $operator::getRegex();
        }

        return sprintf(
            '/(%s)|([%s])|(%s)|([%s%s%s])/i',
            TokenNumber::getRegex(),
            $operatorsRegex,
            TokenFunction::getRegex(),
            TokenLeftBracket::getRegex(),
            TokenRightBracket::getRegex(),
            TokenComma::getRegex()
        );
    }

    /**
     * @param  string                $token
     * @return InterfaceToken
     * @throws UnknownTokenException
     */
    public function createToken($token)
    {
        if (is_numeric($token)) {
            return new TokenNumber($token);
        }

        if ($token == '(') {
            return new TokenLeftBracket();
        }

        if ($token == ')') {
            return new TokenRightBracket();
        }

        if ($token == ',') {
            return new TokenComma();
        }

        foreach ($this->operators as $operator) {
            $regex = sprintf('/%s/i', $operator::getRegex());
            if (preg_match($regex, $token)) {
                return new $operator;
            }
        }

        $regex = sprintf('/%s/i', TokenFunction::getRegex());
        if (preg_match($regex, $token)) {
            if (isset($this->functions[$token])) {
                return new TokenFunction($this->functions[$token]);
            } else {
                throw new UnknownFunctionException();
            }
        }
        throw new UnknownTokenException();
    }
}