mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-12-15 19:07:06 +01:00
588e6a4d4c
Scalar\String_ and Scalar\Encapsed now have an additional "kind" attribute, which may be one of: * String_::KIND_SINGLE_QUOTED * String_::KIND_DOUBLE_QUOTED * String_::KIND_NOWDOC * String_::KIND_HEREDOC Additionally, if the string kind is one of the latter two, an attribute "docLabel" is provided, which contains the doc string label (STR in <<<STR) that was originally used. The pretty printer will try to take the original kind of the string, as well as the used doc string label into account.
154 lines
4.4 KiB
PHP
154 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace PhpParser\Node\Scalar;
|
|
|
|
use PhpParser\Error;
|
|
use PhpParser\Node\Scalar;
|
|
|
|
class String_ extends Scalar
|
|
{
|
|
/* For use in "kind" attribute */
|
|
const KIND_SINGLE_QUOTED = 1;
|
|
const KIND_DOUBLE_QUOTED = 2;
|
|
const KIND_HEREDOC = 3;
|
|
const KIND_NOWDOC = 4;
|
|
|
|
/** @var string String value */
|
|
public $value;
|
|
|
|
protected static $replacements = array(
|
|
'\\' => '\\',
|
|
'$' => '$',
|
|
'n' => "\n",
|
|
'r' => "\r",
|
|
't' => "\t",
|
|
'f' => "\f",
|
|
'v' => "\v",
|
|
'e' => "\x1B",
|
|
);
|
|
|
|
/**
|
|
* Constructs a string scalar node.
|
|
*
|
|
* @param string $value Value of the string
|
|
* @param array $attributes Additional attributes
|
|
*/
|
|
public function __construct($value, array $attributes = array()) {
|
|
parent::__construct($attributes);
|
|
$this->value = $value;
|
|
}
|
|
|
|
public function getSubNodeNames() {
|
|
return array('value');
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* Parses a string token.
|
|
*
|
|
* @param string $str String token content
|
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
|
*
|
|
* @return string The parsed string
|
|
*/
|
|
public static function parse($str, $parseUnicodeEscape = true) {
|
|
$bLength = 0;
|
|
if ('b' === $str[0] || 'B' === $str[0]) {
|
|
$bLength = 1;
|
|
}
|
|
|
|
if ('\'' === $str[$bLength]) {
|
|
return str_replace(
|
|
array('\\\\', '\\\''),
|
|
array( '\\', '\''),
|
|
substr($str, $bLength + 1, -1)
|
|
);
|
|
} else {
|
|
return self::parseEscapeSequences(
|
|
substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* Parses escape sequences in strings (all string types apart from single quoted).
|
|
*
|
|
* @param string $str String without quotes
|
|
* @param null|string $quote Quote type
|
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
|
*
|
|
* @return string String with escape sequences parsed
|
|
*/
|
|
public static function parseEscapeSequences($str, $quote, $parseUnicodeEscape = true) {
|
|
if (null !== $quote) {
|
|
$str = str_replace('\\' . $quote, $quote, $str);
|
|
}
|
|
|
|
$extra = '';
|
|
if ($parseUnicodeEscape) {
|
|
$extra = '|u\{([0-9a-fA-F]+)\}';
|
|
}
|
|
|
|
return preg_replace_callback(
|
|
'~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~',
|
|
function($matches) {
|
|
$str = $matches[1];
|
|
|
|
if (isset(self::$replacements[$str])) {
|
|
return self::$replacements[$str];
|
|
} elseif ('x' === $str[0] || 'X' === $str[0]) {
|
|
return chr(hexdec($str));
|
|
} elseif ('u' === $str[0]) {
|
|
return self::codePointToUtf8(hexdec($matches[2]));
|
|
} else {
|
|
return chr(octdec($str));
|
|
}
|
|
},
|
|
$str
|
|
);
|
|
}
|
|
|
|
private static function codePointToUtf8($num) {
|
|
if ($num <= 0x7F) {
|
|
return chr($num);
|
|
}
|
|
if ($num <= 0x7FF) {
|
|
return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80);
|
|
}
|
|
if ($num <= 0xFFFF) {
|
|
return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
|
|
}
|
|
if ($num <= 0x1FFFFF) {
|
|
return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80)
|
|
. chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
|
|
}
|
|
throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* Parses a constant doc string.
|
|
*
|
|
* @param string $startToken Doc string start token content (<<<SMTHG)
|
|
* @param string $str String token content
|
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
|
*
|
|
* @return string Parsed string
|
|
*/
|
|
public static function parseDocString($startToken, $str, $parseUnicodeEscape = true) {
|
|
// strip last newline (thanks tokenizer for sticking it into the string!)
|
|
$str = preg_replace('~(\r\n|\n|\r)\z~', '', $str);
|
|
|
|
// nowdoc string
|
|
if (false !== strpos($startToken, '\'')) {
|
|
return $str;
|
|
}
|
|
|
|
return self::parseEscapeSequences($str, null, $parseUnicodeEscape);
|
|
}
|
|
}
|