/** * Construct the propagation links */ function FindLinks() { /* Housekeeping detail: ** Add to every propagate link a pointer back to the state to ** which the link is attached. */ foreach ($this->sorted as $info) { $info->key->stp = $info->data; } /* Convert all backlinks into forward links. Only the forward ** links are used in the follow-set computation. */ for ($i = 0; $i < $this->nstate; $i++) { $stp = $this->sorted[$i]; for ($cfp = $stp->data->cfp; $cfp; $cfp = $cfp->next) { for ($plp = $cfp->bplp; $plp; $plp = $plp->next) { $other = $plp->cfp; PHP_ParserGenerator_PropagationLink::Plink_add($other->fplp, $cfp); } } } }
/** * Compute the closure of the configuration list. * * This calculates all of the possible continuations of * each configuration, ensuring that each state accounts * for every configuration that could arrive at that state. */ public static function Configlist_closure(PHP_ParserGenerator_Data $lemp) { for ($cfp = self::$current; $cfp; $cfp = $cfp->next) { $rp = $cfp->rp; $dot = $cfp->dot; if ($dot >= $rp->nrhs) { continue; } $sp = $rp->rhs[$dot]; if ($sp->type == PHP_ParserGenerator_Symbol::NONTERMINAL) { if ($sp->rule === 0 && $sp !== $lemp->errsym) { PHP_ParserGenerator::ErrorMsg($lemp->filename, $rp->line, "Nonterminal \"%s\" has no rules.", $sp->name); $lemp->errorcnt++; } for ($newrp = $sp->rule; $newrp; $newrp = $newrp->nextlhs) { $newcfp = self::Configlist_add($newrp, 0); for ($i = $dot + 1; $i < $rp->nrhs; $i++) { $xsp = $rp->rhs[$i]; if ($xsp->type == PHP_ParserGenerator_Symbol::TERMINAL) { $newcfp->fws[$xsp->index] = 1; break; } elseif ($xsp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { for ($k = 0; $k < $xsp->nsubsym; $k++) { $newcfp->fws[$xsp->subsym[$k]->index] = 1; } break; } else { $a = array_diff_key($xsp->firstset, $newcfp->fws); $newcfp->fws += $a; if ($xsp->lambda === false) { break; } } } if ($i == $rp->nrhs) { PHP_ParserGenerator_PropagationLink::Plink_add($cfp->fplp, $newcfp); } } } } }