Passed
Pull Request — master (#483)
by
unknown
03:01
created

ExpressionArray::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
    /**
122
     * @param ExpressionArray $component
123
     */
124
    public static function build($component): string
125
    {
126
        throw new RuntimeException(Translator::gettext('Not implemented yet.'));
127
    }
128
129
    /**
130
     * @param Expression[] $component the component to be built
131
     */
132 66
    public static function buildAll(array $component): string
133
    {
134 66
        $ret = [];
135 66
        foreach ($component as $frag) {
136 66
            $ret[] = $frag::build($frag);
137
        }
138
139 66
        return implode(', ', $ret);
140
    }
141
142
    public function __toString(): string
143
    {
144
        return static::build($this);
145
    }
146
}
147