xref: /template/mikio/inc/parens-parser.php (revision daf2cd7a0e47fbd8250686479c29e965bf222036)
1*daf2cd7aSJames Collins<?php
2*daf2cd7aSJames Collins
3*daf2cd7aSJames Collins// @rodneyrehm
4*daf2cd7aSJames Collins// http://stackoverflow.com/a/7917979/99923
5*daf2cd7aSJames Collinsclass ParensParser
6*daf2cd7aSJames Collins{
7*daf2cd7aSJames Collins    // something to keep track of parens nesting
8*daf2cd7aSJames Collins    protected $stack = null;
9*daf2cd7aSJames Collins    // current level
10*daf2cd7aSJames Collins    protected $current = null;
11*daf2cd7aSJames Collins
12*daf2cd7aSJames Collins    // input string to parse
13*daf2cd7aSJames Collins    protected $string = null;
14*daf2cd7aSJames Collins    // current character offset in string
15*daf2cd7aSJames Collins    protected $position = null;
16*daf2cd7aSJames Collins    // start of text-buffer
17*daf2cd7aSJames Collins    protected $buffer_start = null;
18*daf2cd7aSJames Collins
19*daf2cd7aSJames Collins    public function parse($string)
20*daf2cd7aSJames Collins    {
21*daf2cd7aSJames Collins        if (!$string) {
22*daf2cd7aSJames Collins            // no string, no data
23*daf2cd7aSJames Collins            return array();
24*daf2cd7aSJames Collins        }
25*daf2cd7aSJames Collins
26*daf2cd7aSJames Collins        if ($string[0] == '[') {
27*daf2cd7aSJames Collins            // killer outer parens, as they're unnecessary
28*daf2cd7aSJames Collins            $string = substr($string, 1, -1);
29*daf2cd7aSJames Collins        }
30*daf2cd7aSJames Collins
31*daf2cd7aSJames Collins        $this->current = array();
32*daf2cd7aSJames Collins        $this->stack = array();
33*daf2cd7aSJames Collins
34*daf2cd7aSJames Collins        $this->string = $string;
35*daf2cd7aSJames Collins        $this->length = strlen($this->string);
36*daf2cd7aSJames Collins        // look at each character
37*daf2cd7aSJames Collins        for ($this->position=0; $this->position < $this->length; $this->position++) {
38*daf2cd7aSJames Collins            switch ($this->string[$this->position]) {
39*daf2cd7aSJames Collins                case '[':
40*daf2cd7aSJames Collins                    $this->push();
41*daf2cd7aSJames Collins                    // push current scope to the stack an begin a new scope
42*daf2cd7aSJames Collins                    array_push($this->stack, $this->current);
43*daf2cd7aSJames Collins                    $this->current = array();
44*daf2cd7aSJames Collins                    break;
45*daf2cd7aSJames Collins
46*daf2cd7aSJames Collins                case ']':
47*daf2cd7aSJames Collins                    $this->push();
48*daf2cd7aSJames Collins                    // save current scope
49*daf2cd7aSJames Collins                    $t = $this->current;
50*daf2cd7aSJames Collins                    // get the last scope from stack
51*daf2cd7aSJames Collins                    $this->current = array_pop($this->stack);
52*daf2cd7aSJames Collins                    // add just saved scope to current scope
53*daf2cd7aSJames Collins                    $this->current[] = $t;
54*daf2cd7aSJames Collins                    break;
55*daf2cd7aSJames Collins               /*
56*daf2cd7aSJames Collins                case ' ':
57*daf2cd7aSJames Collins                    // make each word its own token
58*daf2cd7aSJames Collins                    $this->push();
59*daf2cd7aSJames Collins                    break;
60*daf2cd7aSJames Collins                */
61*daf2cd7aSJames Collins                default:
62*daf2cd7aSJames Collins                    // remember the offset to do a string capture later
63*daf2cd7aSJames Collins                    // could've also done $buffer .= $string[$position]
64*daf2cd7aSJames Collins                    // but that would just be wasting resources…
65*daf2cd7aSJames Collins                    if ($this->buffer_start === null) {
66*daf2cd7aSJames Collins                        $this->buffer_start = $this->position;
67*daf2cd7aSJames Collins                    }
68*daf2cd7aSJames Collins            }
69*daf2cd7aSJames Collins        }
70*daf2cd7aSJames Collins
71*daf2cd7aSJames Collins        return $this->current;
72*daf2cd7aSJames Collins    }
73*daf2cd7aSJames Collins
74*daf2cd7aSJames Collins    protected function push()
75*daf2cd7aSJames Collins    {
76*daf2cd7aSJames Collins        if ($this->buffer_start !== null) {
77*daf2cd7aSJames Collins            // extract string from buffer start to current position
78*daf2cd7aSJames Collins            $buffer = substr($this->string, $this->buffer_start, $this->position - $this->buffer_start);
79*daf2cd7aSJames Collins            // clean buffer
80*daf2cd7aSJames Collins            $this->buffer_start = null;
81*daf2cd7aSJames Collins            // throw token into current scope
82*daf2cd7aSJames Collins            $this->current[] = $buffer;
83*daf2cd7aSJames Collins        }
84*daf2cd7aSJames Collins    }
85*daf2cd7aSJames Collins}
86