vendor/twig/twig/src/TokenStream.php line 28

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) Fabien Potencier
  6. * (c) Armin Ronacher
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Twig;
  12. use Twig\Error\SyntaxError;
  13. /**
  14. * Represents a token stream.
  15. *
  16. * @author Fabien Potencier <fabien@symfony.com>
  17. */
  18. final class TokenStream
  19. {
  20. private $tokens;
  21. private $current = 0;
  22. private $source;
  23. public function __construct(array $tokens, Source $source = null)
  24. {
  25. $this->tokens = $tokens;
  26. $this->source = $source ?: new Source('', '');
  27. }
  28. public function __toString()
  29. {
  30. return implode("\n", $this->tokens);
  31. }
  32. public function injectTokens(array $tokens)
  33. {
  34. $this->tokens = array_merge(\array_slice($this->tokens, 0, $this->current), $tokens, \array_slice($this->tokens, $this->current));
  35. }
  36. /**
  37. * Sets the pointer to the next token and returns the old one.
  38. */
  39. public function next(): Token
  40. {
  41. if (!isset($this->tokens[++$this->current])) {
  42. throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source);
  43. }
  44. return $this->tokens[$this->current - 1];
  45. }
  46. /**
  47. * Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
  48. *
  49. * @return Token|null The next token if the condition is true, null otherwise
  50. */
  51. public function nextIf($primary, $secondary = null)
  52. {
  53. if ($this->tokens[$this->current]->test($primary, $secondary)) {
  54. return $this->next();
  55. }
  56. }
  57. /**
  58. * Tests a token and returns it or throws a syntax error.
  59. */
  60. public function expect($type, $value = null, string $message = null): Token
  61. {
  62. $token = $this->tokens[$this->current];
  63. if (!$token->test($type, $value)) {
  64. $line = $token->getLine();
  65. throw new SyntaxError(sprintf('%sUnexpected token "%s"%s ("%s" expected%s).',
  66. $message ? $message.'. ' : '',
  67. Token::typeToEnglish($token->getType()),
  68. $token->getValue() ? sprintf(' of value "%s"', $token->getValue()) : '',
  69. Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
  70. $line,
  71. $this->source
  72. );
  73. }
  74. $this->next();
  75. return $token;
  76. }
  77. /**
  78. * Looks at the next token.
  79. */
  80. public function look(int $number = 1): Token
  81. {
  82. if (!isset($this->tokens[$this->current + $number])) {
  83. throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source);
  84. }
  85. return $this->tokens[$this->current + $number];
  86. }
  87. /**
  88. * Tests the current token.
  89. */
  90. public function test($primary, $secondary = null): bool
  91. {
  92. return $this->tokens[$this->current]->test($primary, $secondary);
  93. }
  94. /**
  95. * Checks if end of stream was reached.
  96. */
  97. public function isEOF(): bool
  98. {
  99. return /* Token::EOF_TYPE */ -1 === $this->tokens[$this->current]->getType();
  100. }
  101. public function getCurrent(): Token
  102. {
  103. return $this->tokens[$this->current];
  104. }
  105. /**
  106. * Gets the source associated with this stream.
  107. *
  108. * @internal
  109. */
  110. public function getSourceContext(): Source
  111. {
  112. return $this->source;
  113. }
  114. }
  115. class_alias('Twig\TokenStream', 'Twig_TokenStream');