Passed
Push — master ( 26b7be...6fd2c5 )
by Maurício
05:21 queued 02:34
created

ExpressionArray   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 91.11%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 43
dl 0
loc 113
ccs 41
cts 45
cp 0.9111
rs 10
c 1
b 0
f 0
wmc 24

4 Methods

Rating   Name   Duplication   Size   Complexity  
D parse() 0 84 21
A buildAll() 0 3 1
A build() 0 3 1
A __toString() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Components;
6
7
use PhpMyAdmin\SqlParser\Component;
8
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
9
use PhpMyAdmin\SqlParser\Parser;
10
use PhpMyAdmin\SqlParser\Token;
11
use PhpMyAdmin\SqlParser\TokensList;
12
use PhpMyAdmin\SqlParser\Translator;
13
use RuntimeException;
14
15
use function count;
16
use function implode;
17
use function preg_match;
18
use function strlen;
19
use function substr;
20
21
/**
22
 * Parses a list of expressions delimited by a comma.
23
 */
24
final class ExpressionArray implements Component
25
{
26
    /**
27
     * @param Parser               $parser  the parser that serves as context
28
     * @param TokensList           $list    the list of tokens that are being parsed
29
     * @param array<string, mixed> $options parameters for parsing
30
     *
31
     * @return Expression[]
32
     *
33
     * @throws ParserException
34
     */
35 510
    public static function parse(Parser $parser, TokensList $list, array $options = []): array
36
    {
37 510
        $ret = [];
38
39
        /**
40
         * The state of the parser.
41
         *
42
         * Below are the states of the parser.
43
         *
44
         *      0 ----------------------[ array ]---------------------> 1
45
         *
46
         *      1 ------------------------[ , ]------------------------> 0
47
         *      1 -----------------------[ else ]----------------------> (END)
48
         *
49
         * @var int
50
         */
51 510
        $state = 0;
52
53 510
        for (; $list->idx < $list->count; ++$list->idx) {
54
            /**
55
             * Token parsed at this moment.
56
             */
57 510
            $token = $list->tokens[$list->idx];
58
59
            // End of statement.
60 510
            if ($token->type === Token::TYPE_DELIMITER) {
61 232
                break;
62
            }
63
64
            // Skipping whitespaces and comments.
65 504
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
66 388
                continue;
67
            }
68
69
            if (
70 504
                ($token->type === Token::TYPE_KEYWORD)
71 504
                && ($token->flags & Token::FLAG_KEYWORD_RESERVED)
72 504
                && ((~$token->flags & Token::FLAG_KEYWORD_FUNCTION))
73 504
                && ($token->value !== 'DUAL')
74 504
                && ($token->value !== 'NULL')
75 504
                && ($token->value !== 'CASE')
76 504
                && ($token->value !== 'NOT')
77
            ) {
78
                // No keyword is expected.
79 424
                break;
80
            }
81
82 494
            if ($state === 0) {
83 494
                if ($token->type === Token::TYPE_KEYWORD && $token->value === 'CASE') {
84 38
                    $expr = CaseExpression::parse($parser, $list, $options);
85
                } else {
86 492
                    $expr = Expression::parse($parser, $list, $options);
87
                }
88
89 494
                if ($expr === null) {
90 2
                    break;
91
                }
92
93 492
                $ret[] = $expr;
94 492
                $state = 1;
95 192
            } elseif ($state === 1) {
96 192
                if ($token->value !== ',') {
97 20
                    break;
98
                }
99
100 182
                $state = 0;
101
            }
102
        }
103
104 510
        if ($state === 0) {
0 ignored issues
show
introduced by
The condition $state === 0 is always true.
Loading history...
105 20
            $parser->error('An expression was expected.', $list->tokens[$list->idx]);
106
        }
107
108 510
        --$list->idx;
109 510
        $retIndex = count($ret) - 1;
110 510
        if (isset($ret[$retIndex])) {
111 492
            $expr = $ret[$retIndex]->expr;
112 492
            if (preg_match('/\s*--\s.*$/', $expr, $matches)) {
113 4
                $found = $matches[0];
114 4
                $ret[$retIndex]->expr = substr($expr, 0, strlen($expr) - strlen($found));
115
            }
116
        }
117
118 510
        return $ret;
119
    }
120
121
    public function build(): string
122
    {
123
        throw new RuntimeException(Translator::gettext('Not implemented yet.'));
124
    }
125
126
    /**
127
     * @param Expression[] $component the component to be built
128
     */
129 66
    public static function buildAll(array $component): string
130
    {
131 66
        return implode(', ', $component);
132
    }
133
134
    public function __toString(): string
135
    {
136
        return $this->build();
137
    }
138
}
139