Lexer   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 115
Duplicated Lines 26.96 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 27
c 2
b 1
f 0
lcom 0
cbo 1
dl 31
loc 115
ccs 76
cts 76
cp 1
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
D parse() 31 106 27

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * ExpressionParser.php
5
 *
6
 * @date 28.03.2015 1:03:37
7
 * @copyright Sklyarov Alexey <[email protected]>
8
 */
9
10
namespace Sufir\Calc;
11
12
use InvalidArgumentException;
13
use Sufir\Calc\Token;
14
use Sufir\Calc\Token\TokenFactory;
15
16
/**
17
 * ExpressionParser
18
 *
19
 * Description of ExpressionParser
20
 *
21
 * @todo Multibyte encoding support.
22
 * @author Sklyarov Alexey <[email protected]>
23
 * @package Sufir\Calc
24
 */
25
class Lexer
26
{
27
    /**
28
     * Разбивает переданную строку на токены
29
     *
30
     * @param string $expr
31
     * @return Token[]
32
     */
33 35
    public function parse($expr)
34
    {
35 35
        if (!is_string($expr) || strlen($expr) < 1) {
36 2
            throw new InvalidArgumentException('Wrong expression');
37
        }
38
39 33
        $stack = array();
40 33
        $tokenFactory = new TokenFactory();
41 33
        $lastToken = '';
42 33
        $lastTokenType = null;
43
44 33
        for ($i = 0; $i < mb_strlen($expr); $i++) {
45 33
            $char = $expr[$i];
46
47
            // Скобки
48 33
            if ($char === '(' || $char === ')') {
49 22
                if ($lastTokenType) {
50 22
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
51 22
                }
52
53 22
                $lastTokenType = Token::TYPE_BRACKET;
54 22
                $lastToken = $char;
55
56
            // Разделители параметров функции
57 33
            } elseif ($char === ',') {
58 7
                if ($lastTokenType) {
59 7
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
60 7
                }
61
62 7
                $lastTokenType = Token::TYPE_DELIMITER;
63 7
                $lastToken = $char;
64
65 33
            } elseif ($char === '-') {
66
                // Если предыдущий токен не число и не закрывающая скобка,
67
                // то минус означает отрицательное число
68 11
                if (!$lastTokenType) {
69 3
                    $lastTokenType = Token::TYPE_NUMBER;
70 3
                } elseif ($lastTokenType === Token::TYPE_NUMBER
71 11
                    || $lastToken === ')'
72 11
                ) {
73 11
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
74 11
                    $lastTokenType = Token::TYPE_OPERATOR;
75 11
                } else {
76 3
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
77 3
                    $lastTokenType = Token::TYPE_NUMBER;
78
                }
79
80 11
                $lastToken = $char;
81
82 33
            } elseif (preg_match("/[\+\*\/\^]+/i", $char)) {
83 27
                if ($lastTokenType) {
84 27
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
85 27
                }
86
87 27
                $lastTokenType = Token::TYPE_OPERATOR;
88 27
                $lastToken = $char;
89
90
            // Начало переменной
91 33
            } elseif ($char === '$') {
92 11
                if (!$lastTokenType) {
93 6
                    $lastTokenType = Token::TYPE_VARIABLE;
94 6
                    $lastToken = $char;
95 6
                } else {
96 10
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
97 10
                    $lastTokenType = Token::TYPE_VARIABLE;
98 10
                    $lastToken = $char;
99
                }
100
101
            // Буквы a-z, A-Z или символ подчеркивания
102
            // (могут использоваться в именах переменных и функций)
103 33 View Code Duplication
            } elseif (preg_match("/[a-zA-Z\_]+/i", $char)) {
104 25
                if (!$lastTokenType) {
105 11
                    $lastTokenType = Token::TYPE_FUNCTION;
106 11
                    $lastToken = $char;
107 11
                } elseif ($lastTokenType === Token::TYPE_FUNCTION
108 25
                    || $lastTokenType === Token::TYPE_VARIABLE
109 25
                ) {
110 25
                    $lastToken .= $char;
111 25
                } else {
112 11
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
113 11
                    $lastTokenType = Token::TYPE_FUNCTION;
114 11
                    $lastToken = $char;
115
                }
116
117
            // Числа
118 33
            } elseif (is_numeric($char) || $char === '.') {
119 32 View Code Duplication
                if (!$lastTokenType) {
120 10
                    $lastTokenType = Token::TYPE_NUMBER;
121 10
                    $lastToken = $char;
122 10
                } elseif ($lastTokenType === Token::TYPE_NUMBER
123 32
                    || $lastTokenType === Token::TYPE_VARIABLE
124 32
                    || $lastTokenType === Token::TYPE_FUNCTION
125 32
                ) {
126 14
                    $lastToken .= $char;
127 14
                } else {
128 32
                    $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
129 32
                    $lastTokenType = Token::TYPE_NUMBER;
130 32
                    $lastToken = $char;
131
                }
132 32
            }
133 33
        }
134
135 33
        $stack[] = $tokenFactory->create($lastTokenType, $lastToken);
136
137 32
        return $stack;
138
    }
139
}
140