Completed
Push — master ( 76acb2...4e56bc )
by Nico
02:11
created

BaseNode::getMethodName()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @license     http://opensource.org/licenses/mit-license.php MIT
7
 * @link        https://github.com/nicoSWD
8
 * @author      Nicolas Oelgart <[email protected]>
9
 */
10
namespace nicoSWD\Rule\TokenStream\Node;
11
12
use Closure;
13
use nicoSWD\Rule\TokenStream\TokenCollection;
14
use nicoSWD\Rule\Parser\Exception\ParserException;
15
use nicoSWD\Rule\Grammar\CallableFunction;
16
use nicoSWD\Rule\TokenStream\TokenStream;
17
use nicoSWD\Rule\TokenStream\Token\TokenType;
18
use nicoSWD\Rule\TokenStream\Token;
19
20
abstract class BaseNode
21
{
22
    /** @var TokenStream */
23
    protected $tokenStream;
24
    /** @var string */
25
    protected $methodName = '';
26
    /** @var int */
27
    protected $methodOffset = 0;
28
29 202
    public function __construct(TokenStream $tokenStream)
30
    {
31 202
        $this->tokenStream = $tokenStream;
32 202
    }
33
34
    abstract public function getNode(): Token\BaseToken;
35
36
    /**
37
     * Looks ahead, but does not move the pointer.
38
     */
39 190
    protected function hasMethodCall(): bool
40
    {
41 190
        $stackClone = $this->tokenStream->getStack()->getClone();
42
43 190
        while ($stackClone->valid()) {
44 190
            $stackClone->next();
45
46 190
            if (!$token = $stackClone->current()) {
47 98
                break;
48 188
            } elseif ($token->isWhitespace()) {
49 144
                continue;
50 188
            } elseif ($token->isOfType(TokenType::METHOD)) {
51 108
                $this->methodName = $token->getValue();
52 108
                $this->methodOffset = $token->getOffset();
53
54 108
                return true;
55
            } else {
56 174
                break;
57
            }
58
        }
59
60 176
        return false;
61
    }
62
63 108
    public function getMethod(Token\BaseToken $token): CallableFunction
64
    {
65 108
        return $this->tokenStream->getMethod($this->getMethodName(), $token);
66
    }
67
68 108
    private function getMethodName(): string
69
    {
70
        do {
71 108
            $this->tokenStream->next();
72 108
        } while ($this->getCurrentNode()->getOffset() < $this->methodOffset);
73
74 108
        return trim(ltrim(rtrim($this->methodName, "\r\n("), '.'));
75
    }
76
77 26
    public function getFunction(): Closure
78
    {
79 26
        return $this->tokenStream->getFunction($this->getFunctionName());
80
    }
81
82 26
    private function getFunctionName(): string
83
    {
84 26
        return rtrim($this->getCurrentNode()->getValue(), " \r\n(");
85
    }
86
87 52
    public function getArrayItems(): TokenCollection
88
    {
89 52
        return $this->getCommaSeparatedValues(TokenType::SQUARE_BRACKET);
90
    }
91
92 124
    public function getArguments(): TokenCollection
93
    {
94 124
        return $this->getCommaSeparatedValues(TokenType::PARENTHESIS);
95
    }
96
97 198
    public function getCurrentNode()
98
    {
99 198
        return $this->tokenStream->getStack()->current();
100
    }
101
102 146
    private function getCommaSeparatedValues(int $stopAt): TokenCollection
103
    {
104 146
        $commaExpected = false;
105 146
        $items = new TokenCollection();
106
107
        do {
108 146
            $this->tokenStream->next();
109
110 146
            if (!$token = $this->tokenStream->current()) {
111 4
                throw new ParserException('Unexpected end of string');
112
            }
113
114 146
            if ($token->getType() & (TokenType::VALUE | TokenType::INT_VALUE)) {
115 122
                if ($commaExpected) {
116 4
                    throw ParserException::unexpectedToken($token);
117
                }
118
119 122
                $commaExpected = true;
120 122
                $items->attach($token);
121 146
            } elseif ($token->isOfType(TokenType::COMMA)) {
122 60
                if (!$commaExpected) {
123 4
                    throw ParserException::unexpectedToken($token);
124
                }
125
126 60
                $commaExpected = false;
127 146
            } elseif ($token->getType() === $stopAt) {
128 130
                break;
129 64
            } elseif (!$token->isWhitespace()) {
130 4
                throw ParserException::unexpectedToken($token);
131
            }
132 122
        } while ($this->tokenStream->valid());
133
134 130
        if (!$commaExpected && $items->count() > 0) {
135 6
            throw new ParserException(sprintf(
136 6
                'Unexpected "," at position %d on line %d',
137 6
                $token->getPosition(),
138 6
                $token->getLine()
139
            ));
140
        }
141
142 124
        $items->rewind();
143
144 124
        return $items;
145
    }
146
}
147