/** * This function handles parsing the beginnings of an open tag. When we see a [ * at an appropriate time, this function is entered. * * @param ElementNode $parent the current parent node * @param Tokenizer $tokenizer the tokenizer we're using * * @return ElementNode the new parent node */ protected function parseTagOpen(ElementNode $parent, Tokenizer $tokenizer) { if (!$tokenizer->hasNext()) { /* The [ that sent us to this state was just a trailing [, not the * opening for a new tag. Treat it as such. */ $this->createTextNode($parent, '['); return $parent; } $next = $tokenizer->next(); /* This while loop could be replaced by a recursive call to this same method, * which would likely be a lot clearer but I decided to use a while loop to * prevent stack overflow with a string like [[[[[[[[[...[[[. */ while ('[' == $next) { /* The previous [ was just a random bracket that should be treated as text. * Continue until we get a non open bracket. */ $this->createTextNode($parent, '['); if (!$tokenizer->hasNext()) { $this->createTextNode($parent, '['); return $parent; } $next = $tokenizer->next(); } if (!$tokenizer->hasNext()) { $this->createTextNode($parent, '[' . $next); return $parent; } $after_next = $tokenizer->next(); $tokenizer->stepBack(); if ($after_next != ']') { $this->createTextNode($parent, '[' . $next); return $parent; } /* At this point $next is either ']' or plain text. */ if (']' == $next) { $this->createTextNode($parent, '['); $this->createTextNode($parent, ']'); return $parent; } else { /* $next is plain text... likely a tag name. */ return $this->parseTag($parent, $tokenizer, $next); } }