Passed
Pull Request — master (#535)
by
unknown
02:55
created

ExpressionArray::buildAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Components\Parsers;
6
7
use PhpMyAdmin\SqlParser\Components\CaseExpression;
8
use PhpMyAdmin\SqlParser\Components\Expression;
9
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
10
use PhpMyAdmin\SqlParser\Parseable;
11
use PhpMyAdmin\SqlParser\Parser;
12
use PhpMyAdmin\SqlParser\Token;
13
use PhpMyAdmin\SqlParser\TokensList;
14
use PhpMyAdmin\SqlParser\TokenType;
15
16
use function count;
17
use function implode;
18
use function preg_match;
19
use function strlen;
20
use function substr;
21
22
/**
23
 * Parses a list of expressions delimited by a comma.
24
 */
25
final class ExpressionArray implements Parseable
26
{
27
    /**
28
     * @param Parser               $parser  the parser that serves as context
29
     * @param TokensList           $list    the list of tokens that are being parsed
30
     * @param array<string, mixed> $options parameters for parsing
31
     *
32
     * @return Expression[]
33
     *
34
     * @throws ParserException
35
     */
36 522
    public static function parse(Parser $parser, TokensList $list, array $options = []): array
37
    {
38 522
        $ret = [];
39
40
        /**
41
         * The state of the parser.
42
         *
43
         * Below are the states of the parser.
44
         *
45
         *      0 ----------------------[ array ]---------------------> 1
46
         *
47
         *      1 ------------------------[ , ]------------------------> 0
48
         *      1 -----------------------[ else ]----------------------> (END)
49
         *
50
         * @var int
51
         */
52 522
        $state = 0;
53
54 522
        for (; $list->idx < $list->count; ++$list->idx) {
55
            /**
56
             * Token parsed at this moment.
57
             */
58 522
            $token = $list->tokens[$list->idx];
59
60
            // End of statement.
61 522
            if ($token->type === TokenType::Delimiter) {
62 234
                break;
63
            }
64
65
            // Skipping whitespaces and comments.
66 516
            if (($token->type === TokenType::Whitespace) || ($token->type === TokenType::Comment)) {
67 392
                continue;
68
            }
69
70
            if (
71 516
                ($token->type === TokenType::Keyword)
72 516
                && ($token->flags & Token::FLAG_KEYWORD_RESERVED)
73 516
                && ((~$token->flags & Token::FLAG_KEYWORD_FUNCTION))
74 516
                && ($token->value !== 'DUAL')
75 516
                && ($token->value !== 'NULL')
76 516
                && ($token->value !== 'CASE')
77 516
                && ($token->value !== 'NOT')
78
            ) {
79
                // No keyword is expected.
80 434
                break;
81
            }
82
83 504
            if ($state === 0) {
84 504
                if ($token->type === TokenType::Keyword && $token->value === 'CASE') {
85 38
                    $expr = CaseExpression::parse($parser, $list, $options);
86
                } else {
87 502
                    $expr = Expression::parse($parser, $list, $options);
88
                }
89
90 504
                if ($expr === null) {
91 2
                    break;
92
                }
93
94 502
                $ret[] = $expr;
95 502
                $state = 1;
96 194
            } elseif ($state === 1) {
97 194
                if ($token->value !== ',') {
98 20
                    break;
99
                }
100
101 184
                $state = 0;
102
            }
103
        }
104
105 522
        if ($state === 0) {
0 ignored issues
show
introduced by
The condition $state === 0 is always true.
Loading history...
106 22
            $parser->error('An expression was expected.', $list->tokens[$list->idx]);
107
        }
108
109 522
        --$list->idx;
110 522
        $retIndex = count($ret) - 1;
111 522
        if (isset($ret[$retIndex])) {
112 502
            $expr = $ret[$retIndex]->expr;
113 502
            if (preg_match('/\s*--\s.*$/', $expr, $matches)) {
114 4
                $found = $matches[0];
115 4
                $ret[$retIndex]->expr = substr($expr, 0, strlen($expr) - strlen($found));
116
            }
117
        }
118
119 522
        return $ret;
120
    }
121
122
    /** @param Expression[] $component the component to be built */
123 66
    public static function buildAll(array $component): string
124
    {
125 66
        return implode(', ', $component);
126
    }
127
}
128