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