COMMENTAIRES

Il est inutile d'insister sur la nécessité de documenter au maximum vos directives ADAPT: il n'est pas toujours facile de se replonger dans un fichier de directives écrit six mois auparavant.
ADAPT vous permet donc d'insérer des commentaires dans vos directives. Ceux-ci sont toujours précédés d'un point-virgule (;). Par exemple:

(1);Cette transformation (malheureusement trop vorace)
(2)/Sans_commentaire :; supprime tous les commentaires
(3);présents dans un fichier de directives ADAPT.
(4)';', 0~" ":"~"; Tous les caractères affichables
(5)= .; après un ";" sont supprimés.

Cette transformation n'est pas parfaite: appliquée à elle même (c'est-à-dire avec ses propres directives comme fichier d'entrée à traiter), cette transformation supprime tout le contenu de la ligne (4) immédiatement après la première apostrophe:

(1)
(2)/Sans_commentaire :
(3)
(4)'
(5)= .

Les patrons de fouille ';', 0~" ":"~" repèrent un point virgule et ce qui le suit n'importe où, même si le point-virgule se trouve dans la définition d'une chaîne de caractères ...

Le chapitre ALTERNATIVES ET NEGATIONS fournit des solutions à ce genre de problèmes.

ALTERNATIVES ET NÉGATIONS

Alternatives:

Il arrive souvent que plusieurs alternatives soient possibles pour une même portion des données à convertir.

Vous pouvez donc définir plusieurs alternatives pour un même patron de fouille.

Par exemple:

/Voyelle = "a" | "e" | "i" | "o" | "u" | "y"

est un type de donnée qui se vérifie lorsqu'une voyelle minuscule, majuscule ou accentuée est rencontrée dans les données.


Un patron peut comporter plusieurs alternatives, séparées par une barre verticale:

alternative | ... | alternative

Ces alternatives sont vérifiées de gauche à droite et dès que l'une se vérifie, le patron entier se vérifie.


Puisque chaque alternative est elle-même un patron de fouille, il est parfois nécessaire de mettre entre parenthèses l'ensemble de toutes les alternatives. Ainsi:

2 "a" | "e" | "i" | "o" | "u" | "y"

équivaut à:

"aa" | "e" | "i" | "o" | "u" | "y"

Pour exiger deux voyelles côte à côte, il faut écrire :

2 ("a"| "e" | "i" | "o" | "u" | "y")

ou encore 2 voyelle si on utilise le type de donnée défini plus haut.

On peut aussi définir une syntaxe des nombres réels:

/réel = ~1('+' | '-'), ( 1~d, ~1('.', 1~d) ) | ('.', 1~d)
/d = '0':'9'

~1('+' | '-')
indique que un signe + ou - peut éventuellement précéder le nombre réel;
1~d, ~1('.', 1~d)
indique une première alternative pour la syntaxe du nombre: celui-ci comporte au moins un chiffre, éventuellement suivi d'un point ( . ) et d'une décimale ou plus;
'.', 1~d
indique une seconde alternative pour la syntaxe du nombre: celui-ci ne comporte pas de partie entière et au moins une décimale après le point.

Le type de donnée réel se vérifiera donc pour des données comme:

123, +1, 12.3, +12.34, .1, -.12

et il ne se vérifiera pas pour:

., +., -., 12. ou + -

Si un nom de variable se trouve devant une série d'alternatives, les données pour lesquelles une de ces alternatives se vérifie sont stockées dans la variable:

SIGNE '+' | '-' stocke le caractère rencontré dans la variable SIGNE lorsque le patron se vérifie.

Pour stocker dans une variable les données pour lesquelles une alternative spécifique se vérifie, le nom de cette variable doit être indiqué entre parenthè ses avec l'alternative :

'+' | (SIGNE '-') stocke le caractère - dans SIGNE

'+' | SIGNE '-' n'est pas permis

Le symbole () permet d'indiquer un patron qui se vérifie toujours, sans extraire de données en entrée. Ceci permet d'écrire des alternatives qui réussissent toujours:

'+' | '-' | () est équivalent à ~1 ('+' | '-')

Ce symbole permet aussi d'initialiser une variable à un contenu vide:

SIGNE (), ~1 ( '+' | (SIGNE '-') ) permet de ne rien avoir dans la variable SIGNE sauf si - est rencontré.

Négation:

Il est souvent plus facile de définir ce que l'on ne veut pas traiter que ce que l'on veut traiter.


Un patron de fouille peut n'avoir que le symbole 0(zéro) ou le symbole ~ à la place d'un facteur de répétition. Il fait alorsd l'objet d'une négation:

Il se vérifie alors si et seulement si ce qui suit le symbole de négation ne se vérifie pas.

Par exemple, pour repérer des nombres entiers dans un texte (donc une suite de chiffres sans point décimal à la fin), il suffit d'écrire: 1~'0': '9', o'.'


La négation est particulièrement pratique pour retrouver des chaînes de caractères entre délimiteurs. Ces chaînes de caractères contiennent n'importe quel caractère sauf le délimiteur. Par exemple:

/chaine_guillemets = '"', 0~( 0 '"', " ":"~" ), '"'

Le type de donnée chaine_guillemets repère, dans un fichier de directives ADAPT, une chaîne de caractères entre guillemets. Cette chaîne est composée de zéro ou plus caractères définis de la façon suivante:

0 '"' :si un guillemet est présent, ce patron ne se vérifie pas. Si le caractère n'est pas un guillemet, ce patron se vérifie. Il n'avance cependant pas dans les données en entrée.

" ":"~"se vérifie ensuite pour n'importe quel caractère affichable.


