comparison vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents c2387f117808
children
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
5 /* 5 /*
6 * This parser is based on a skeleton written by Moriyoshi Koizumi, which in 6 * This parser is based on a skeleton written by Moriyoshi Koizumi, which in
7 * turn is based on work by Masato Bito. 7 * turn is based on work by Masato Bito.
8 */ 8 */
9 use PhpParser\Node\Expr; 9 use PhpParser\Node\Expr;
10 use PhpParser\Node\Expr\Cast\Double;
10 use PhpParser\Node\Name; 11 use PhpParser\Node\Name;
11 use PhpParser\Node\Param; 12 use PhpParser\Node\Param;
13 use PhpParser\Node\Scalar\Encapsed;
12 use PhpParser\Node\Scalar\LNumber; 14 use PhpParser\Node\Scalar\LNumber;
13 use PhpParser\Node\Scalar\String_; 15 use PhpParser\Node\Scalar\String_;
14 use PhpParser\Node\Stmt\Class_; 16 use PhpParser\Node\Stmt\Class_;
15 use PhpParser\Node\Stmt\ClassConst; 17 use PhpParser\Node\Stmt\ClassConst;
16 use PhpParser\Node\Stmt\ClassMethod; 18 use PhpParser\Node\Stmt\ClassMethod;
677 */ 679 */
678 protected function getAttributesAt(int $pos) : array { 680 protected function getAttributesAt(int $pos) : array {
679 return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; 681 return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos];
680 } 682 }
681 683
684 protected function getFloatCastKind(string $cast): int
685 {
686 $cast = strtolower($cast);
687 if (strpos($cast, 'float') !== false) {
688 return Double::KIND_FLOAT;
689 }
690
691 if (strpos($cast, 'real') !== false) {
692 return Double::KIND_REAL;
693 }
694
695 return Double::KIND_DOUBLE;
696 }
697
682 protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { 698 protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) {
683 try { 699 try {
684 return LNumber::fromString($str, $attributes, $allowInvalidOctal); 700 return LNumber::fromString($str, $attributes, $allowInvalidOctal);
685 } catch (Error $error) { 701 } catch (Error $error) {
686 $this->emitError($error); 702 $this->emitError($error);
706 if (!is_int($num)) { 722 if (!is_int($num)) {
707 return new String_($str, $attributes); 723 return new String_($str, $attributes);
708 } 724 }
709 725
710 return new LNumber($num, $attributes); 726 return new LNumber($num, $attributes);
727 }
728
729 protected function stripIndentation(
730 string $string, int $indentLen, string $indentChar,
731 bool $newlineAtStart, bool $newlineAtEnd, array $attributes
732 ) {
733 if ($indentLen === 0) {
734 return $string;
735 }
736
737 $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)';
738 $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])';
739 $regex = '/' . $start . '([ \t]*)(' . $end . ')?/';
740 return preg_replace_callback(
741 $regex,
742 function ($matches) use ($indentLen, $indentChar, $attributes) {
743 $prefix = substr($matches[1], 0, $indentLen);
744 if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) {
745 $this->emitError(new Error(
746 'Invalid indentation - tabs and spaces cannot be mixed', $attributes
747 ));
748 } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) {
749 $this->emitError(new Error(
750 'Invalid body indentation level ' .
751 '(expecting an indentation level of at least ' . $indentLen . ')',
752 $attributes
753 ));
754 }
755 return substr($matches[0], strlen($prefix));
756 },
757 $string
758 );
759 }
760
761 protected function parseDocString(
762 string $startToken, $contents, string $endToken,
763 array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape
764 ) {
765 $kind = strpos($startToken, "'") === false
766 ? String_::KIND_HEREDOC : String_::KIND_NOWDOC;
767
768 $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/';
769 $result = preg_match($regex, $startToken, $matches);
770 assert($result === 1);
771 $label = $matches[1];
772
773 $result = preg_match('/\A[ \t]*/', $endToken, $matches);
774 assert($result === 1);
775 $indentation = $matches[0];
776
777 $attributes['kind'] = $kind;
778 $attributes['docLabel'] = $label;
779 $attributes['docIndentation'] = $indentation;
780
781 $indentHasSpaces = false !== strpos($indentation, " ");
782 $indentHasTabs = false !== strpos($indentation, "\t");
783 if ($indentHasSpaces && $indentHasTabs) {
784 $this->emitError(new Error(
785 'Invalid indentation - tabs and spaces cannot be mixed',
786 $endTokenAttributes
787 ));
788
789 // Proceed processing as if this doc string is not indented
790 $indentation = '';
791 }
792
793 $indentLen = \strlen($indentation);
794 $indentChar = $indentHasSpaces ? " " : "\t";
795
796 if (\is_string($contents)) {
797 if ($contents === '') {
798 return new String_('', $attributes);
799 }
800
801 $contents = $this->stripIndentation(
802 $contents, $indentLen, $indentChar, true, true, $attributes
803 );
804 $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents);
805
806 if ($kind === String_::KIND_HEREDOC) {
807 $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape);
808 }
809
810 return new String_($contents, $attributes);
811 } else {
812 assert(count($contents) > 0);
813 if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) {
814 // If there is no leading encapsed string part, pretend there is an empty one
815 $this->stripIndentation(
816 '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes()
817 );
818 }
819
820 $newContents = [];
821 foreach ($contents as $i => $part) {
822 if ($part instanceof Node\Scalar\EncapsedStringPart) {
823 $isLast = $i === \count($contents) - 1;
824 $part->value = $this->stripIndentation(
825 $part->value, $indentLen, $indentChar,
826 $i === 0, $isLast, $part->getAttributes()
827 );
828 $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape);
829 if ($isLast) {
830 $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value);
831 }
832 if ('' === $part->value) {
833 continue;
834 }
835 }
836 $newContents[] = $part;
837 }
838 return new Encapsed($newContents, $attributes);
839 }
711 } 840 }
712 841
713 protected function checkModifier($a, $b, $modifierPos) { 842 protected function checkModifier($a, $b, $modifierPos) {
714 // Jumping through some hoops here because verifyModifier() is also used elsewhere 843 // Jumping through some hoops here because verifyModifier() is also used elsewhere
715 try { 844 try {