Souligneur syntaxique de code (delphi, vb, c/c++ etc)

Description

Voici un petit souligneur syntaxique que j'ai écrit en 2 jours, là je l'ai configuré de telle facon qu'il analyse le code Delphi, mais il est très facilement modifiable pour supporter d'autres langages tels que le VB, le C/C++ etc.

Il suffit juste de bien configurer toutes les variables globales. Tout est configurable, y compris les couleurs et le style, les mots clés, les séparateurs de mots, les délimiteurs de chaines, les délimiteurs de commentaires, les délimiteurs d'instructions préprocesseur, etc.

Source / Exemple :


<html>

<head>
	<title>Souligneur Syntaxique Delphi</title>	
</head>

<body>
<?php
/**

  • Souligneur syntaxique Delphi
  • Peut facilement être adapté pour d'autres langages (vb, c, c++...)
  • Il suffit de modifier le contenu des variables
* // On limite le temps d'execution à 15 secondes // (pour éviter de freezer la machine avec un code trop gros) set_time_limit(15); /****************************************************************/ /* Les variables qui définissent le comportement de l'analyseur */ /****************************************************************/ $case_sensitive = false; // Langage sensible à la case ou pas $tokdelimiters = " []()=+-/*:;,.\n\t\r "; // Les délimiteurs de mots /***************************************************/ /* Les couleurs associées à chaque type de données */ /***************************************************/ $colorkeyword = ""; $colortext = ""; $colorstring = "#000080"; $colorcomment = "#000080"; $colorsymbol = ""; $colornumber = "#000080"; $colorpreproc = "#008000"; /*************************************************/ /* Les styles donnés pour chaque type de données */ /*************************************************/ $stylekeyword = array("<b>", "</b>"); $styletext = array("", ""); $stylestring = array("", ""); $stylecomment = array("<i>", "</i>"); $stylesymbol = array("", ""); $stylenumber = array("", ""); $stylepreproc = array("<i>", "</i>"); /*****************/ /* Les mots clés */ /*****************/ $keywords = array( 'unit', 'interface', 'implementation', 'initialization', 'finalization', 'uses', 'type', 'var', 'begin', 'end', 'with', 'do', 'function', 'procedure', 'property', 'to', 'as', 'is', 'while', 'loop', 'for', 'repeat', 'until', 'use', 'class', 'private', 'protected', 'public', 'published', 'record', 'packed', 'case', 'of', 'const', 'array', 'try', 'finally', 'except', 'message', 'if', 'then', 'else', 'out', 'nil', 'string', 'constructor', 'destructor', 'library', 'set', 'inherited', 'object', 'overload', 'override', 'virtual', 'abstract', 'read', 'write', 'default', 'program', 'absolute', 'asm', 'external', 'stdcall', 'resourcestring', 'downto', 'exports', 'inline', 'raise', 'goto', 'label', 'dispinterface', 'file', 'threadvar', 'not', 'or', 'and', 'xor', 'mod', 'shl', 'shr', 'div' ); /***********************************/ /* Les délimiteurs de commentaires */ /***********************************/ $commentdelimiters = array( array("//", "\n"), array("{", "}"), array("(*", "*)") ); /********************************************/ /* Les délimiteurs de chaines de caractères */ /********************************************/ $stringdelimiters = array( array("'", "'") ); /********************************************************/ /* Les délimiteurs d'instructions pour le préprocesseur */ /********************************************************/ $preprocdelimiters = array( array("(*\$", "*)"), array("{\$", "}") ); ///////////////////////////////////////////////////////////////////////////////////////// // Le code en lui-même ///////////////////////////////////////////////////////////////////////////////////////// /************************************************************************/ /* Renvoie vrai si un caractère est visible et peut être mis en couleur */ /************************************************************************/ function visiblechar($char) { $inviblechars = " \t\n\r "; return (!is_integer(strpos($inviblechars, $char))); } /************************************************************/ /* Formatte un mot d'une manière spéciale (couleur + style) */ /************************************************************/ function formatspecialtok($tok, $color, $style) { if (empty($color)) return sprintf("%s$tok%s", $style[0], $style[1]); return sprintf("%s<font color=\"%s\">$tok</font>%s", $style[0], $color, $style[1]); } /*******************************************************************/ /* Recherche un élément dans un tableau sans se soucier de la case */ /*******************************************************************/ function array_search_case($needle, $array) { if (!is_array($array)) return false; if (empty($array)) return false; foreach($array as $index=>$string) if (strcasecmp($needle, $string) == 0) return intval($index); return false; } /*****************************************************/ /* Analyse un mot et le renvoie de manière formattée */ /*****************************************************/ function analyseword($tok) { global $keywords; global $case_sensitive; global $colorkeyword; global $colornumber; global $colortext; global $stylekeyword; global $stylenumber; global $styletext; // Si c'est un nombre if (($tok[0] == '$') || ($tok[0] == '#') || ($tok == (string)intval($tok))) return formatspecialtok($tok, $colornumber, $stylenumber); // Si c'est vide, on renvoie une chaine vide if (empty($tok)) return $tok; // Si c'est un mot clé if ((($case_sensitive) && (is_integer(array_search($tok, $keywords, FALSE)))) || ((!$case_sensitive) && (is_integer(array_search_case($tok, $keywords))))) return formatspecialtok($tok, $colorkeyword, $stylekeyword); // Sinon, on renvoie le mot sans formattage return formatspecialtok($tok, $colortext, $styletext); } /***************************************************/ /* On regarde si on ne tombe pas sur un délimiteur */ /***************************************************/ function parsearray($array, $color = "#000080", $style = array("<i>", "</i>")) { global $code; global $newcode; global $char; global $tok; global $i; global $codelength; // On effectue quelques vérifications if (!is_array($array)) return false; if (!strlen($code)) return false; if (!sizeof($array)) return false; // On va essayer de comparer le caractère courrant avec le 1° // caractère de chaque premier délimiteur foreach($array as $delimiterarray) { $delimiter1 = $delimiterarray[0]; // Si le 1° char correspond if ($char == $delimiter1[0]) { $match = true; // On va tenter de comparer tous les autres caractères // Pour vérifier qu'on a bien le délimiteur complet for ($j = 1; ($j < strlen($delimiter1)) && $match; $j++) { $match = ($code[$i + $j] == $delimiter1[$j]); } // for // Si on l'a en entier if ($match) { $delimiter2 = $delimiterarray[1]; // Alors on recherche le délimiteur de fin $delimiterend = strpos($code, $delimiter2, $i + strlen($delimiter1)); // Si on ne trouve pas le délimiteur de fin, on prend tout le fichier if (!is_integer($delimiterend)) $delimiterend = strlen($code); // Maintenant qu'on a tout, on analyse le mot avant le délimiteur, s'il existe if (!empty($tok)) { $newcode .= analyseword($tok); $tok = ""; } // Ensuite, on place le texte contenu entre les délimiteurs $newcode .= formatspecialtok(substr($code, $i, $delimiterend - $i + strlen($delimiter2)), $color, $style); // On replace l'indice au bon endroit $i = $delimiterend + strlen($delimiter2); // Enfin on récupère le caractère en cours if ($i > $codelength) $char = null; else $char = $code[$i]; // On précise qu'on a trouvé return true; } //if } // if } // foreach return false; } /******************************/ /* On traite les cas spéciaux */ /******************************/ function parsearrays() { global $preprocdelimiters; global $commentdelimiters; global $stringdelimiters; global $colorpreproc; global $colorcomment; global $colorstring; global $stylepreproc; global $stylecomment; global $stylestring; $haschanged = true; // A chaque changement, on redemarre la boucle entière while($haschanged){ // On regarde si on ne tombe pas sur un délimiteur de commentaire $haschanged = parsearray($preprocdelimiters, $colorpreproc, $stylepreproc); if (!$haschanged) { // On regarde si on ne tombe pas sur un délimiteur de commentaire $haschanged = parsearray($commentdelimiters, $colorcomment, $stylecomment); if (!$haschanged) { // Ou de chaine de caractère $haschanged = parsearray($stringdelimiters, $colorstring, $stylestring); } // if } // if } // while } // parsearrays /***************************/ /* Analyse un code complet */ /***************************/ function analysecode() { global $code; // Le code reçu du formulaire global $newcode; // Le nouveau code généré global $tok; // Le mot en train d'être découpé global $char; // Le caractère en cours global $i; // La position en cours dans le code global $codelength; // La longueur de la chaine de code global $commentdelimiters; global $stringdelimiters; global $preprocdelimiters; global $tokdelimiters; global $colorsymbol; global $stylesymbol; // On initialise les variables $newcode = ""; $tok = ""; $char = null; $codelength = strlen($code); for ($i = 0; $i < $codelength; $i++) { $char = $code[$i]; // On regarde si on tombe sur un cas spécial parsearrays(); // On regarde si on est arrivé au bout de la chaine if ($char == null) return $newcode; // On a fini d'analyser les commentaires, on regarde si on a un mot complet if (is_integer(strpos($tokdelimiters, $char))) { // On tombe sur un délimiteur, on coupe le mot $newcode .= analyseword($tok); // On formatte le délimiteur if (visiblechar($char)) $newcode .= formatspecialtok($char, $colorsymbol, $stylesymbol); else $newcode .= $char; // On remet à 0 le mot en cours $tok = ""; } else {// On n'a pas de mot complet, on complete le mot $tok .= $char; } } // for // On regarde si on arrive au bout du code if (!empty($tok)) $newcode .= analyseword($tok); return $newcode; } /**********************/ /* On analyse le code */ /**********************/ if (isset($code)) { // On retire les \ devant les ' $code = stripslashes($code); // On analyse le code $newcode = analysecode(); print("<h2>Code mis en valeur</h2>"); print("<pre>$newcode</pre>"); } print("<hr>"); ?> <form action="<?php print("http://$HTTP_HOST$PHP_SELF");?>" method="POST"> Texte à analyser:<br> <textarea name="code" cols="80" rows="20"> <?php print($code); // Juste pour les tests, à retirer par la suite // On ajoute un exemple de code if (!isset($code)) { ?> implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Caption := 'Salut'; Tag := 3; end; <?php } ?> </textarea> <br> <input type="submit" value="analyser"> </form> </body> </html>

Conclusion :


Le code est assez rapide: sur mon P4 1.7 Ghz, j'arrive à analyser le fichier Messages.pas de Delphi 7 (1847 lignes de code) en 8 secondes... En revanche, chez mon hébergeur (Amen), au bout de 15 secondes l'analyse n'était pas encore terminée...

J'ai mis une limite d'execution de 15 secondes au début du fichier pour éviter de bouffer tout le temps processeur.

Ce petit bout de code peut être très utile si vous faites un site sur la programmation avec des morceaux de code...

N'hésitez pas à apporter vos critiques et idées d'amélioration...

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.