PC & Mobile

Manipuler AST avec JavaScript – JavaScript en anglais simple

Manipuler AST avec JavaScript - JavaScript en anglais simple


Auparavant, j'ai parlé de la façon d'écrire une transformation babel, et je suis allé un peu plus loin dans Babel, en montrant comment vous pouvez créer une syntaxe JavaScript personnalisée, j'ai montré comment Babel analyse votre code en AST, le transforme et génère de nouveau en code.

Armés des connaissances et de l'expérience de la lecture de l'AST JavaScript avec Babel, voyons comment nous pouvons également généraliser ces connaissances dans d'autres langues.

Quand je fais référence à «d'autres langues», je fais en fait référence aux langues frontales populaires, par exemple: Javascript, Manuscrit, Toupet, CSS, HTML, réduction

Bien sûr, cela ne se limite pas aux langues frontales. C'est juste qu'il est plus facile de trouver un analyseur pour ces langages écrits en JavaScript que d'autres langages, par exemple C ++ ou Java.

Comme la façon dont nous utilisons Babel pour analyser et générer JavaScript, il existe d'autres bibliothèques pour nous aider à analyser et à générer notre langage.

Une astuce simple pour trouver ces bibliothèques est via https://astexplorer.net/.

Après avoir choisi une langue, vous verrez une liste d'analyseurs que vous pouvez utiliser pour analyser votre langue. Par exemple, si vous choisissez HTML, il y a htmlparser2, hyntax, parse5… Et lorsque vous choisissez l'un des analyseurs, vous pouvez immédiatement voir à quoi ressemble l'AST dans le panneau de droite et le lien Github vers l'analyseur en haut à droite.

Voici une liste non exhaustive d'analyseurs, et c'est analyser et produire méthodes:

Comme vous pouvez le voir, la plupart des analyseurs fournissent à la fois des méthodes d'analyse et de génération.

Donc, en général, vous pouvez avoir les éléments suivants comme modèle pour écrire votre code de transformation de code:

Vous pouvez, bien sûr, transformer AST d'une langue en AST d'une autre langue, par exemple: Sass ➡️ CSS, Markdown ➡️ HTML, et utiliser le générateur d'une autre langue pour générer le code.

Maintenant armé de ce modèle, parlons plus magique des trucs, la fonction de transformation.

Comme son nom l'indique, AST utilise une structure de données arborescente. Pour perfectionner les compétences de manipulation de l'AST, nous devons rappeler notre longue mémoire «Algorithme 101», les recherche en profondeur d'abord (DFS) algorithme de traversée d'arbre.

Vaidehi Joshi a écrit un article étonnant sur la démystification de la recherche en profondeur d'abord, je ne pense pas pouvoir mieux l'expliquer, donc si vous voulez récapituler sur la recherche en profondeur d'abord, allez lire son article avant de continuer.

Maintenant, vous avez une idée plus claire du fonctionnement de la recherche en profondeur d'abord, une recherche en profondeur d'abord sur un AST ressemblerait à ceci:

Nous pouvons ensuite remplir le FAIRE avec notre code de manipulation.

Si nous devions faire plusieurs traversées, avec différentes manipulations AST, nous réaliserions bientôt que mélanger le code de manipulation AST avec le code de traversée est pas assez propre. Naturellement, vous vous rendriez compte c'est plus propre pour passer une fonction de rappel qui est appelée à chaque fois que nous visitons un nœud:

le visite La fonction est maintenant suffisamment générique pour que vous puissiez l'utiliser pour n'importe quel AST:

Naturellement, vous penseriez qu'il serait utile d'avoir dans la fonction de rappel les informations du nœud parent et la clé / index du nœud actuel:

Maintenant, nous pourrions penser à nous-mêmes, je ne veux pas recevoir de rappel pour chaque nœud visité, j'ai juste besoin d'un rappel pour un certain nœud. Vous pourriez être tenté d'ajouter une condition dans le visite une fonction:

Mais vous réfléchissez à deux fois: et si quelqu'un d'autre veut utiliser visite mais avec une condition de rappel différente?

La plupart du temps, vous souhaitez rappeler uniquement à certains types de nœuds. Dans ce cas, au lieu de transmettre une fonction de rappel, vous pouvez transmettre une mappe de type de nœud à leurs fonctions de rappel respectives:

À ce stade, vous vous rendez peut-être compte, hé, cela ressemble tellement à une de ces bibliothèques traversant AST! Et oui, c'est ainsi qu'ils sont mis en œuvre.

Nous pouvons maintenant parcourir l'AST et trouver le nœud qui nous intéresse, donc la prochaine étape consiste à les manipuler.

