debug ) { echo ("Enter DFA.predict for decision ".$this->decisionNumber); } $mark = $input->mark(); // remember where decision started in input try { $ret = $this->_predict($input); } catch(Exception $e) { $input->rewind($mark); throw $e; } $input->rewind($mark); return $ret; } public function _predict($input) { $s = 0; // we always start at s0 while ( true ) { if ( $this->debug ) echo ("DFA ".$this->decisionNumber." state ".$s." LA(1)=".$input->LA(1)."(".$input->LA(1)."), index=".$input->index()); $specialState = $this->special[$s]; if ( $specialState>=0 ) { if ( $this->debug ) { echo ("DFA ".$this->decisionNumber. " state ".$s." is special state ".$specialState); } $s = $this->specialStateTransition($specialState, $input); if ( $this->debug ) { echo ("DFA ".$this->decisionNumber. " returns from special state ".$specialState." to ".s); } if ( $s==-1 ) { $this->noViableAlt($s, $input); return 0; } $input->consume(); continue; } if ( $this->accept[$s] >= 1 ) { if ( $this->debug ) echo ("accept; predict "+$this->accept[$s]+" from state "+$this->s); return $this->accept[$s]; } // look for a normal char transition $c = $input->LA(1); // -1 == \uFFFF, all tokens fit in 65000 space if ($c>=$this->min[$s] && $c<=$this->max[$s]) { $snext = $this->transition[$s][$c-$this->min[$s]]; // move to next state if ( $snext < 0 ) { // was in range but not a normal transition // must check EOT, which is like the else clause. // eot[s]>=0 indicates that an EOT edge goes to another // state. if ( $this->eot[$s]>=0 ) { // EOT Transition to accept state? if ( $this->debug ) echo("EOT transition"); $s = $this->eot[$s]; $input->consume(); // TODO: I had this as return accept[eot[s]] // which assumed here that the EOT edge always // went to an accept...faster to do this, but // what about predicated edges coming from EOT // target? continue; } $this->noViableAlt($s,$input); return 0; } $s = $snext; $input->consume(); continue; } if ( $eot[$s]>=0 ) { // EOT Transition? if ( $this->debug ) println("EOT transition"); $s = $this->eot[$s]; $input->consume(); continue; } if ( $c==Token::$EOF && $eof[$s]>=0 ) { // EOF Transition to accept state? if ( $this->debug ) echo ("accept via EOF; predict "+$this->accept[$eof[$s]]+" from "+$eof[$s]); return $this->accept[$eof[$s]]; } // not in range and not EOF/EOT, must be invalid symbol if ( $this->debug ) { echo("min[".$s."]=".$this->min[$s]); echo("max[".$s."]=".$this->max[$s]); echo("eot[".$s."]=".$this->eot[$s]); echo("eof[".$s."]=".$this->eof[$s]); for ($p=0; $p<$this->transition[$s]->length; $p++) { echo $this->transition[$s][$p]+" "; } echo "\n"; } $this->noViableAlt($s, $input); return 0; } } function noViableAlt($s, $input){ if ($this->recognizer->state->backtracking>0) { $this->recognizer->state->failed=true; return; } $nvae = new NoViableAltException($this->getDescription(), $decisionNumber, $s, $input); $this->error($nvae); throw $nvae; } /** A hook for debugging interface */ protected function error($nvae) { ; } function specialStateTransition($s, $input) { return -1; } public function getDescription() { return "n/a"; } /** Given a String that has a run-length-encoding of some unsigned shorts * like "\1\2\3\9", convert to short[] {2,9,9,9}. We do this to avoid * static short[] which generates so much init code that the class won't * compile. :( */ public static function unpackEncodedString($encodedString) { $data = array(); $di = 0; for ($i=0,$len=strlen($encodedString); $i<$len; $i+=2) { $n = charAt($encodedString, $i); $v = charAt($encodedString, $i+1); // add v n times to data for ($j=1; $j<=$n; $j++) { if($v==0xff) $v=-1; $data[$di++] = $v; } } return $data; } function __call($fn, $params){ return call_user_func_array(array($this->recognizer, $fn), $params); } } ?>