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: private static $tokenizer;
28:
29:
30: public $depth = 0;
31:
32:
33: public function __construct($input = [])
34: {
35: parent::__construct(is_array($input) ? $input : $this->parse($input));
36: $this->ignored = [self::T_COMMENT, self::T_WHITESPACE];
37: }
38:
39:
40: public function parse($s)
41: {
42: self::$tokenizer = self::$tokenizer ?: new Tokenizer([
43: self::T_WHITESPACE => '\s+',
44: self::T_COMMENT => '(?s)/\*.*?\*/',
45: self::T_STRING => Parser::RE_STRING,
46: self::T_KEYWORD => '(?:true|false|null|TRUE|FALSE|NULL|INF|NAN|and|or|xor|clone|new|instanceof|return|continue|break)(?![\w\pL_])',
47: self::T_CAST => '\((?:expand|string|array|int|integer|float|bool|boolean|object)\)',
48: self::T_VARIABLE => '\$[\w\pL_]+',
49: self::T_NUMBER => '[+-]?[0-9]+(?:\.[0-9]+)?(?:e[0-9]+)?',
50: self::T_SYMBOL => '[\w\pL_]+(?:-[\w\pL_]+)*',
51: self::T_CHAR => '::|=>|->|\+\+|--|<<|>>|<=>|<=|>=|===|!==|==|!=|<>|&&|\|\||\?\?|\?>|\*\*|\.\.\.|[^"\']',
52: ], 'u');
53: return self::$tokenizer->tokenize($s);
54: }
55:
56:
57: 58: 59: 60:
61: public function append($val, $position = NULL)
62: {
63: if ($val != NULL) {
64: array_splice(
65: $this->tokens,
66: $position === NULL ? count($this->tokens) : $position,
67: 0,
68: is_array($val) ? [$val] : $this->parse($val)
69: );
70: }
71: return $this;
72: }
73:
74:
75: 76: 77: 78:
79: public function prepend($val)
80: {
81: if ($val != NULL) {
82: array_splice($this->tokens, 0, 0, is_array($val) ? [$val] : $this->parse($val));
83: }
84: return $this;
85: }
86:
87:
88: 89: 90: 91: 92:
93: public function fetchWord()
94: {
95: $words = $this->fetchWords();
96: return $words ? implode(':', $words) : FALSE;
97: }
98:
99:
100: 101: 102: 103: 104:
105: public function fetchWords()
106: {
107: do {
108: $words[] = $this->joinUntil(self::T_WHITESPACE, ',', ':');
109: } while ($this->nextToken(':'));
110:
111: if (count($words) === 1 && ($space = $this->nextValue(self::T_WHITESPACE))
112: && (($dot = $this->nextValue('.')) || $this->isPrev('.')))
113: {
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: }
140: