Surlignage du code FORTH en PHP
publication: 22 juin 2022 / mis à jour 23 juin 2022
Appel à collaboration
Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.
Partagez-les ici sur ce site.
ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.
Vos montages peuvent aider d'autres développeurs.
Les montages des autres développeurs peuvent vous aider.
Pour proposer un article ou un montage, cliquez ici
Préambule
Très tôt, dans ma longue carrière de programmeur informatique, j'ai apprécié les éditeurs de code source qui surlignent la syntaxe du code source. Certains de ces éditeurs de code savent s'adapter au langage de programmation utilisé.
Plus tard, en écrivant des articles traitant de programmation, sur des blogs, puis sur mes sites web, j'ai utilisé GesHi, une librairie puissante, mais complexe.
Le souci, avec GesHi, c'est qu'il ne traite pas le code FORTH. J'ai bien réussi à créer des scripts adaptés au langage FORTH pour GesHi, mais ces scripts avaient toujours quelques défauts:
Ici, GesHi détecte le mot begin
dans le mot MDNS.BEGIN
.
Après analyse, GesHi traite le code FORTH caractère par caractère et considère les caractères . et - comme des opérateurs de code.
GesHi représente plus de 4000 lignes de code en PHP. Un code complexe et peu factorisé. On sent la patte de plusieurs programmeurs qui ont chacun rajouté des couches.
Code complet disponible ici:
Un nouvel analyseur de code pour FORTH
J'étais confronté à plusieurs choix:
- laisser les travaux FORTH GEsHi en l'état et accepter les erreurs de GesHi
- choisir un autre analyseur de code et retomber sur des problèmes similaires d'adaptation
- passer des dizaines d'heures à tracer et tenter d'améliorer Geshi....
Il s'avère que je maitrise parfaitement la programmation en PHP. J'ai donc commencé par faire un test très simple: exploser un code FORTH avec PHP:
/** * Explode FORTH source code in array of keywords * @param type $code */ private function explodeSource($code) { $lines = explode( "\n", str_replace("\r", "", $code)); $this->keySource = array(); foreach ($lines AS $line) { $this->keySource[] = explode(" ", $line); } }
Le résultat était tout simplement ce que je recherchais. Cette fonction explodeSource
découpe chaque ligne en tableau de lignes. La seconde boucle découpe le contenu de chaque
ligne en tableau en prenant comme séparateur le caractère espace. Le résultat est restitué
dans un tableau $this->keySource
.
C'est ce qui m'a décidé à créer mon propre analyseur de code FORTH en PHP. J'ai réalisé un surligneur de code FORTH en deux soirées à peine....
Définir les liste de mots FORTH
Sur mon site web, les mots FORTH sont stockés en base de données. Voici comment est réalisée
l'injection des listes de mots FORTH dans un tableau $this->keywords
:
/** * fetch all forth words from database */ private function getKeywords() { $Glossaire = new Application_Model_Glossaire; $this->keywords[0] = $Glossaire->getListeMotsOrdinaires(); $this->keywords[1] = $Glossaire->getListeMotsDefinition(); $this->keywords[2] = $Glossaire->getListeMotsStructure(); $this->keywords[3] = $Glossaire->getVariablesConstantes(); $this->keywords[4] = $Glossaire->getListeMotsVocabulaires(); //$motsDefered = $Glossaire->getListeMotsDefered(); $Registers = new Application_Model_Registers; $this->keywords[5] = $Registers->getListeRegistres(); }
Sur votre site web, vous pouvez définir vos listes de cette manière si vous ne souhaitez pas exploiter une base de données:
/** * fetch all forth words from database */ private function getKeywords() { $Glossaire = new Application_Model_Glossaire; $this->keywords[0] = array('drop', 'dup', 'rot', 'over', 'swap'); $this->keywords[1] = array(':', ';', 'constant', 'variable'); $this->keywords[2] = array('if','else','then'); $this->keywords[3] = array('base'); $this->keywords[4] = array('forth'); }
Avec cette méthode, on définit différentes catégories de mots FORTH. Ceci permet de surligner le code FORTH avec des styles différents.
Définition des styles
On définit un autre tableau contenant les différents styles pour surligner le code FORTH:
/** * define all styles for decoration * @var array */ var $outStyle = array( 0 => 'color: #0000ff;', // normal words 1 => 'color: red; font-weight: bold;', // definitions words 2 => 'color: black; background-color: yellow;', // structure words 3 => 'color: #ff00ff; font-weight: bold;', // constants 4 => 'color: black; font-weight: bold; background-color: #d7d7ff', // vocs 'bin' => 'color: #7f00dd;', // binaries values 'dec' => 'color: #0000dd;', // decimal values 'hex' => 'color: #003ffd;', // hexadecimal values );
Dans ce code, nous avons trois clés bin dec
et hex
. Ces clés
sont utilisées pour décorer des valeurs numériques en binaire, décimal ou hexadécimal.
Décoration d'un mot FORTH
La décoration d'un mot FORTH fonctionne par paliers successifs:
- si le mot est dans un commentaire, on ne le décore pas
- si le mot est un nombre binaire ou décimal ou hexadécimal, on le décore. C'est le rôle d'expressions régulières analysant la structure du mot. Par exemple, 10010011 est analysé comme valeur binaire;
- si on rencontre le mot
\
on active le flag marquant le commentaire et on retourne la décoration marquant ce commetaire; - enfin, on teste si le mot figure dans le tableau des mots FORTH à décorer. C'est le rôle de la dernière boucle
foreach
. Si c'est un mot à décorer, on le décore.
A chaque palier, on sort de la fonction par return
. Si aucune condition n'est remplie
on renvoie le mot sans décoration, suivi d'un caractère espace.
/** * highlight FORTH code * @param string $word */ private function styliseWord($word) { if ($this->commentFlag == TRUE) { return $word ." "; } // test if $word is a binary value $re = '/^[0-1]{8}/is'; preg_match($re, $word, $matches, PREG_OFFSET_CAPTURE, 0); if (!empty($matches)) { return '<abbr style="' . $this->outStyle['bin'] . '" title="binary byte">' . $word . '</abbr> '; } // test if $word is a decimal value $re = '/^\d{1,}/is'; preg_match($re, $word, $matches, PREG_OFFSET_CAPTURE, 0); if (!empty($matches)) { return '<abbr style="' . $this->outStyle['dec'] . '" title="number">' . $word . '</abbr> '; } // test if $word is a hexadecimal value $re = '/^\$[a-f0-9]{1,}/is'; preg_match($re, $word, $matches, PREG_OFFSET_CAPTURE, 0); if (!empty($matches)) { return '<abbr style="' . $this->outStyle['hex'] . '" title="hexadecimal value">' . $word . '</abbr> '; } // if it's the word \ tag comment if (ord($word) == 92) { $this->commentFlag = TRUE; return '<span style="color: #808080; font-style: italic;">' . $word ." "; } // test if $word is a FORTH word foreach ($this->keywords AS $level => $listeMots) { if (in_array(strtoupper($word), $listeMots)) { return $this->linkifyWord($word, $level); } } return $word ." "; }
La décoration d'un mot FORTH qui est défini dans la liste des mots FORTH s'effectue de cette manière en PHP:
/** * array of external links * @var array */ var $outlink = array( 0 => 'help/index-esp32/word/', 1 => 'help/index-esp32/word/', 2 => 'help/index-esp32/word/', 3 => 'help/index-esp32/word/', 4 => 'help/index-esp32/word/', 5 => 'help/reg-esp32/word/', ); /** * include FORTH word in an external link * @param string $word * @param mixed $level * @return string */ private function linkifyWord($word, $level) { if ($this->enable_keyword_links) { return '<a href="' . $this->outlink[$level] . base64_encode($word) . '" style="' . $this->outStyle[$level] . '">' . $word . '</a> '; } return '<abbr style="' . $this->outStyle[$level] . '">' . $word . '</abbr> '; }
On définit une liste de liens dans le tableau $outlink
. Ici, ce sont des liens internes
propres à mon site web. Il est facile de définir des liens vers des sites externes:
/** * array of external links * @var array */ var $outlink = array( 0 => 'https://forth-standard.org/standard/core/DUP', 1 => 'https://forth-standard.org/standard/core/DUP', 2 => 'https://forth-standard.org/standard/core/DUP', 3 => 'https://forth-standard.org/standard/core/DUP', 4 => 'https://forth-standard.org/standard/core/DUP', );
Reconstitution du code FORTH décoré
Pour reconstruire notre code FORTH décoré, on part du tableau $this->keySource
.
Ce tableau a été rempli par explodeSource
. On lit ce tableau item par item.
Si on rencontre un item vide, on concatène un espace simple. Dans le cas contraire,
on décore l'item selon les conditions de la fonction styliseWord
.
/** * Generate highlighted FORTH source code * @return string */ private function generateOutsource() { $outSource = ""; foreach ($this->keySource AS $line) { foreach ($line AS $word) { if (strlen($word)==0) { $outSource .= " "; } else { $outSource .= $this->styliseWord($word); } } if ($this->commentFlag == TRUE) { $this->commentFlag = FALSE; $outSource .= "</span>"; } $outSource .= " "; } return $outSource; }
Voici comment exploiter le code PHP permettant de surligner le code FORTH. Le code PHP doit être chargé préalablement par include ou la fonction autoload de PHP:
<?php $forthStr = <<<EOT DEFINED? --random [if] forget --random [then] create --random \ Random number data $3FF75144 constant RNG_DATA_REG \ Read Only ESP32 register \ get 32 bits random b=number : rnd ( -- x ) RNG_DATA_REG UL@ ; EOT; echo $Forth->sourceForView($forthStr); ?>
Le résultat est celui attendu:
DEFINED? --random [if] forget --random [then] create --random \ Random number data $3FF75144 constant RNG_DATA_REG \ Read Only ESP32 register \ get 32 bits random b=number : rnd ( -- x ) RNG_DATA_REG UL@ ;
Conclusion
Si on se réfère au seul contenu du code de gesHi, le surlignage de code semble une tâche ardue. Et c'en est effectivement une si on construit une usine à gaz.
Ici, avec moins de 200 lignes de code, en PHP, j'ai développé, en quelques heures, un surligneur de code FORTH qui fonctionne bien mieux que le code de gesHi sur lequel j'ai passé des dizaines de journées à tenter d'en comprendre toutes les subtilités.
Reste la question de l'intérêt de surligner le code FORTH...
Ce qui m'a intéressé, avec GesHi, c'est que nativement, si on surligne du code PHP, il est possible d'activer des liens externes de documentation.
C'est cet aspect de GesHi qui me semble avoir un énorme intérêt pour FORTH. Car vous aurez beau documenter un programme, rien ne vaut un accès direct à des explications sur n'importe quel mot du vocabulaire FORTH.
Dans les codes sources diffusés ici, tous les mots de ESP32forth qui sont documentés sont affichés avec une coloration syntaxique et un lien hypertexte donnant accès direct à la documentation de ce mot.
Car, si on veut que FORTH intéresse des programmeurs, il me semble essentiel de faciliter la compréhension du code. Et, sauf erreur, aucun autre site web de développeur FORTH n'a encore donnée un accès aussi simple à la documentation du code FORTH au travers de la coloration syntaxique.
Un mot pour Peter FORTH:
Peter.
Vous m'avez bloqué de votre groupe FORTH2020 quand j'ai présenté cette méthode de surlignage du code FORTH.
Vous m'avez également bloqué d'autres groupes dès que j'intervenais pour présenter FORTH. Votre blog ESP32FORTH est indigent. Mal construit. Il gagnerait en lisibilité à exploiter mon code PHP.
Alors mettez votre égo de coté. Si vous pensez vraiment oeuvrer dans l'intérêt du langage FORTH, Cessez cette atitude enfantine envers moi.
Legal: site web personnel sans commerce / personal site without seling