xref: /plugin/combo/vendor/salesforce/handlebars-php/src/Handlebars/Parser.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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