1<?php declare(strict_types=1);
2
3namespace PhpParser;
4
5if (!\function_exists('PhpParser\defineCompatibilityTokens')) {
6    function defineCompatibilityTokens(): void {
7        $compatTokens = [
8            // PHP 8.0
9            'T_NAME_QUALIFIED',
10            'T_NAME_FULLY_QUALIFIED',
11            'T_NAME_RELATIVE',
12            'T_MATCH',
13            'T_NULLSAFE_OBJECT_OPERATOR',
14            'T_ATTRIBUTE',
15            // PHP 8.1
16            'T_ENUM',
17            'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
18            'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
19            'T_READONLY',
20            // PHP 8.4
21            'T_PROPERTY_C',
22            'T_PUBLIC_SET',
23            'T_PROTECTED_SET',
24            'T_PRIVATE_SET',
25        ];
26
27        // PHP-Parser might be used together with another library that also emulates some or all
28        // of these tokens. Perform a sanity-check that all already defined tokens have been
29        // assigned a unique ID.
30        $usedTokenIds = [];
31        foreach ($compatTokens as $token) {
32            if (\defined($token)) {
33                $tokenId = \constant($token);
34                if (!\is_int($tokenId)) {
35                    throw new \Error(sprintf(
36                        'Token %s has ID of type %s, should be int. ' .
37                        'You may be using a library with broken token emulation',
38                        $token, \gettype($tokenId)
39                    ));
40                }
41                $clashingToken = $usedTokenIds[$tokenId] ?? null;
42                if ($clashingToken !== null) {
43                    throw new \Error(sprintf(
44                        'Token %s has same ID as token %s, ' .
45                        'you may be using a library with broken token emulation',
46                        $token, $clashingToken
47                    ));
48                }
49                $usedTokenIds[$tokenId] = $token;
50            }
51        }
52
53        // Now define any tokens that have not yet been emulated. Try to assign IDs from -1
54        // downwards, but skip any IDs that may already be in use.
55        $newTokenId = -1;
56        foreach ($compatTokens as $token) {
57            if (!\defined($token)) {
58                while (isset($usedTokenIds[$newTokenId])) {
59                    $newTokenId--;
60                }
61                \define($token, $newTokenId);
62                $newTokenId--;
63            }
64        }
65    }
66
67    defineCompatibilityTokens();
68}
69