Passed
Push — master ( 079f1e...99c93a )
by Observer
01:36
created

Parser::parse()   F

Complexity

Conditions 30
Paths 256

Size

Total Lines 186
Code Lines 90

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 90
c 1
b 0
f 0
dl 0
loc 186
rs 2.6333
cc 30
nc 256
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
                    ]
122
                ]));
123
124
                $tree->push ($objects->current ());
125
            }
126
127
            /**
128
             * Установка свойства
129
             */
130
            elseif (($pos = strpos ($line, ':')) !== false)
131
            {
132
                if ($objects->size () == 0)
133
                    throw new \Exception ('Trying to set property to unknown object at line '. ($line_num + 1));
134
135
                if (!isset ($words[1]))
136
                    throw new \Exception ('Trying to set void property value at line '. ($line_num + 1));
137
138
                $propertyName  = substr ($line, 0, $pos);
139
                $propertyValue = substr ($line, $pos + 1);
140
141
                /**
142
                 * Обработка многострочных свойств
143
                 */
144
                if ($line[$pos + 1] == '^')
145
                {
146
                    $parsed = self::parseSubtext ($lines, $line_num, $height);
147
148
                    $propertyValue = substr ($propertyValue, 1) . $parsed[0];
149
                    $skip_at       = $parsed[1];
150
                }
151
152
                $objects->current ()->push (new Node ([
153
                    'type'   => \VLF\PROPERTY_SET,
154
                    'line'   => $line,
155
                    'words'  => $words,
156
                    'height' => $height,
157
158
                    'args' => [
159
                        'name'  => $propertyName,
160
                        'value' => $propertyValue
161
                    ]
162
                ]));
163
            }
164
165
            /**
166
             * Вызов метода
167
             */
168
            elseif (isset ($words[0][1]) && $words[0][0] == '-' && $words[0][1] == '>')
169
            {
170
                if ($objects->size () == 0)
171
                    throw new \Exception ('Trying to call method from unknown object at line '. ($line_num + 1));
172
173
                $methodArgs = [];
174
175
                if (($pos = strpos ($line, '(')) !== false)
176
                {
177
                    if (($end = strrpos ($line, ')', $pos)) === false)
178
                        throw new \Exception ('Incorrect method arguments syntax at line '. ($line_num + 1));
179
180
                    $methodArgs = substr ($line, $pos + 1, $end - $pos - 1);
181
182
                    $methodName = trim (substr ($line, 2, $pos - 2));
183
                    $methodArgs = self::filter ($methodArgs) ?
184
                        self::parseArguments ($methodArgs) : [];
185
                }
186
187
                else $methodName = trim (substr ($line, 2));
188
189
                $objects->current ()->push (new Node ([
190
                    'type'   => \VLF\METHOD_CALL,
191
                    'line'   => $line,
192
                    'words'  => $words,
193
                    'height' => $height,
194
195
                    'args' => [
196
                        'name' => $methodName,
197
                        'args' => $methodArgs
198
                    ]
199
                ]));
200
            }
201
202
            /**
203
             * Неопознанная структура
204
             */
205
            else throw new \Exception ('Unsupported structure founded at line '. ($line_num + 1));
206
        }
207
208
        return $tree;
209
    }
210
}
211