L'analyseur générique de langage repose sur algorithme très rudimentaire pour décomposer un fichier. Le besoin est de seulement diviser le texte en régions homogènes, telles que chaîne, commentaire ou code. Certaines de ces régions subissent un traitement secondaire pour en extraire les identificateurs qui seront recherchés dans un dictionnaire.

En conséquence, LXR ne nécessite pas toutes les complications d'un véritable analyseur de compilateur.

Chaque description de langage est une liste délimitée par des accolades de paires clef/valeur séparées par des virgules: { nom_LXR_du_language => { 'langid' => id_numerique_unique , 'identdef' => motif , 'flags' => [ liste_attributs ] , 'reserved' => [ liste_mots_clef ] , 'include' => { gestion_include } , 'spec' => [ configuration_analyseur ] , 'typemap' => { table_correspondance_ectags } } }

Le paramètre le plus important est 'spec' qui indique comment diviser le fichier en régions. 'spec' doit définir les régions par:

'spec' => { nom_region => [ motif_debut, motif_fin, motif_protection ] , nom_region => [ ... ] }

Exemples:

Commentaire /* ... */ en C

{ 'comment' => [ '/\*', '\*/' ] }

Commentaire // en C++ (\$ représente la fin de ligne)

{ 'comment' => [ '//', '\$' ] }

Chaîne en C: nous devons rester à l'intérieur de la chaîne si nous rencontrons des caractères protégés (sinon nous pourrions décréter la fin de la chaîne et nous retrouver dans une situation désynchronisée).

Attention: celui-ci est très délicat; lisez attentivement votre documentation Perl. { 'string' => [ '"', '"', '\\\\.' ] }

Le second paramètre important est 'identdef' utilisé à l'intérieur des régions code pour trouver les identificateurs et les mots-clef:

'identdef' => motif_mot_clef

Exemple:

Fourre-tout pour de nombreux langages (couvre les identificateurs et les mots-clef du préprocesseur C)

'identdef' => '([\w~]|\#\s*)[\w]*'

Vous donnez ensuite la liste des mots réservés qui ne seront pas pris en compte dans la recherche:

'reserved' => [ liste_mots_clef ] Dans certains langages, les mots-clef n'ont pas de casse particulière. Une seule liste suffit pour reconnaître toutes leurs variations si l'attribut 'case_insensitive' est activé: 'flags' => [ 'case_insensitive' ]

Exemple:

Extrait de la table C

'reserved' => [ 'auto', 'break', 'case', 'char', 'const', '#if' ]

Enfin, vous donnez une traduction intelligible des indicateurs ctags de façon que les listes de références croisées marquent les identificateurs avec des descriptions compréhensibles. Consultez la page man ctags pour une liste complète concernant un langage donné.

'typemap' => { lettre => categorie , lettre => categorie }

Exemple:

Extrait de la table C

'typemap' => { 'c' => 'classe' , 'd' => '(in)définition de macro' , 'f' => 'définition de function ' , 'v' => 'définition de variable' }

Si un langage peut "importer" des fichiers (ne vous tracassez pas au sujet de C/C++, ses règles sont incorporées), vous donnez à LXR des règles pour transformer l'expression du fichier dans le langage en une référence système pour permettre de plaquer un hyperlien cliquable sur le nom en question:

'include' => { 'directive' => motif , 'separator' => chaine , 'pre' => [ cible, remplacement ] , 'global' => [ cible, remplacement ] , 'post' => [ cible, remplacement ] } Antérieurement à la version 1.2, 'pre' et 'post'étaient nommés 'first' et 'last'. 'separator' est nouveau dans 1.2.

'directive' définit une expression régulière pour séparer l'instruction en 5 composants, à savoir:

  1. mot(s)-clef de l'instruction ou préfixe,
  2. espacement,
  3. délimiteur gauche,
  4. nom de fichier,
  5. délimiteur droit.

Exemple pour use ou require en Perl:

'directive' => '([\w]+)(\s+)()([\w:]+\b)()' # pas de délimiteurs en Perl mais l'expression régulière DOIT définir 5 composants

'separator' définit l'éventuel séparateur des noms de fichier dans le langage. Il est remplacé par le séparateur du système avant de tenter d'accéder au fichier.

'pre', 'global' et 'post' sont des règles optionnelles de substitution (cible est un motif et remplacement est substituté si correspondance). 'pre' est appliqué une seule fois au début. 'global' est ensuite appliqué répétitivement jusqu'à ce qu'il n'y ait plus de correspondance. 'separator' est remplacé par le séparateur du système. 'post' est appliqué une seule fois après les autres règles.

Exemple pour use ou require en Perl:

, 'separator' => '::' # Séparateur de package Perl , 'post' => [ '$', '.pm' ] # Ajouter l'extension systeme Perl a la fin du fichier

est plus efficace que l'équivalent:

, 'global' => [ '::', '/' ] # Remplacer tous les delimiteurs Perl :: par un delimiteur systeme / , 'post' => [ '$', '.pm' ] # Ajouter l'extension systeme Perl a la fin du fichier
À partir de la version 1.0, les règles include sont incorporées dans l'analyseur pour les langages C/C++, Perl, Python et Ruby. Il en est de même pour Java et Make à partir de la version 1.1. Ces analyseurs n'utilisent plus 'include'.