Parser::checkObjectHasOpenBracket()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 4
nc 2
nop 1
crap 4
1
<?php
2
/**
3
 * Copyright (C) 2013-2020
4
 * Piotr Olaszewski <[email protected]>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24
namespace WSDL\Parser;
25
26
use Ouzo\Utilities\Strings;
27
use WSDL\Lexer\Token;
28
use WSDL\Lexer\TokenObject;
29
30
/**
31
 * Parser
32
 *
33
 * @author Piotr Olaszewski <[email protected]>
34
 *
35
 * Grammar:
36
 *
37
 * S -> P
38
 * P -> T R I
39
 * I -> P
40
 * I -> e
41
 * R -> '[]' N O
42
 * R -> N O
43
 * O -> '{' P '}'
44
 * O -> e
45
 * N -> 'token_name'
46
 * T -> 'token_type'
47
 */
48
class Parser
49
{
50
    const OBJECT_TYPE = 'object';
51
52
    /**
53
     * @var TokenObject[]
54
     */
55
    private $tokens;
56
    /**
57
     * @var int
58
     */
59
    private $position;
60
61
    /**
62
     * @param TokenObject[] $tokens
63
     */
64 25
    public function __construct(array $tokens)
65
    {
66 25
        $this->tokens = $tokens;
67 25
        $this->position = 0;
68 25
    }
69
70
    /**
71
     * @return Node[]
72
     */
73 25
    public function S(): array
74
    {
75 25
        return $this->P();
76
    }
77
78 25
    /**
79
     * @return Node[]
80 25
     */
81 23
    private function P(): array
82 18
    {
83 17
        $type = $this->T();
84 17
        list($isArray, $name, $elements) = $this->R();
85 17
        $nodes = $this->I();
86
        $node = new Node($type, $name, $isArray, $elements);
87
        array_unshift($nodes, $node);
88 25
89
        return $nodes;
90 25
    }
91 25
92 23
    private function T(): string
93
    {
94 3
        $token = $this->shift();
95
        if ($token->getName() == Token::TYPE) {
96
            return $token->getValue();
97 23
        }
98
        throw new ParserException('Wrong type');
99 23
    }
100 10
101 10
    private function R(): array
102 10
    {
103 10
        if ($this->lookahead()->getName() == Token::ARRAYS) {
104 10
            $this->shift();
105 20
            $name = $this->N();
106 18
            $elements = $this->O();
107 15
            $isArray = true;
108
        } else {
109 18
            $name = $this->N();
110
            $elements = $this->O();
111
            $isArray = false;
112 18
        }
113
114 18
        return [$isArray, $name, $elements];
115 11
    }
116
117 17
    /**
118
     * @return Node[]
119
     */
120 23
    private function I(): array
121
    {
122 23
        if ($this->lookahead()->getName() != Token::EOF && $this->lookahead()->getName() != Token::CLOSE_OBJECT) {
123 23
            return $this->P();
124 21
        }
125
126 3
        return [];
127
    }
128
129 21
    private function N(): string
130
    {
131 21
        $token = $this->shift();
132 21
        if (in_array($token->getName(), [Token::NAME, Token::CLASS_NAME])) {
133 20
            return $token->getValue();
134 15
        }
135 15
        throw new ParserException('Wrong name');
136 12
    }
137 11
138
    /**
139 18
     * @return Node[]
140
     */
141
    private function O(): array
142 21
    {
143
        $token = $this->lookahead();
144 21
        $this->checkObjectHasOpenBracket($token);
145 21
        if ($token->getName() == Token::OPEN_OBJECT) {
146 2
            $this->shift();
147
            $node = $this->P();
148 20
            $this->checkObjectHasCloseBracket();
149
150 12
            return $node;
151
        }
152 12
153 12
        return [];
154 2
    }
155
156 11
    private function checkObjectHasOpenBracket(TokenObject $token): void
157
    {
158 25
        $tokenObject = $this->lookAt(($this->position - 2));
159
        if ($tokenObject && Strings::equalsIgnoreCase($tokenObject->getValue(), self::OBJECT_TYPE) && $token->getName() != Token::OPEN_OBJECT) {
160 25
            throw new ParserException('Missing open object');
161
        }
162
    }
163 21
164
    private function checkObjectHasCloseBracket(): void
165 21
    {
166
        $token = $this->shift();
167
        if ($token->getName() != Token::CLOSE_OBJECT) {
168 25
            throw new ParserException('Missing close object');
169
        }
170 25
    }
171 25
172 25
    private function lookahead(): TokenObject
173
    {
174
        return $this->tokens[$this->position];
175
    }
176
177
    private function lookAt($position): TokenObject
178
    {
179
        return $this->tokens[$position];
180
    }
181
182
    private function shift(): TokenObject
183
    {
184
        $token = $this->lookahead();
185
        $this->position++;
186
187
        return $token;
188
    }
189
}
190