• Aucun résultat trouvé

4.4 Définition formelle du langage de transformation

4.4.1 Grammaire visuelle et syntaxe abstraite

Nous avons défini, dans le cadre de l’étude formelle du langage visuel pour la représentation de DTD ([221] et Annexe B), une grammaire basée sur une version légèrement étendue du formalisme des gram-maires relationnelles [236, 95]. Cette grammaire (voir la Définition 1 de l’article en Annexe B) définit un langage visuel représentant un sur-ensemble des phrases visuelles pouvant être engendrées à partir de la traduction de DTD. Informellement, cette grammaire autorise l’emboîtement (potentiellement infini) d’objets graphiques et de chaînes de caractères aux conditions suivantes :

– les objets contenant d’autres objets doivent être rectangulaires,

– l’ensemble des fils d’un objet est disposé soit horizontalement soit verticalement (alignement des centres géométriques), avec la condition supplémentaire que ces objets ne doivent pas se chevau-cher même partiellement,

– le rectangle englobant l’ensemble des fils (bounding box) est centré par rapport à l’objet parent, dont la taille est définie de manière à contenir l’ensemble de ses fils.

Définition formelle du langage de transformation 103

text

FIG. 4.16 : Exemples de phrases visuelles correctes

FIG. 4.17 : Exemples de phrases visuelles incorrectes

Nous donnons quelques exemples de phrases visuelles correctes et incorrectes. La figure 4.16 montre deux exemples de phrases correctes ; les objets fils d’un même élément sont alignés entre eux et centrés par rapport à leur parent. La figure 4.17 illustre deux phrases n’appartenant pas au langage : la première est incorrecte car une forme autre qu’un rectangle (le losange11) contient un autre objet et parce que deux objets se chevauchent partiellement ; la seconde est incorrecte car les fils du rectangle gris ne sont alignés ni verticalement ni horizontalement.

La définition formelle de cette grammaire est donnée dans l’annexe B. Une introduction au formalisme des grammaires relationnelles est proposée en annexe C. Sa lecture n’est cependant pas requise pour la compréhension de la suite de ce chapitre puisque nous travaillons directement sur des variantes de la syntaxe abstraite AS définie dans l’article mentionné précédemment (annexe B) et reprise ici.

Les propriétés du langage visuel décrit par cette grammaire ont été capturées dans une syntaxe abstraite nommée AS afin de simplifier les traitements effectués lors de la manipulation des structures visuelles. Il est en effet difficile de raisonner sur la grammaire, qui représente le langage de manière concrète et fournit par conséquent un niveau de détails (et donc de complexité) trop important par rapport aux traitements envisagées. La syntaxe AS simplifie les traitements formels en s’abstrayant de certaines questions spatiales de bas niveau, tout en conservant une sémantique visuelle fournie par la fonction de traduction T (annexe B) qui s’applique aux phrases appartenant à L(AS) (le langage généré par AS) et produit un ensemble d’objets graphiques. Dans l’article, une syntaxe abstraite plus spécifique DS

11Il s’agit en fait d’un carré orienté à 45 degrés ; nous désignons par la suite de telles formes par le terme de losange pour des raisons de commodité.

G → Shp(f, s) forme géométrique terminale

G → Txt(t) texte terminal

avec t une chaîne de texte et f une variable codant la forme et pouvant prendre les valeurs triangle, square, lozenge, star ou circle. s est un quadruplet dont les éléments représentent les attributs de style des objets graphiques. Le premier élément représente le style du contour de l’objet (continu ou discontinu) ; le deuxième la couleur de ce contour ; le troisième l’épaisseur du contour et enfin le dernier la transparence13de l’intérieur. Dans le cadre de VXT, seules certaines combinaisons seront autorisées :

Définition 2 (Valeurs autorisées des quadruplets de style)

s : hv1∈ {solid, dashed}, v2∈ Color, v3∈ {thin, thick}, v4∈ {notF illed, translucent}i s1 = hsolid, lightblue, thin, translucenti 

        

s2 = hsolid, lightblue, thin, notF illedi

s3 = hsolid, lightblue, thick, translucenti          

s4 = hsolid, lightblue, thick, notF illedi

s5 = hsolid, blue, thick, translucenti          

s6 = hsolid, blue, thick, notF illedi

s7 = hsolid, blue, thin, translucenti            

s8 = hsolid, blue, thin, notF illedi s9 = hsolid, red, thick, notF illedi s10 = hsolid, red, thin, notF illedi

s11 = hdashed, blue, thick, translucenti          

s12 = hdashed, blue, thin, translucenti                                    

Nous définissons alors deux syntaxes abstraites ASV et ASR, spécialisations de AS capturant les contraintes structurales liées respectivement aux VPMEs et aux productions de règles VXT.

12Ce langage est plus contraint que L(AS) ; il s’agit donc d’un sous-langage de L(AS).

Définition formelle du langage de transformation 105

Définition 3 (Syntaxe abstraite ASV pour les VPMEs)

GV → BV | SV E| SV T | SV Z| SV A HV E → BV | SV E| SV T | SV Z HV E → Ha(BV | SV E| SV T | SV Z, HV E) HV A → SV A| Ha(SV A, HV A) BV → Box(HV E| HV A, s) BV → Va(Txt(t), Box(HV E| HV A, s)) BV → Box(Va(HV E, HV A), s) BV → Va(Txt(t), Box(Va(HV E, HV A), s))

SV E → Shp(square, s) | Va(Txt(t), Shp(square, s))

SV T → Shp(lozenge, s)

SV Z → Shp(star, s)

