Comment ça marche : le compilateur de squelettes
Là .. on attaque le gros morceau :-)
La fonction calculer_squelette (dans inc-compilo) prend 4 arguments :
-
$squelette: le texte du squelette source -
$nom: le nom de la fonction principale attendue -
$gram: l’extension -
$sourcefile: le nom du fichier squelette source
Voila ce qu’elle fait :
- défini un tableau
$bouclesvide. Il contiendra plus tard une entrée par boucle du squelette (ccmStructureTableauBoucle). - inclusion de
inc-$gram-squel.php3qui doit définir une fonctionphraser(ccmPhraseur) - appel de cette fonction (
$boucleest passé en argument et peuplé par la fonction) et retour mis dans la variable$racine(=nom de la boucle principale du squelette) - init d’un tableau
$descravec les champs nom (le nom de la fonction principale), documents (false) et sourcefile (le nom du fichier sqC) - on passe le champ document à true s’il y a une boucle de type documents avec le critère doublons.
- on établi le lien mère/fille pour les boucles récursives et on appelle
calculer_listedessus - pour les autres boucles
- on récupère son id_table et sa primary_key ainsi que ses jointures (pour les tables spip)
- on appelle
calculer_criteresdessus - on appelle
calculer_listedessus
- on appelle
calculer_listesur la racine - dans les 3 cas, le retour de la fonction
calculer_listeest mis dans le champreturnde la boucle. - pour chaque boucle
- on appelle la fonction de génération de code associée, c’est à dire une fonction
boucle_{machin}, sinonboucle_{machin]-dist, sinonboucle_DEFAUT(machin étant le type de la boucle, c’est à dire ARTICLES, MOTS ...). Ces fonctions doivent retourner le corps d’une fonction générant le code de la boucle.- la plupart de ces fonctions appellent
calculer_bouclequi effectue la génération de code select et la boucle d’itérations associée. À ce moment, le phraseur à déjà analysé les critères de boucle, et mis leur interprétation dans les champs de la structure boucle, mais c’est cette fonctio qui en déduit les éléments de requète et d’itérateur à générer.
- la plupart de ces fonctions appellent
- on affecte au champ
returnle code de la déclaration d’une fonction :- son nom est construit à partir du nom du squelette et de celui de la boucle
- son code est celui retourné par la fonction boucle_*
- ses arguments sont fixés
- si on est en mode debug, on ajoute des trucs au champ return, via la fonction
boucle_debug_compile
- on appelle la fonction de génération de code associée, c’est à dire une fonction
- pour chaque boucle, on ajoute son champ return à une chaine de caractère qui constitue donc le code compilé
- on ajoute un commentaire d’entête à tout le machin et la définition de la fonction principale
- on retourne le tout.
Bon ... c’est carrément pas clair car il est toujours difficile d’expliquer un code de compilateur, où des fonctions retournent le code d’un corps de fonction à placer dans une chaîne qui devient un fichier source ...
Voila un schéma qui résume un peu ces différentes étapes :
j’ai également une version pdf et la
source xfig que vous pouvez améliorer si ça vous botte.
À plusieurs reprises, on appelle calculer_liste sur une entrée du tableau boucles.
Voila le commentaire de cette fonction :
// Production du code PHP a partir de la sequence livree par le phraseur
// $boucles est passe par reference pour affectation par index_pile.
// Retourne une expression PHP,
// (qui sera argument d'un Return ou la partie droite d'une affectation).Elle appelle compile_cas puis colle les extraits de codes retournés avec éventuelement des infos de debug.
compile_cas boucle sur les éléments du tableau passé en argument (soit la racine d’un squelette, soit le milieu d’une boucle).
Pour chacun, selon qu’il s’agit d’un texte, un polyglotte (tag <multi>), un include, une boucle, un idiome
(tag <:..:>), ou un champ, on appelle une fonction dédiée à ce cas (calculer_inclure, calculer_champ), ou on génère directement le code correspondant (appel à _T, multi_trad ou texte déspécialisé).
Dans certains cas, des parties avant/apres/sinon sont évaluées via un appel à calculer_liste.
Pour chaque bloc, on génère ensuite un extrait contenant le code seul, ou la construction si/alors/sinon associée à une boucle ou un champ.
Il y a également un appel tout discret à calculer_criteres qui a pourtant son importance : cette fonction parcours
la liste des critères de la boucle, et pour chacun, il appelle une fonction criteres_OP sinon
criteres_OP_dist sinon calculer_critere_DEFAUT ou calculer_critere_parties (dans le cas des critères {1,2} ou {1/3}.
Le "OP" correspond à l’opérateur du critère, c’est à dire un élément isolé lors du parsing (pour plus de détail, voir la fonction
phraser_criteres de inc-html-squel, bon courage ...).

