1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Latte;
9:
10:
11: 12: 13:
14: class MacroTokens extends TokenIterator
15: {
16: const T_WHITESPACE = 1,
17: = 2,
18: T_SYMBOL = 3,
19: T_NUMBER = 4,
20: T_VARIABLE = 5,
21: T_STRING = 6,
22: T_CAST = 7,
23: T_KEYWORD = 8,
24: T_CHAR = 9;
25:
26:
27: public $depth = 0;
28:
29:
30: private static $tokenizer;
31:
32:
33: 34: 35:
36: public function __construct($input = [])
37: {
38: parent::__construct(is_array($input) ? $input : $this->parse($input));
39: $this->ignored = [self::T_COMMENT, self::T_WHITESPACE];
40: }
41:
42:
43: public function parse($s)
44: {
45: self::$tokenizer = self::$tokenizer ?: new Tokenizer([
46: self::T_WHITESPACE => '\s+',
47: self::T_COMMENT => '(?s)/\*.*?\*/',
48: self::T_STRING => Parser::RE_STRING,
49: self::T_KEYWORD => '(?:true|false|null|TRUE|FALSE|NULL|INF|NAN|and|or|xor|clone|new|instanceof|return|continue|break)(?![\w\pL_])',
50: self::T_CAST => '\((?:expand|string|array|int|integer|float|bool|boolean|object)\)',
51: self::T_VARIABLE => '\$[\w\pL_]+',
52: self::T_NUMBER => '[+-]?[0-9]+(?:\.[0-9]+)?(?:e[0-9]+)?',
53: self::T_SYMBOL => '[\w\pL_]+(?:-+[\w\pL_]+)*',
54: self::T_CHAR => '::|=>|->|\+\+|--|<<|>>|<=>|<=|>=|===|!==|==|!=|<>|&&|\|\||\?\?|\?>|\*\*|\.\.\.|[^"\']',
55: ], 'u');
56: return self::$tokenizer->tokenize($s);
57: }
58:
59:
60: 61: 62: 63:
64: public function append($val, $position = null)
65: {
66: if ($val != null) {
67: array_splice(
68: $this->tokens,
69: $position === null ? count($this->tokens) : $position,
70: 0,
71: is_array($val) ? [$val] : $this->parse($val)
72: );
73: }
74: return $this;
75: }
76:
77:
78: 79: 80: 81:
82: public function prepend($val)
83: {
84: if ($val != null) {
85: array_splice($this->tokens, 0, 0, is_array($val) ? [$val] : $this->parse($val));
86: }
87: return $this;
88: }
89:
90:
91: 92: 93: 94:
95: public function fetchWord()
96: {
97: $words = $this->fetchWords();
98: return $words ? implode(':', $words) : false;
99: }
100:
101:
102: 103: 104: 105:
106: public function fetchWords()
107: {
108: do {
109: $words[] = $this->joinUntil(self::T_WHITESPACE, ',', ':');
110: } while ($this->nextToken(':'));
111:
112: if (count($words) === 1 && ($space = $this->nextValue(self::T_WHITESPACE))
113: && (($dot = $this->nextValue('.')) || $this->isPrev('.'))) {
114: $words[0] .= $space . $dot . $this->joinUntil(',');
115: }
116: $this->nextToken(',');
117: $this->nextAll(self::T_WHITESPACE, self::T_COMMENT);
118: return $words === [''] ? [] : $words;
119: }
120:
121:
122: public function reset()
123: {
124: $this->depth = 0;
125: return parent::reset();
126: }
127:
128:
129: protected function next()
130: {
131: parent::next();
132: if ($this->isCurrent('[', '(', '{')) {
133: $this->depth++;
134: } elseif ($this->isCurrent(']', ')', '}')) {
135: $this->depth--;
136: }
137: }
138: }
139: