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 ]; 21 22 // PHP-Parser might be used together with another library that also emulates some or all 23 // of these tokens. Perform a sanity-check that all already defined tokens have been 24 // assigned a unique ID. 25 $usedTokenIds = []; 26 foreach ($compatTokens as $token) { 27 if (\defined($token)) { 28 $tokenId = \constant($token); 29 if (!\is_int($tokenId)) { 30 throw new \Error(sprintf( 31 'Token %s has ID of type %s, should be int. ' . 32 'You may be using a library with broken token emulation', 33 $token, \gettype($tokenId) 34 )); 35 } 36 $clashingToken = $usedTokenIds[$tokenId] ?? null; 37 if ($clashingToken !== null) { 38 throw new \Error(sprintf( 39 'Token %s has same ID as token %s, ' . 40 'you may be using a library with broken token emulation', 41 $token, $clashingToken 42 )); 43 } 44 $usedTokenIds[$tokenId] = $token; 45 } 46 } 47 48 // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 49 // downwards, but skip any IDs that may already be in use. 50 $newTokenId = -1; 51 foreach ($compatTokens as $token) { 52 if (!\defined($token)) { 53 while (isset($usedTokenIds[$newTokenId])) { 54 $newTokenId--; 55 } 56 \define($token, $newTokenId); 57 $newTokenId--; 58 } 59 } 60 } 61 62 defineCompatibilityTokens(); 63} 64