Question

En tant que projet animalier, j'aimerais essayer d'implémenter un langage de base de ma propre conception pouvant être utilisé comme langage de script Web. Il est simple d'exécuter un programme C ++ en tant que CGI Apache. Le vrai travail consiste donc à analyser un fichier d'entrée contenant du code non-codant (HTML / CSS) et du code côté serveur.

Dans mon cours de compilation pour les étudiants de premier cycle, nous avons utilisé Flex et Bison pour générer un scanner et un analyseur syntaxique pour un langage simple. Nous avons reçu une copie de la grammaire et avons écrit un analyseur qui traduisait le langage simple en un assemblage simple pour une machine virtuelle. Le scanner Flex identifie l’entrée et transmet les jetons à l’analyseur Bison.

La différence entre cela et ce que je voudrais faire est que, comme PHP, ce langage peut avoir un balisage HTML simple et que le langage de script est intercalé comme suit:

<p>Hello,
<? echo "World ?>
</p>

Est-ce que je me trompe en supposant qu'il serait efficace d'analyser le fichier d'entrée comme suit:

  1. Scanne l'entrée jusqu'à ce qu'une balise de début de script soit trouvée ('
  2. Le second analyseur tokenize la section de script côté serveur du fichier d'entrée (à partir de la balise ouverte: '') et transmet le jeton à l'analyseur, qui n'a pas besoin de connaître le balisage dans le fichier.
  3. Le contrôle est renvoyé au premier scanner qui poursuit ce modèle général.

Fondamentalement, le premier scanner ne fait la distinction que entre le balisage (qui est retourné directement au navigateur sans modification) et le code, qui est transmis au second scanner, qui à son tour bascule le code et transmet les jetons à l'analyseur.

S'il s'agit pas d'un modèle de conception solide, comment des langages tels que PHP gèrent-ils le balayage des entrées et l'analyse du code?

Était-ce utile?

La solution

Vous souhaitez examiner les conditions de démarrage. Par exemple:

"<?"            { BEGIN (PHP); }
<PHP>[a-zA-Z]*  { return PHP_TOKEN; }
<PHP>">?"       { BEGIN (0); }
[a-zA-Z]*       { return HTML_TOKEN; }

Vous commencez à l'état 0, utilisez la macro BEGIN pour changer d'état. Pour faire correspondre une RE uniquement dans un état particulier, préfixez-la avec le nom de l’état entouré de crochets.

Dans l'exemple ci-dessus, " PHP " est l'état. " PHP_TOKEN " et " HTML_TOKEN " _% token_s est défini par votre fichier yacc.

Autres conseils

PHP ne fait pas la distinction entre l'analyse et le balisage. Il sort simplement dans la mémoire tampon en mode Markup, puis passe en analyse en mode code. Vous n'avez pas besoin d'un scanner à deux passes et vous pouvez le faire avec un seul flex lexer.

Si vous êtes intéressé par le fonctionnement de PHP, téléchargez le code source (essayez le code source PHP4, il est beaucoup plus facile à comprendre). Ce que vous voulez regarder se trouve dans le répertoire Zend, zend_language_scanner.l .

Ayant écrit quelque chose de similaire moi-même, je vous conseillerais vraiment de repenser les itinéraires Flex et Bison et d'adopter un style moderne comme Antlr . C'est beaucoup plus facile, plus facile à comprendre (les macros utilisées dans une grammaire lex sont très confuses et difficiles à lire) et il a un débogueur intégré ( AntlrWorks ) afin que vous n'ayez pas à passer des heures à regarder des fichiers de débogage de 3 Mo. Il prend également en charge de nombreux langages (Java, C #, C, Python, Actionscript) et possède un excellent livre et un très bon site Web qui devrait vous permettre de démarrer rapidement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top