Parser::parse()   F
last analyzed

Complexity

Conditions 37
Paths 352

Size

Total Lines 231
Code Lines 114

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 114
c 1
b 0
f 0
dl 0
loc 231
rs 1.1466
cc 37
nc 352
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace VLF\VST;
4
5
use \VLF\{
6
    AST,
7
    Stack,
8
    Node
9
};
10
11
/**
12
 * Парсер VST разметки
13
 */
14
class Parser extends \VLF\Parser
15
{
16
    /**
17
     * Парсер AST дерева из VST разметки
18
     * 
19
     * @param string $vst - VST разметка
20
     * 
21
     * @return AST - возвращает AST дерево разметки
22
     */
23
    public static function parse (string $vst): AST
24
    {
25
        $tree    = new AST;
26
        $objects = new Stack;
27
28
        if (file_exists ($vst))
29
            $vst = file_get_contents ($vst);
30
31
        $lines   = explode (self::$divider, $vst);
32
        $skip_at = -1;
33
34
        foreach ($lines as $line_num => $line)
35
        {
36
            // \VoidEngine\pre ($line_num .', '. ($skip_at > $line_num ? 'skip' : 'not skip') .': '. $line);
37
38
            if ($skip_at > $line_num || !self::filter ($line))
39
                continue;
40
41
            $height = self::getHeight ($line);
42
            $words  = array_filter (explode (' ', $line), 'VLF\Parser::filter');
43
            $poped  = false;
44
45
            # Очищаем стек объектов
46
            while ($objects->size () > 0)
47
                if ($objects->current ()->height >= $height)
48
                {
49
                    $objects->pop ();
50
                    
51
                    $poped = true;
52
                }
53
54
                else break;
55
56
            # Создаём новую ссылку на объект
57
            if ($poped && $objects->size () > 0)
58
            {
59
                $object = $objects->pop ();
60
61
                $objects->push (new Node (array_merge ($object->export (), ['nodes' => []])));
62
                $tree->push ($objects->current ());
63
            }
64
65
            /**
66
             * Комментарии
67
             */
68
            if ($words[0][0] == '#')
69
            {
70
                /**
71
                 * Обработка многострочных комментариев
72
                 */
73
                if (isset ($words[0][1]))
74
                {
75
                    if ($words[0][1] == '^')
76
                        $skip_at = self::parseSubtext ($lines, $line_num, $height)[1];
77
78
                    else throw new \Exception ('Unknown char founded after comment definition at line '. ($line_num + 1));
79
                }
80
81
                continue;
82
            }
83
84
            /**
85
             * Создание нового стиля
86
             */
87
            elseif ($words[0][0] == '.')
88
            {
89
                $pos     = strpos ($line, ':');
90
                $parents = null;
91
92
                if ($pos !== false)
93
                {
94
                    $name = trim (substr ($line, 1, $pos - 1));
95
96
                    if (isset ($line[$pos]))
97
                    {
98
                        $parents = trim (substr ($line, $pos + 1));
99
100
                        if (strlen ($parents) == 0)
101
                            $parents = null;
102
103
                        else $parents = array_map ('trim', explode (',', $parents));
104
                    }
105
                }
106
107
                else $name = trim (substr ($line, 1));
108
109
                if ($parents === null && $objects->size () > 0 && $objects->current ()->height < $height)
110
                    $parents = [$objects->current ()->args['name']];
111
112
                $objects->push (new Node ([
113
                    'type'   => \VLF\STYLE_DEFINITION,
114
                    'line'   => $line,
115
                    'words'  => $words,
116
                    'height' => $height,
117
118
                    'args' => [
119
                        'name'       => $name,
120
                        'parents'    => $parents,
121
                        'is_default' => false
122
                    ]
123
                ]));
124
125
                $tree->push ($objects->current ());
126
            }
127
128
            /**
129
             * Создание стиля по умолчанию для класса
130
             */
131
            elseif ($words[0][0] == '*')
132
            {
133
                $pos     = strpos ($line, ':');
134
                $parents = null;
135
136
                if ($pos !== false)
137
                {
138
                    $name = trim (substr ($line, 1, $pos - 1));
139
140
                    if (isset ($line[$pos]))
141
                    {
142
                        $parents = trim (substr ($line, $pos + 1));
143
144
                        if (strlen ($parents) == 0)
145
                            $parents = null;
146
147
                        else $parents = array_map ('trim', explode (',', $parents));
148
                    }
149
                }
150
151
                else $name = trim (substr ($line, 1));
152
153
                if ($parents === null && $objects->size () > 0 && $objects->current ()->height < $height)
154
                    $parents = [$objects->current ()->args['name']];
155
156
                $objects->push (new Node ([
157
                    'type'   => \VLF\STYLE_DEFINITION,
158
                    'line'   => $line,
159
                    'words'  => $words,
160
                    'height' => $height,
161
162
                    'args' => [
163
                        'name'       => $name,
164
                        'parents'    => $parents,
165
                        'is_default' => true
166
                    ]
167
                ]));
168
169
                $tree->push ($objects->current ());
170
            }
171
172
            /**
173
             * Установка свойства
174
             */
175
            elseif (($pos = strpos ($line, ':')) !== false)
176
            {
177
                if ($objects->size () == 0)
178
                    throw new \Exception ('Trying to set property to unknown object at line '. ($line_num + 1));
179
180
                if (!isset ($words[1]))
181
                    throw new \Exception ('Trying to set void property value at line '. ($line_num + 1));
182
183
                $propertyName  = substr ($line, 0, $pos);
184
                $propertyValue = substr ($line, $pos + 1);
185
186
                /**
187
                 * Обработка многострочных свойств
188
                 */
189
                if ($line[$pos + 1] == '^')
190
                {
191
                    $parsed = self::parseSubtext ($lines, $line_num, $height);
192
193
                    $propertyValue = substr ($propertyValue, 1) . $parsed[0];
194
                    $skip_at       = $parsed[1];
195
                }
196
197
                $objects->current ()->push (new Node ([
198
                    'type'   => \VLF\PROPERTY_SET,
199
                    'line'   => $line,
200
                    'words'  => $words,
201
                    'height' => $height,
202
203
                    'args' => [
204
                        'name'  => $propertyName,
205
                        'value' => $propertyValue
206
                    ]
207
                ]));
208
            }
209
210
            /**
211
             * Вызов метода
212
             */
213
            elseif (isset ($words[0][1]) && $words[0][0] == '-' && $words[0][1] == '>')
214
            {
215
                if ($objects->size () == 0)
216
                    throw new \Exception ('Trying to call method from unknown object at line '. ($line_num + 1));
217
218
                $methodArgs = [];
219
220
                if (($pos = strpos ($line, '(')) !== false)
221
                {
222
                    if (($end = strrpos ($line, ')', $pos)) === false)
223
                        throw new \Exception ('Incorrect method arguments syntax at line '. ($line_num + 1));
224
225
                    $methodArgs = substr ($line, $pos + 1, $end - $pos - 1);
226
227
                    $methodName = trim (substr ($line, 2, $pos - 2));
228
                    $methodArgs = self::filter ($methodArgs) ?
229
                        self::parseArguments ($methodArgs) : [];
230
                }
231
232
                else $methodName = trim (substr ($line, 2));
233
234
                $objects->current ()->push (new Node ([
235
                    'type'   => \VLF\METHOD_CALL,
236
                    'line'   => $line,
237
                    'words'  => $words,
238
                    'height' => $height,
239
240
                    'args' => [
241
                        'name' => $methodName,
242
                        'args' => $methodArgs
243
                    ]
244
                ]));
245
            }
246
247
            /**
248
             * Неопознанная структура
249
             */
250
            else throw new \Exception ('Unsupported structure founded at line '. ($line_num + 1));
251
        }
252
253
        return $tree;
254
    }
255
}
256