1*04fd306cSNickeau<?php 2*04fd306cSNickeau/** 3*04fd306cSNickeau * Handlebars parser (based on mustache) 4*04fd306cSNickeau * 5*04fd306cSNickeau * This class is responsible for turning raw template source into a set of 6*04fd306cSNickeau * Handlebars tokens. 7*04fd306cSNickeau * 8*04fd306cSNickeau * @category Xamin 9*04fd306cSNickeau * @package Handlebars 10*04fd306cSNickeau * @author fzerorubigd <fzerorubigd@gmail.com> 11*04fd306cSNickeau * @author Behrooz Shabani <everplays@gmail.com> 12*04fd306cSNickeau * @author Mardix <https://github.com/mardix> 13*04fd306cSNickeau * @copyright 2012 (c) ParsPooyesh Co 14*04fd306cSNickeau * @copyright 2013 (c) Behrooz Shabani 15*04fd306cSNickeau * @copyright 2013 (c) Mardix 16*04fd306cSNickeau * @license MIT 17*04fd306cSNickeau * @link http://voodoophp.org/docs/handlebars 18*04fd306cSNickeau */ 19*04fd306cSNickeau 20*04fd306cSNickeaunamespace Handlebars; 21*04fd306cSNickeauuse ArrayIterator; 22*04fd306cSNickeauuse LogicException; 23*04fd306cSNickeau 24*04fd306cSNickeauclass Parser 25*04fd306cSNickeau{ 26*04fd306cSNickeau /** 27*04fd306cSNickeau * Process array of tokens and convert them into parse tree 28*04fd306cSNickeau * 29*04fd306cSNickeau * @param array $tokens Set of 30*04fd306cSNickeau * 31*04fd306cSNickeau * @return array Token parse tree 32*04fd306cSNickeau */ 33*04fd306cSNickeau public function parse(Array $tokens = []) 34*04fd306cSNickeau { 35*04fd306cSNickeau return $this->buildTree(new ArrayIterator($tokens)); 36*04fd306cSNickeau } 37*04fd306cSNickeau 38*04fd306cSNickeau /** 39*04fd306cSNickeau * Helper method for recursively building a parse tree. 40*04fd306cSNickeau * 41*04fd306cSNickeau * @param \ArrayIterator $tokens Stream of tokens 42*04fd306cSNickeau * 43*04fd306cSNickeau * @throws \LogicException when nesting errors or mismatched section tags 44*04fd306cSNickeau * are encountered. 45*04fd306cSNickeau * @return array Token parse tree 46*04fd306cSNickeau * 47*04fd306cSNickeau */ 48*04fd306cSNickeau private function buildTree(ArrayIterator $tokens) 49*04fd306cSNickeau { 50*04fd306cSNickeau $stack = []; 51*04fd306cSNickeau 52*04fd306cSNickeau do { 53*04fd306cSNickeau $token = $tokens->current(); 54*04fd306cSNickeau $tokens->next(); 55*04fd306cSNickeau 56*04fd306cSNickeau if ($token === null) { 57*04fd306cSNickeau continue; 58*04fd306cSNickeau } else { 59*04fd306cSNickeau switch ($token[Tokenizer::TYPE]) { 60*04fd306cSNickeau case Tokenizer::T_END_SECTION: 61*04fd306cSNickeau $newNodes = []; 62*04fd306cSNickeau do { 63*04fd306cSNickeau $result = array_pop($stack); 64*04fd306cSNickeau if ($result === null) { 65*04fd306cSNickeau throw new LogicException( 66*04fd306cSNickeau 'Unexpected closing tag: /' . $token[Tokenizer::NAME] 67*04fd306cSNickeau ); 68*04fd306cSNickeau } 69*04fd306cSNickeau 70*04fd306cSNickeau if (!array_key_exists(Tokenizer::NODES, $result) 71*04fd306cSNickeau && isset($result[Tokenizer::NAME]) 72*04fd306cSNickeau && $result[Tokenizer::NAME] == $token[Tokenizer::NAME] 73*04fd306cSNickeau ) { 74*04fd306cSNickeau $result[Tokenizer::NODES] = $newNodes; 75*04fd306cSNickeau $result[Tokenizer::END] = $token[Tokenizer::INDEX]; 76*04fd306cSNickeau array_push($stack, $result); 77*04fd306cSNickeau break 2; 78*04fd306cSNickeau } else { 79*04fd306cSNickeau array_unshift($newNodes, $result); 80*04fd306cSNickeau } 81*04fd306cSNickeau } while (true); 82*04fd306cSNickeau break; 83*04fd306cSNickeau default: 84*04fd306cSNickeau array_push($stack, $token); 85*04fd306cSNickeau } 86*04fd306cSNickeau } 87*04fd306cSNickeau 88*04fd306cSNickeau } while ($tokens->valid()); 89*04fd306cSNickeau 90*04fd306cSNickeau return $stack; 91*04fd306cSNickeau 92*04fd306cSNickeau } 93*04fd306cSNickeau 94*04fd306cSNickeau} 95