La manipulation de l'AST peut être classée en 3 opérations différentes:

  • Ajout d'un nœud
  • Remplacement d'un nœud
  • Supprimer un nœud

Pour ajouter un nœud, vous pouvez l'affecter à une propriété à clé de votre nœud:

ou poussez le nouveau nœud, si la propriété keyed est un tableau:

Pour ajouter un nœud en tant que frère, vous devrez peut-être accéder au parent du nœud:

Pour remplacer le nœud actuel par un autre nœud, mettez à jour la propriété key du parent du nœud actuel:

Si la propriété clé du parent est un tableau:

Pour supprimer le nœud actuel, supprimez la propriété key du parent du nœud actuel:

Si la propriété clé du parent est un tableau:

Les opérations de ajouter, remplacer, et enlever les nœuds sont si communs qu'ils sont généralement implémentés comme une fonction util.

Cependant, il y a une étape importante que je n'ai pas couvert: après avoir muté le nœud, vous devez vous assurer que la traversée fonctionne toujours bien.

Pour un nœud qui est une propriété d'une clé de son parent, les ajouter, les remplacer et les supprimer sont généralement corrects. À l'exception de l'opération de remplacement, vous devrez peut-être revoir le «Nœud actuel», qui est le nouveau noeud de remplacement.

Cependant, pour les nœuds qui sont dans un tableau, vous devez faire particulièrement attention à mettre à jour l'index du tableau de la boucle:

Mais comment savez-vous que le nœud actuel a été supprimé?

Eh bien, savoir quand un nœud a été supprimé est parfois un secret qui se trouve dans le retirer utiliser la fonction de la bibliothèque de traversée d'arbre.

Cela peut être aussi simple que de définir un indicateur lorsque vous appelez retirer:

Mais parfois, au lieu d'avoir à importer le retirer utiliser de la bibliothèque de traversée d'arbre, le retirer est disponible en cette du visitCallback:

Maintenant que vous avez appris les 3 opérations de base de la manipulation de l'AST, vous vous demandez peut-être comment utiliser exactement ces opérations de base pour écrire un codemod ou un plugin de transformation AST?

Eh bien, dans mon guide étape par étape, j'ai expliqué que vous pouvez utiliser AST explorer comme http://astexplorer.net/ ou Babel AST Explorer pour vous aider.

Tu dois:

  • Savoir à quoi ressemble la partie du code que vous souhaitez modifier dans l'AST, afin que vous puissiez cibler le type spécifique du nœud, et
  • Savoir à quoi ressemble la sortie finale que vous souhaitez voir dans l'AST, afin que vous sachiez quels nœuds créer, mettre à jour ou supprimer.

Nous allons donc développer plus précisément ces 2 étapes.

Le ciblage des nœuds, la plupart du temps, ne représente que ===.

Par exemple, si vous souhaitez cibler un

avec une classe foo qui contient un - Manipuler AST avec JavaScript - JavaScript en anglais simple et un
dans htmlparser2:

Vous devez vérifier:

Pour le rendre moins verbeux, nous pouvons refactoriser chaque vérification en fonctions réutilisables:

Il existe plusieurs façons de créer un nœud AST.

Le moyen le plus simple et le plus grossier est de créer manuellement l'objet nœud. La plupart du temps, l'objet nœud est un objet JavaScript. Vous pouvez donc simplement les créer manuellement:

Cela peut devenir difficile à gérer lors de la création de nœuds AST complexes et de grande taille, donc la bibliothèque décide parfois de fournir des fonctions de générateur, comme @ babel / types pour simplifier la création de nœuds et fournir des valeurs par défaut:

Il avait l'air plus concis et plus ordonné, mais il est difficile de comprendre et de saisir le nœud qu'il crée.

Donc, une meilleure façon de créer un nœud AST complexe, est d'utiliser le analyser fonction + chaîne:

Pour Babel, il existe un utilitaire incroyable appelé @ babel / template, où vous pouvez utiliser des littéraux de modèle pour créer un nœud AST:

Nous avons traversé:

  • Comment traverser un AST, en utilisant l'algorithme de recherche en profondeur d'abord,
  • Les 3 manipulations de base de l'AST, ajout, remplacement et retrait,
  • Comment cibler un nœud dans AST, et
  • Comment créer un nœud AST

Dinesh (@flexdinesh) tweeté sa collection de poche de ressources AST:

Publié à l'origine sur https://lihautan.com/

Afficher plus

SupportIvy

SupportIvy.com : Un lieu pour partager le savoir et mieux comprendre le monde. Meilleure plate-forme de support gratuit pour vous, Documentation &Tutoriels par les experts.

Articles similaires

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bouton retour en haut de la page
Fermer