SV A → Shp(triangle, s) | Va(Txt(t), Shp(triangle, s))

Nous notons alors L(ASV)le langage visuel des VPMEs généré par ASV. De la même façon, nous dé-finissons le langage visuel L(ASR)représentant les parties droites correspondant aux fragments d’arbre produits par les règles. Ce langage est généré par la grammaire ASRsuivante (le style associé aux objets graphiques est beaucoup plus simple pour les parties droites ; nous remplaçons donc pour des raisons de concision le quadruplet de style par une chaîne de caractères indiquant si l’objet est coloré en bleu (blue), s’il est gris (gray) ou bien hachuré (hatched)).

Définition 4 (Syntaxe abstraite ASRpour les productions)

GR → FR| Va(FR, GR)

FR → BR| SREF | SREW | SRT | SRC| SRAF | SRAW HRE → BR| SREF | SREW | SRT | SRC

HRE → Ha(BR| SREF | SREW | SRT | SRC, HRE) HRA → SRAF | SRAW

HRA → Ha(SRAF | SRAW, HRA)

BR → Va(Txt(t), Box(HRE | HRA,gray))

BR → Va(Txt(t), Box(Va(HRE, HRA),gray))

BR → Box(HRE | HRA,blue)

BR → Box(Va(HRE, HRA),blue)

BR → Box(HRE | HRA,hatched)

BR → Box(Va(HRE, HRA),hatched)

SREF → Shp(square, blue)

SREW → Va(Txt(t), Shp(square, gray))

SRT → Shp(lozenge, gray) | Shp(lozenge, blue)

SRC → Shp(circle, blue)

SRAF → Shp(triangle, blue)

et

Shpi(f, s)

Chaque règle VXT possède deux ensembles d’index disjoints référençant respectivement les nœuds de la VPME et les nœuds de la production (partie droite). Dans chacun de ces ensembles, l’index d’un nœud est unique et référence donc exactement un nœud dans l’un des arbres (VPME ou production). Par exemple,

Shp3(square, hsolid, blue, thin, notFilledi)

indique que ce nœud de type élément est référencé par l’index 3. Afin d’alléger la notation dans les traitements suivants, nous ne faisons apparaître ces indices (notés i, j et k) que quand ils sont nécessaires.

Correspondance entre index et sous-arbres

Nous allons avoir besoin dans les définitions suivantes de plusieurs fonctions retournant des sous-arbres de VPME en fonction de l’index et de la nature des nœuds. Nous avons vu précédemment que chaque nœud de type Shp(f, s) ou Box(X, s) est associé à un index unique dans l’ensemble des index associé à la VPME à laquelle le nœud appartient. Nous fixons, par convention, une contrainte supplé-mentaire : pour chaque VPME, le nœud contextuel est associé à l’index 0. Il n’y a par contre aucune contrainte sur la manière d’indexer les autres nœuds, hormis l’unicité des index.

Nous appelons alors i2v la fonction qui, étant donné une VPME et un index, retourne le sous-arbre dont le nœud racine a pour index la valeur passée en paramètre. Nous notons I l’ensemble des index.

Définition 5 (i2v : Fonction d’association index/sous-arbre)

i2v : L(ASV) × I → L(ASV)

Nous allons aussi avoir besoin d’une fonction utilisée lors de la manipulation d’arbres, notée gp pour get path qui, étant donné deux index associés à deux nœuds d’une même VPME, retourne le chemin à parcourir dans l’arbre pour atteindre le second nœud en partant du premier. Le résultat est fourni sous la forme d’une séquence contenant les index associés aux nœuds rencontrés sur ce chemin, les index du nœud origine et du nœud final inclus. La fonction est définie uniquement dans le cas où le deuxième nœud est un descendant du premier nœud ou bien égal à ce nœud. Elle fournit par conséquent uniquement des séquences représentant des chemins orientés de la racine vers les feuilles de l’arbre. Dans le cas où cette condition n’est pas vérifiée, c’est-à-dire que le premier nœud n’est pas un ancêtre du (ou égal au) second, la fonction retourne une séquence vide.

Définition formelle du langage de transformation 107

Définition 6 (gp : Génération de chemins entre deux nœuds)

gp : L(ASV) × I × I → I

Nous notons I le monoïde libre obtenu par la concaténation de l’ensemble des index. Nous utilisons pour l’accès aux membres la notation standard suivante :

sk

où k est un entier positif indiquant la position du membre dans le monoïde. Par convention, le premier élément est à l’index 0, donc s1désigne le deuxième élément.

Remarque : comme nous l’avons défini plus haut, seuls les nœuds de type Shp(f, s) ou Box(X, s)

sont indexés. Il en résulte que les index présents dans une séquence retournée par gp sont uniquement associés à des nœuds de ces deux types.

Enfin, toujours dans le but d’alléger les notations, nous introduisons la fonction gscn pour Get Subtree Containing Node, qui étant donné une VPME et deux index i et j retourne le sous-arbre dont la racine est un fils du nœud d’indice i et qui contient le nœud d’indice j :

Définition 7 (gscn : Génération de chemins entre deux nœuds)

gscn : L(ASV) × I × I → L(ASV)

gscn(v, i, j) = i2v(v, s1) avec gp(v, i, j) = s0 s1 . . . sn

Le contexte d’utilisation de cette fonction nous garantit que la séquence retournée par gp(v, i, j) contient au moins deux éléments, donc s1 sera toujours défini dans ce contexte. Nous utiliserons souvent cette fonction en assignant la valeur 0 à j, cette index étant par convention assigné au nœud contextuel de chaque VPME.

4.4.2 VPMEs et productions bien formées