private function step(&$tokenStream, Symbol $symbol, &$parseTreeBranch) { $returnValue = false; $this->depth++; $alternatives = $symbol->getConsistence(); $altChangedSth = false; //iterating over alternatives foreach ($alternatives as $alt) { //iterating over symbols and terminals an alternative consists of $alternativeMatched = true; $first = true; foreach ($alt as $parseElement) { if ($this->debug) { $this->debugOutput(str_repeat(" ", $this->depth) . $this->depth . " " . $parseElement->getName() . " " . get_class($parseElement)); } if (is_a($parseElement, "Terminal")) { if ($parseElement->getName() == "V_e") { //alternative consists of epsilon, so alternative has matched, because alternative and therefore symbol has fullfilled it's destination $alternativeMatched = true; break; } else { if (count($tokenStream) == 0) { if ($first) { //having no more tokens, i say this alternative failes.but it's the first token to check, so let's see if epsilon is produced in another alternative $alternativeMatched = false; break; } else { //uh, I'm in the middle of something? breaking baaaaad. throw new ParserException("I'm through with the Input-Band, i was expecting: " . $parseElement->getName() . ", not good!"); } } //peek on tokenstream, $tokenStream[0] matches terminal->name? if ($parseElement->getName() == $tokenStream[0]['symbol']) { if ($this->debug) { $this->debugOutput(str_repeat(" ", $this->depth) . " FOUND! | " . $this->listTokenString($tokenStream)); } //shift it out $parseTreeBranch[] = array_shift($tokenStream); } else { if ($this->debug) { $this->debugOutput(str_repeat(" ", $this->depth) . " not found! | " . $this->listTokenString($tokenStream)); } //hmm, is first? if ($first) { //let's try another alternative $alternativeMatched = false; break; } else { //i ran in this one...not return, breaking bad throw new ParserException("Unexpected Token: " . $tokenStream[0]['symbol'] . ", Expected: " . $parseElement->getName()); } } } } else { if (is_a($parseElement, "Symbol")) { //get symbol and pass it to new cycle of functioni $mySymbol = $this->symbols[$parseElement->getName()]; $tmpParseTreeBranch = array(); $retVal = $this->step($tokenStream, $mySymbol, $tmpParseTreeBranch); //got a symbol match or not? if yes, break alternative and switch to next one if (!$retVal) { if ($first) { $alternativeMatched = false; break; } else { //i ran in this one...not return, breaking bad throw new ParserException("Expected: " . $parseElement->getName()); } } else { $parseTreeBranch[$parseElement->getName()] = $tmpParseTreeBranch; } } } $first = false; } if ($alternativeMatched) { //current alternative produced a complete match. no need to check other alternatives $returnValue = true; break; } } $this->depth--; return $returnValue; }