La Form Machine
I. Formes
Une forme est un ensemble ordonné de règles.
F = {R1, ...,Rn}
La première règle (R1) est la règle de plus haute priorité ; la dernière règle (Rn) est la règle de plus basse priorité.
La machine à formes reçoit en entrée : 1) une liste d'adresses et de longueurs qui délimitent le ou les flux d'entrée ; 2) une liste d'adresses et de longueurs qui délimitent la ou les zones de sortie ; 3) un pointeur vers une liste de forme(s) ; 4) un pointeur vers la position de départ du flux d'entrée ; et 5) un pointeur vers la position de départ de la zone de sortie. La Form Machine applique une forme à la chaîne d'entrée en émettant une chaîne de sortie dans la zone de sortie. La forme est appliquée de la manière suivante :
Étape 1 : R1 devient la règle courante.
Étape 2 : La règle courante est appliquée aux données d'entrée.
Étape 3 : a) Si la règle échoue, la règle de priorité immédiatement inférieure devient courante.
b) Si la règle réussit, la règle de plus haute priorité devient courante
c) Lorsque la règle de plus basse priorité échoue, la forme échoue et l'application de la forme aux données d'entrée se termine.
Étape 4 : Continuer à l'étape 2.
De plus, pendant l'étape 2, si le reste de la chaîne d'entrée est insuffisant pour satisfaire une règle, alors cette règle échoue et les résultats partiels ne sont pas émis. Si une règle remplit la chaîne de sortie, l'application de la forme se termine.
II. Règles
Une règle est une opération de remplacement de la forme :
left-hand-side -> right-hand-side
Les deux côtés d'une règle se composent d'une série de zéro ou plusieurs termes (voir ci-dessous) séparés par des virgules.
Le côté gauche de la règle est appliqué à la chaîne d'entrée à la position courante comme une opération de correspondance de motif. S'il décrit exactement l'entrée, 1) le pointeur de position d'entrée courant est avancé au-delà de l'entrée appariée, 2) le côté droit émet des données à la position courante dans la chaîne de sortie, et 3) le pointeur de position de sortie courant est avancé au-delà des données émises.
III. Termes
Un terme est une variable qui décrit la chaîne d'entrée à apparier ou la chaîne de sortie à émettre. Un terme a trois formats.
Format de terme 1
+---------------------------------------------------------------------+
| |
| name ( data replication . value : length ) |
| type expression expression expression |
| |
|_____________________________________________________________________|
N'importe lequel des champs peut être absent.
Le nom est un nom symbolique du terme au sens habituel des langages de programmation. C'est une seule lettre alphabétique minuscule, unique au sein d'une règle.
Le type de données décrit le genre de données que le terme représente. Il est membre de l'ensemble :
{D, O, X, A, E, B}
Les types de données ont les significations et les longueurs d'unité implicites suivantes :
Char. Meaning Length
----- -------- -------
D decimal number 1 bit
O octal number 3 bits
X hexadecimal number 4 bits
A ASCII character 8 bits
E EBCDIC character 8 bits
B binary number 1 bit
L'expression de réplication est un multiplicateur de l'expression de valeur. Une expression de réplication possède les formats suivants.
- une expression arithmétique des membres de l'ensemble :
{v(name), L(name) , numerals, programming variables}
Le v(name) est un opérateur de valeur qui génère une valeur numérique du type de données nommé et L(name) est un opérateur de longueur qui génère une valeur numérique de la longueur de chaîne nommée.
La variable de programmation est décrite au format de terme trois. Les opérateurs arithmétiques sont présentés ci-dessous et ont leurs significations habituelles.
{*, /, +, -}
ou 2) le terminal '#' qui signifie un multiple arbitraire de l'expression de valeur.
L'expression de valeur est la valeur unitaire d'un terme exprimée dans le format indiqué par le type de données. L'expression de valeur est répétée selon l'expression de réplication. Une expression de valeur a le format :
- identique à la partie 1) de l'expression de réplication, où là encore v(name) produit une valeur numérique
ou 2) un seul membre de l'ensemble
{v(name), quoted literal}
où v(name) produit une valeur de type de données (E ou A)). (Notez que la concaténation s'accomplit au moyen de plusieurs termes.)
L'expression de longueur est la longueur du champ contenant l'expression de valeur telle que modifiée par l'expression de réplication. Elle a les mêmes formats qu'une expression de réplication.
Ainsi, le terme
x(E(7.'F'):L(x)) est nommé x, est de type EBCDIC, a la valeur 'FFFFFFF' et est de longueur 7.
Le terme
y(A:8) du côté gauche d'une règle se verrait attribuer les 64 bits suivants de l'entrée comme valeur ; du côté droit, il ne ferait qu'avancer le pointeur de sortie de 64 positions de bit, car il n'a pas d'expression de valeur (contenu) permettant de générer des données dans la zone de sortie.
Format de terme 2
+---------------------------------------------------------------------+
| |
| name (label) |
| |
+---------------------------------------------------------------------+
L'étiquette est une référence symbolique à un terme précédemment nommé dans la règle. Elle a la même valeur que le terme portant ce nom.
L'opération d'identité ci-dessous illustre l'usage de la notation étiquette.
a(A:10) -> (a)
Le (a) du côté droit fait que le terme a est émis dans la zone de sortie. Cela équivaut à la règle ci-dessous.
a(A:10) -> (Av(a):L(a))
Format de terme 3
+---------------------------------------------------------------------+
| |
| name ( programming connective operand ) |
| variable expression |
| |
+---------------------------------------------------------------------+
Une variable de programmation est un élément de données contrôlé par l'utilisateur qui n'apparaît pas explicitement dans les flux d'entrée/sortie. Sa valeur peut être comparée aux données d'entrée, à des constantes, et servir à générer des données de sortie. Les variables de programmation sont des symboles grecs uniques en minuscules.
On les utilise : pour générer des indices, des compteurs, etc. dans la zone de sortie ; pour comparer des indices, des compteurs, etc. dans la zone d'entrée, et ; pour lier des règles de remplacement lorsque les données dépendent du contexte (expliqué plus loin).
Un connecteur est un membre de l'ensemble :
{<-, =, !=, >=, <=, <, >}
La flèche gauche indique le remplacement de la partie gauche par la partie droite ; les autres connecteurs sont des comparateurs.
L'expression d'opérande est une expression arithmétique des membres de l'ensemble :
{programming variables, v(name), l(name), numerals}
Par exemple, si la variable de programmation [alpha] a la valeur 0 et que la règle
a(H[alpha]:1) -> (a), ([alpha]<-[alpha]+1), (H[alpha]:1)
est appliquée exhaustivement à une chaîne de chiffres hexadécimaux
0 1 2 3 4 5
la sortie serait la chaîne hexadécimale
0 1 1 2 2 3 3 4 4 5 5 6 .
Remarque : la règle ci-dessus équivaut à
a(B[alpha]:4) -> (a), ([alpha]<-[alpha]+1), (B[alpha]:4)
IV. Restrictions et interprétations des fonctions de terme
Lorsqu'une règle réussit, une sortie est générée. Dans la règle
a(A:#),(A'/':1)->(Ev(a):74),(E'?':1)
on recherche dans la chaîne d'entrée un nombre arbitraire de caractères ASCII suivis d'un terminal '/'. Les caractères ASCII (a) sont convertis en EBCDIC dans un champ de 74 octets suivi d'un terminal '?'. Cela met en évidence trois problèmes :
-
Les termes de longueur arbitraire doivent être séparés par des littéraux, car les données ne sont pas spécifiques à un type.
-
Le # ne peut être utilisé que du côté gauche d'une règle.
-
Un schéma de remplissage/troncature est nécessaire.
Le schéma de remplissage/troncature est le suivant :
-
Caractère vers caractère (types : A, E) La sortie est justifiée à gauche, avec troncature ou remplissage (par des blancs) à droite.
-
Caractère vers numérique (A, E vers D, O, H, B)
-
Numérique vers caractère (D, O, H, B vers A, E)
-
Numérique vers numérique (D, O, H, B) La sortie est justifiée à droite, avec remplissage ou troncature à gauche. Le remplissage se fait avec des zéros si la sortie est numérique.