private function buildshifts(PHP_ParserGenerator_State $stp)
    {
//    struct config *cfp;  /* For looping thru the config closure of "stp" */
//    struct config *bcfp; /* For the inner loop on config closure of "stp" */
//    struct config *new;  /* */
//    struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
//    struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
//    struct state *newstp; /* A pointer to a successor state */
    
        /* Each configuration becomes complete after it contibutes to a successor
        ** state.  Initially, all configurations are incomplete */
        $cfp = $stp->cfp;
        for ($cfp = $stp->cfp; $cfp; $cfp = $cfp->next) {
            $cfp->status = PHP_ParserGenerator_Config::INCOMPLETE;
        }
    
        /* Loop through all configurations of the state "stp" */
        for ($cfp = $stp->cfp; $cfp; $cfp = $cfp->next) {
            if ($cfp->status == PHP_ParserGenerator_Config::COMPLETE) {
                continue;    /* Already used by inner loop */
            }
            if ($cfp->dot >= $cfp->rp->nrhs) {
                continue;  /* Can't shift this config */
            }
            PHP_ParserGenerator_Config::Configlist_reset();                      /* Reset the new config set */
            $sp = $cfp->rp->rhs[$cfp->dot];             /* Symbol after the dot */
    
            /* For every configuration in the state "stp" which has the symbol "sp"
            ** following its dot, add the same configuration to the basis set under
            ** construction but with the dot shifted one symbol to the right. */
            $bcfp = $cfp;
            for ($bcfp = $cfp; $bcfp; $bcfp = $bcfp->next) {
                if ($bcfp->status == PHP_ParserGenerator_Config::COMPLETE) {
                    continue;    /* Already used */
                }
                if ($bcfp->dot >= $bcfp->rp->nrhs) {
                    continue; /* Can't shift this one */
                }
                $bsp = $bcfp->rp->rhs[$bcfp->dot];           /* Get symbol after dot */
                if (!PHP_ParserGenerator_Symbol::same_symbol($bsp, $sp)) {
                    continue;      /* Must be same as for "cfp" */
                }
                $bcfp->status = PHP_ParserGenerator_Config::COMPLETE;             /* Mark this config as used */
                $new = PHP_ParserGenerator_Config::Configlist_addbasis($bcfp->rp, $bcfp->dot + 1);
                PHP_ParserGenerator_PropagationLink::Plink_add($new->bplp, $bcfp);
            }

            /* Get a pointer to the state described by the basis configuration set
            ** constructed in the preceding loop */
            $newstp = $this->getstate();
            if (is_array($newstp)) {
                $this->buildshifts($newstp[0]); /* Recursively compute successor states */
                $newstp = $newstp[0];
            }

            /* The state "newstp" is reached from the state "stp" by a shift action
            ** on the symbol "sp" */
            if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) {
                for($i = 0; $i < $sp->nsubsym; $i++) {
                    PHP_ParserGenerator_Action::Action_add($stp->ap, PHP_ParserGenerator_Action::SHIFT, $sp->subsym[$i],
                                            $newstp);
                }
            } else {
                PHP_ParserGenerator_Action::Action_add($stp->ap, PHP_ParserGenerator_Action::SHIFT, $sp, $newstp);
            }
        }
    }