Un patron comportant une négation n'avance pas dans les données en entrée: il définit ce que l'on ne veut pas extraire mais il ne définit pas ce que l'on veut extraire.

Si ce patron se vérifie (c'est-à-dire que ce qui suit le symbole de négation ne se vérifie pas), le patron suivant est vérifié pour les mêmes données.

Par exemple,0"a":"z", " ":"~" se vérifie pour n'importe quel caractère affichable qui n'est pas une lettre.


Plusieurs négations peuvent se succéder, permettant, entre autre, de refuser plusieurs intervalles decaractères:

~"a":"z", ~'0':'9', " ":"~"

est un patron qui se vérifie pour tout caractère affichable qui n'est ni une lettre ni un chiffre. Dans cet exemple, la tilde ( ~ ) a été utilisée à la place de zéro ( 0 ) : les deux symboles sont tout à fait équivalents.

Vous vous rappelez sans doute qu'une chaîne de caractères entre guillemets peut contenir un guillemet si celui-ci est redoublé.

Pour améliorer chaîne_guillemets, nous pouvons donc définir:

/chaîne_guillemets = '"', 0~( '""' | ( 0'"', " ":"~") ), '"'

et aussi:

/chaîne_apostrophes= "'", 0~( "''" | ( 0"'", " ":"~") ), "'"

La chaîne de caractères débute donc par un guillemet, et a comme contenu une suite de zéro ou plus éléments. Ceux-ci peuvent être soit des guillemets dé doublés, soit un caractère affichable autre qu'un guillemet.


Ceux qui sont familiers avec la logique booléenne auront reconnu l'opérateur OU ( | )et l'opérateur NON ( ~ ou 0).


La transformation Sans_commentaire peut maintenant être perfectionnée pour laisser intouchés les points-virgules qui n'indiquent pas vraiment le dé but d'un commentaire:

(1)/Sans_commentaire :
(2); Recopier telles quelles les chaînes de caractères
(3); entre guillemets ou entre apostrophes :
(4)CHAINE chaîne_guillemets = CHAINE.
(5)CHAINE chaîne_apostrophes= CHAINE.
(6)';', 0~c = . ; Supprimer les car. affichables après ";"
(7)/c = " ":"~"
(8)/q = ''''
(9)/dq = '"'
(10)/chaîne_guillemets = dq, 0~ ( 2dq | (~dq, c)), dq
(11)/chaîne_apostrophes= q, 0~ ( 2q | (~q, c)), q

Vous remarquerez que l'utilisation de types de donnée augmente beaucoup la lisibilité de ces directives.

Les règles des lignes (4) et (5) ont toutes les deux le même résultat ( = CHAINE. ) : elles pourraient donc aussi s'écrire:

CHAINE (chaîne_guillemets | chaine_apostrophe) = CHAINE.


Les règles d'une transformation sont donc comme une série d'alternatives à vérifier sur les données en entrée, chacune produisant cependant un résultat différent.

La première règle qui se vérifie déclenche l'action correspondante (production du résultat) et les règles suivantes ne sont pas vérifiées.


Cette façon d'appliquer les règles de transformation permet donc, dans la transformation Sans_commentaire , de recopier les chaînes de caractères et leur contenu avant de traiter les points-virgules (et supprimer ce qui les suit). Les points-virgules dans les chaînes de caractères sont donc sains et saufs!

EXEMPLE COMPLET : Traduction d'un programme

Un informaticien désire traduire son programme écrit dans le langage PASCAL français en PASCAL anglais. Il a défini le fichier de directives suivant:

(1)/Traduire :
(2); Traduire un programme PASCAL du français à l'anglais.
(3); Ne pas traiter les commentaires:
(4)COMMENTAIRE ('{', 0~ ( ~'}', c ), '}') =COMMENTAIRE.
(5)COMMENTAIRE ('(*', 0~ ( ~'*)', c ), '*)') =COMMENTAIRE.
(6); Ne pas traiter les chaînes de car. entre apostrophes:
(7)CHAINE q, 0~ ( 2q | (~q, c)), q = CHAINE.
(8); Traduire tous les mots clés:
(9)"programme", ~Ld = 'Program'.
(10)"faire", ~Ld = 'do'.

...Vous trouverez cet exemple au complet sur disquette ...

(11)"fin", ~Ld = 'End'.
(12)IDENTIFICATEUR 1~Ld = IDENTIFICATEUR.
(13); Types de donnée utilisés :
(14)/Ld = '0':'9' | "a":"z" ; une lettre ou un chiffre
(15)/c = $00:$FF ; absolument n'importe quel caractère
(16)/q = ''''; apostrophe

Dans un programme PASCAL, les commentaires (c.f.lignes (4) et (5)) sont entre accolades
{ et } ) ou entre (* et*) et peuvent prendre plusieurs lignes. Ils peuvent donc contenir absolument n'importe quel caractère, affichable ou non affichable, à l'exception du délimiteur final ( } ou *) ).

Les chaînes de caractères entre apostrophes sont recopiées telles quelles ( ligne (7)).

Les mots-clés à traduire ( tantque, programme, etc.) (lignes (9) à (11)) doivent apparaître dans le programme PASCAL sans être suivis d'une lettre ou d' un chiffre ( ~Ld ) : ceci évite de traduire des identificateurs comme programmes, final, etc.

La dernière règle (ligne (12)) extrait au complet tout identificateur qui n'a pas été traduit et le recopie tel quel : de cette façon affaire ne risque pas de devenir afdo deux caractères plus tard ! Les données sont donc traitées mot par mot et non caractère par caractère.