9
votes

Génération de code PHP (des jetons d'analyseurs)


3 commentaires

Est-ce que quelqu'un voit un problème potentiel, si j'écris simplement une instruction de commutation volumineuse pour convertir les jetons de reconstitution à leurs représentations de chaîne (c'est-à-dire T_DO à «faire»), cartographiez sur les jetons, rejoignez des espaces et recherchez une sorte de code PHP. Solution jolie imprimante?


Si tout ce que vous voulez qu'il fasse, c'est de la jolie imprimée, cela fonctionnera en quelque sorte. Vous découvrirez que la régénération des nombres de points flottants et des chaînes littérales est plus de sueur que prévu. Mais la vraie question est, où avez-vous obtenu la corde de jeton que vous souhaitez imprimer? Vraisemblablement, vous lisez du programme existant et vous en apportez des modifications. Dans ce cas, vous trouverez que vous avez besoin de beaucoup plus de machines à analyser, de déterminer les tables de symboles, de l'analyse de flux, ou autre chose.


Oui, j'ai compris que cela assez rapidement. Néanmoins, ça me donne un lexer, ce qui fait, bien, quelque chose ...


4 Réponses :


2
votes

de mon commentaire:

Est-ce que quelqu'un voit un problème potentiel, Si je dis simplement un grand commutateur déclaration pour convertir les jetons de retour à leurs représentations de chaîne (c'est-à-dire T_do à 'faire'), cartographique que sur le jetons, rejoignez des espaces et cherchez une sorte de code PHP jolie-impression solution? p> blockQuote>

Après avoir cherché, j'ai trouvé une solution de PHP maison dans Cette question, qui utilise réellement l'interface de Tokenizer PHP, ainsi que certains outils de mise en forme de code PHP plus configurables (mais nécessiteraient la solution comme décrit ci-dessus). P>

ces pourrait être utilisé pour réaliser rapidement une solution. Je posterai ici lorsque je trouve un peu de temps pour cuisiner ça. P>


solution avec php_beautifier h2>

C'est la solution rapide que j'ai cuisinée, je vais le laisser ici dans le cadre de la question. Notez que cela vous oblige à ouvrir la classe PHP_Beautififier, en changeant tout (probablement pas tout, mais c'est plus facile) qui est privé em> à protégé em> pour vous permettre de Utilisez les fonctionnages internes de php_bâtainifier (sinon il était impossible de réutiliser la fonctionnalité de php_beautifiant sans réimplémenter la moitié de leur code). P>

Un exemple d'utilisation de la classe serait: p>

Fichier: Main.PHP CODE> P>

class PHP2PHP extends PHP_Beautifier {

  function php2token($phpCode) {
    return token_get_all($phpCode);
  }

  function token2php(array $phpToken) {

    // prepare properties
    $this->resetProperties();
    $this->aTokens = $phpToken;
    $iTotal        = count($this->aTokens);
    $iPrevAssoc    = false;

    // send a signal to the filter, announcing the init of the processing of a file
    foreach($this->aFilters as $oFilter)
      $oFilter->preProcess();

    for ($this->iCount = 0;
         $this->iCount < $iTotal;
         $this->iCount++) {
      $aCurrentToken = $this->aTokens[$this->iCount];
      if (is_string($aCurrentToken))
        $aCurrentToken = array(
          0 => $aCurrentToken,
          1 => $aCurrentToken
        );

      // ArrayNested->off();
      $sTextLog = PHP_Beautifier_Common::wsToString($aCurrentToken[1]);

      // ArrayNested->on();
      $sTokenName = (is_numeric($aCurrentToken[0])) ? token_name($aCurrentToken[0]) : '';
      $this->oLog->log("Token:" . $sTokenName . "[" . $sTextLog . "]", PEAR_LOG_DEBUG);
      $this->controlToken($aCurrentToken);
      $iFirstOut           = count($this->aOut); //5
      $bError              = false;
      $this->aCurrentToken = $aCurrentToken;
      if ($this->bBeautify) {
        foreach($this->aFilters as $oFilter) {
          $bError = true;
          if ($oFilter->handleToken($this->aCurrentToken) !== FALSE) {
            $this->oLog->log('Filter:' . $oFilter->getName() , PEAR_LOG_DEBUG);
            $bError = false;
            break;
          }
        }
      } else {
        $this->add($aCurrentToken[1]);
      }
      $this->controlTokenPost($aCurrentToken);
      $iLastOut = count($this->aOut);
      // set the assoc
      if (($iLastOut-$iFirstOut) > 0) {
        $this->aAssocs[$this->iCount] = array(
          'offset' => $iFirstOut
        );
        if ($iPrevAssoc !== FALSE)
          $this->aAssocs[$iPrevAssoc]['length'] = $iFirstOut-$this->aAssocs[$iPrevAssoc]['offset'];
        $iPrevAssoc = $this->iCount;
      }
      if ($bError)
        throw new Exception("Can'process token: " . var_dump($aCurrentToken));
    } // ~for

    // generate the last assoc
    if (count($this->aOut) == 0)
        throw new Exception("Nothing on output!");

    $this->aAssocs[$iPrevAssoc]['length'] = (count($this->aOut) -1) - $this->aAssocs[$iPrevAssoc]['offset'];

    // post-processing
    foreach($this->aFilters as $oFilter)
      $oFilter->postProcess();
    return $this->get();
  }
}
?>


1 commentaires

@Kirzilla: Je ne suis pas tout à fait sûr de ce que vous essayez d'accomplir, mais si vous voulez travailler sur une PHP Ast, avez-vous essayé d'utiliser la php-analyseur de Nikic? Il vous donne une totalité des jetons AST (pas seulement) et est maintenu par un développeur de base PHP. Voir cette question: Stackoverflow.com / Questions / 5586358 / ... .



1
votes

Si je ne me trompe pas http://pear.php.net/package/php_beautififier Utilise TOKEN_GET_ALL (), puis réécrire le flux. Il utilise des tas de méthodes tels que t_else et t_close_brace pour sortir chaque jeton. Peut-être que vous pouvez détourner cela pour la simplicité.


1 commentaires

J'ai fini par faire cela pendant un moment et cela a fonctionné, bien que php_bâtainifier soit assez difficile à étendre à cette fin et m'a forcé à ouvrir certaines méthodes.



-2
votes

Voir notre PHP Front Fin . Il s'agit d'un analyseur PHP complet, de construction automatiquement des asts et d'une jolie empreinte correspondante qui régénère le code PHP compilable complet avec les crédits originaux. (Modifier le 12/2011: Voir ceci afin de répondre à plus de détails sur ce qu'il faut à Prettyprint des asts, qui ne sont qu'une version organisée des jetons: HTTPS: // Stackoverflow.com/a/5834775/120163 )

Le front-end est construit sur notre Toolkit de réengagement logiciel DMS , Activation de l'analyse et de la transformation des asts PHP (puis via le code PrettyPrinter).


8 commentaires

Est-ce que quelque chose équivalent à la boîte à outils DMS disponible comme source ouverte? Ceci est plutôt cher pour un projet de jouet. ^^


@Pepijn: Les choses les plus proches des DMS sont Stratego / XT et TXL. Ils ont tous deux des analyseurs, construisent AST et peuvent régénérer le code. Stratego / XT May a un analyseur PHP, mais je ne sais pas à quel point cela est robuste, et cela compte parce que PHP est vraiment mal documenté la langue (l'analyseur PHP de DMS a traversé des millions de lignes de PHP; son joli solide). Je ne pense pas que TXL a un analyseur PHP complet. AntlR analyse et peut construire des asts avec des efforts supplémentaires; Il n'a pas de jolie imprimante spécifique que je connaisse. ...


@Pepijn: ... Vous devriez constater que vous pourrez peut-être obtenir quelque chose qui commence à se rapprocher de ce que DMS fait, mais vous devrez probablement reproduire la pièce qui manque (grammaire PHP précise? Prettyprinter? Moteurs de support d'analyse?. ..). Au moment où vous faites cela, vous découvrirez IMHO que les versions open source sont plus chères que la DMS au moins si vous pensez que votre temps n'est pas un coût nul. Les gens m'accuseront à battre mon propre tambour ici, et Je suis d'accord avec eux . Il est difficile de reproduire 15 ans d'ingénierie continue et sans parler des 10 années de concepts sur lesquelles la DMS est basée.


@Ira: Je suis pleinement d'accord avec vous à ce sujet et devrais-je avoir besoin de quelque chose comme celui-ci pour un projet d'entreprise (avec un objectif clair à l'esprit), je vais certainement considérer les DMS; Cependant, à ce jour, je suis toujours étudiant et mon objectif à l'esprit est d'apprendre. Ainsi, la mise en œuvre de cette version (même une version semi-assée de celle-ci) m'apportera probablement plus dans l'expérience que d'acheter et de jouer avec le DMS. Néanmoins, merci; On dirait que c'est un excellent produit. (Vous devriez noter que bien que ma question soit liée à PHP, mon intérêt était en fait de la langue continue.)


@Ira: En outre, je pense que la réponse acceptée reflète mieux la question initiale de la demande, et est donc plus en ligne avec les objectifs du débordement de la pile.


@Pepjin: En tant qu'étudiant, ce que je vous suggère de faire, c'est aller TXL et jouer avec elle à l'aide de l'analyseur Java / Prettyprinter, ils ont. L'analyse et la jolie empreinte ne sont pas la partie intéressante du problème . Ils sont plutôt comme l'ante au pot du poker; Vous devez le faire pour jouer, mais Anteing est facile, sa lecture de la main est difficile et conduit à gagner des résultats. Ce que vous devez faire et que vous puissiez faire, avec un programme analysé est la chose que vous souhaitez dépenser de l'énergie. TXL Plus son analyseur Java vous laissera faire cela. Si vous voulez le faire avec PHP, vous avez besoin de plus de machines matures comme DMS.


@Pepjin: ... et oui, je suis d'accord, si vous limitez la question à la façon dont vous avez posée la question, la réponse que vous avez choisie comme acceptée est la meilleure.


@Pepjin: Pour des fins comparatives "Prettyimtrinting", vous pourriez envisager de comparer votre solution avec le prettyprinter fourni dans le cadre de l'exemple pour une langue assez simple ("algèbre") pour DMS à SEMDESIGNS.COM/PRODUCTS/DMS/SIMPLEDMSDOMAINEXAML.HTML L'exemple montre également le reste de la" main poker ", c'est-à-dire la manipulation du résultat analysé d'une manière qui obtient des réponses intéressantes.