Sintaks : Ingénierie Dirigée par les Modèles Appliquée à l’Analyse et la Synthèse de Syntaxe Textuelle Michel Hassenforder
Model-Driven Analysis and Synthesis of Concrete Syntax Models 2006 – Genoa Sosym – en instance Pierre-Alain Muller Franck Fleurey Frédéric Fondement Michel Hassenforder Rémi Schneckenburger Sébastien Gérard Jean-Marc Jézéquel
Model-Driven Analysis and Synthesis of Concrete Syntax Frédéric Fondement Pierre-Alain Muller Franck Fleurey Michel Hassenforder Jean-Marc Jézéquel David Touzet Michel Hassenforder Pierre-Alain Muller Rémi Schneckenburger Sébastien Gérard
Plan Introduction Métamodèle de sintaks Sémantique lors de la synthèse Sémantique lors de l'analyse Exemples Conclusion
Introduction - Motivation En général : Comment créer un modèle conforme à un métamodèle Il existe des outils pour faire des métamodèles Tous l'outillage autour de ecore Il existe des outils pour faire des modèles Tous l'outillage généré avec ecore Dans le cadre de la création/lecture de programme conforme à un métamodèle Grammarware : compilateur (text -> AST -> Model) Modelware : text <-> Model
Introduction - Illustration Un métamodèle très simple Des syntaxes concrètes Type:String Type:User Type:Mail Attribute:From Attribute:To Attribute:Name Type Mail { From : User To : User } Type User { Name : String Type String; Mail@From (User) Mail@To (User) User@Name (String) String;
Processus Sintaks Transformation Bidirectionnelle Meta-Language (Mof, Kermeta,…) Conforme Conforme Métamodèle de Syntaxe concrète Métamodèle de Syntaxe abstraite Conforme Conforme Modèle de Syntaxe concrète Modèle Conforme Sintaks Texte Transformation Bidirectionnelle
Métamodèle de sintaks
Métamodèle de sintaks eClass and eStructuralFeature Rule Root Ponts vers le métamodèle cible Rule Classe abstraite de base Root Container de fragments (rule) Donne le point de départ
Métamodèle de sintaks Sequence Template Terminal Adornment Une collection ordonnée de règles Template Spécifie la classe à utiliser du métamodèle cible Spécifie la règle à appliquer Terminal Un texte connu et fixe lors de la modélisation Un symbol terminal dans le grammarware Adornment Un symbole de décoration invisible comme la fin de ligne ou la tabulation
Métamodèle de sintaks Value (abstraite) PrimitiveValue Constant Un ensemble de propriétés qu’il faut utiliser PrimitiveValue Une portion de texte qui provient d’une ou de plusieurs propriétés Assure la manipulation des types de base : Integer, String, Real, Boolean, … Constant Une valeur fixe connue à la modélisation qu’il faut affecter à une ou plusieurs propriétés ObjectReference Permet de manipuler les propriétés qui référencent un autre objet en utilisant une de ses propriétés comme clé (unique) RuleRef Permet l’invocation d’une règle typiquement un fragment possédé par Root Ce concept permet le partage de règles URIValue Concept interne de sintaks pour sa propre syntaxe concrète.
Métamodèle de sintaks Iteration Permet de gérer une propriété de type container Assure la gestion d’un éventuel séparateur
Métamodèle de sintaks Choice (Abstraite) Condition (Abstraite) Ce concept permet de modéliser des variations dans la formulation de la syntaxe concrète Il possède un ensemble de condition Condition (Abstraite) Ce concept permet de décrire une condition particulière sous la forme D’une valeur que doit prendre une 'expression‘ Une règle qu’il faut exécuter CustomCondition Permet de décrire la propriété qu’il faut tester PolymorphicCondition Permet de décrire la classe qu’il faut tester
Métamodèle de sintaks Choice (Abstraite) Alternative Ce concept permet de modéliser des variations dans la formulation de la syntaxe concrète Il possède un ensemble de condition Alternative La liste de conditions est exploitée une fois pour en sélectionner la plus pertinente Once (expérimental) La liste de conditions est exploitée répétitivement pour sélectionner toutes les plus pertinente (comparable au concept all dans un schéma XML)
Sintaks est bidirectionnel ! Synthèse Impression par descente récursive Visiteur en profondeur Analyse Compilateur par descente récursive Comme du LL(k) (k=0..*) Synthèse Modèle Texte Analyse
Sémantique lors de la synthèse Règle Sequence Un container de règle à invoquer en séquence Règle Terminal La valeur est ajoutée dans le flux de sortie Ajoute des espaces pour délimiter Règle Adornment Selon le cas soit une tabulation (tab) soit une fin de ligne (eoln) est inséré dans le flux de sortie Règle Template Le template ne fait que spécifier le type de l'objet La sous règle est invoquée pour générer le texte associé blabla … blabla … blabla … #1 #2 #3 blabla … blabla … Texte_fixe
Sémantique lors de la synthèse unObject Règle PrimitiveValue Extrait une propriété de l'objet courant Conversion en texte puis impression avec délimiteurs Règle Constant Aucun effet Règle ObjectReference Cherche l'objet référencé Cherche la propriété utilisée comme clé Conversion la valeur en texte puis impression avec délimiteurs Règle RuleRef Invoque la règle interne Règle URIValue Secret de fabrication Propriété = 10 blabla … blabla … 10 référence unObject leRéférencé clé = hello blabla … blabla … hello
Sémantique lors de la synthèse blabla … sép blabla … sép blabla … Règle Iteration La sous règle est invoquée pour chaque objet dans le container L’ordre utilisé est l’ordre du container Eventuellement un séparateur est inséré entre chaque invocation Règle Alternative Chaque condition est évaluée et la première à vraie déclenche la règle associée Règle Once Itération sur l’ensemble des conditions et chaque condition valide déclenche la règle associée #1 #2 #3 unObject prop1 = 10 prop2 = hello prop3 = true blabla … blabla … hello unObject prop1 = 10 prop2 = hello prop3 = true blabla … blabla … 10 hello true
Sémantique lors de la synthèse PolymorphicCondition [ valeur, metaClasse, objetCourant ] Que peut-on tester ? valeur="" objetCourant.class == metaClasse valeur="null" objetCourant.class == null valeur="any" objetCourant.class != null valeur="equals" objetCourant.class == metaClasse valeur="differs" objetCourant.class != metaClasse CustomCondition [ valeur, propriété, objetCourant ] valeur="" faux valeur="null" objetCourant.propriété == null valeur="any" objetCourant.propriété != null valeur="empty" ((String) objetCourant.propriété).length == 0 ((List) objetCourant.propriété).size == 0 valeur="filled" ((String) objetCourant.propriété).length != 0 ((List) objetCourant.propriété).size != 0 valeur="= v0" (String) objetCourant.propriété == v0 valeur="!= v0" (String) objetCourant.propriété != v0 Kermeta à l’aide …
Sémantique lors de l’analyse Analyseur lexical Supprime les espaces blancs (espace, tabulation, fin de ligne, …) Découpage mot par mot (un mot est délimité par des espaces blancs) Sait revenir à une position antérieur particulière Règle Sequence Un container de règle à invoquer en séquence sans échouer … Si on échoue, annulation de la séquence, backtracking pour restituer l’état initial Règle Terminal Une valeur est extraite du flux d’entrée Si elle correspond elle est consommée, sinon erreur Règle Adornment Rien, car les espaces blancs sont déjà supprimés Règle Template La metaClasse est instanciée et devient l’objet courant La sous règle est invoquée pour continuer l’analyse Si une erreur apparaît l’objet courant est oublié blabla … Texte_fixe blabla …
Sémantique lors de l’analyse unObject Règle PrimitiveValue Extrait un mot du flux d’entrée Conversion vers le type de la propriété cible Affectation à la propriété cible de l’objet courant Règle Constant Conversion de la valeur incluse vers le type de la propriété cible Règle ObjectReference Recherche dans le modèle courant avec la propriété clé un objet capable d’utiliser la clé Vérification que la valeur de la clé sur cet objet est celle extraite du flux Si oui affectation de la propriété cible de l’objet courant avec le référencé Sinon création d’un fantôme qui devra être résolu plus tard Règle RuleRef Invoque la règle interne Règle URIValue Secret de fabrication Propriété = … blabla … 10 blabla … unObject blabla … blabla … 10 Propriété = … Modèle référence leRéférencé clé = hello unObject blabla … hello blabla …
Sémantique lors de l’analyse blabla … sép blabla … sép 10 Règle Iteration La sous règle est invoquée jusqu’à échec Chaque invocation avec succès permet l’insertion dans le container Eventuellement un séparateur est analysé entre chaque invocation Règle Alternative Une Itération sur l’ensemble des conditions Chaque règle dans chaque condition est évaluée La première qui analyse avec succès stoppe l’itération Après chaque erreur, l’analyseur revient en arrière Règle Once Répétition de l’Itération sur l’ensemble des conditions Jusqu’à ce qu’une itération ne trouve pas de condition satisfaisante Condition Les 'expressions' ne sont pas évaluées #1 #2 (en EBNF : x ::= a | b | c) (en EBNF : x ::= (a | b | c)* )
Exemples Exemple 1 : Type Exemple 2 : Expression – notation préfixée Exemple 2 : Expression - notation infixée
Example 1 : Type / MetaModel & Model Type Mail { From : User To : User } Type User { Name : String Type String;
Exemple 1 : Type / Modèle de syntaxe concrète Travaille sur la classe 'Model' Opère sur la collection 'chidren' Travaille sur la classe 'Type' Mot clé : Type Extraction de la propriété 'name' La liste 'attributes' est vide Un simple point-virgule Des accolades pour encadrer la liste Un saut de ligne pour faire joli Opère sur la collection 'attributes' Travaille sur la classe 'Attribute' Extraction de la propriété 'name' Référence l’objet dans le modèle + qui possède l’attribut 'name' + qui a la valeur extraite du flux
Exemple 1 : Type / Modèle de syntaxe concrète Travaille sur la classe 'Model' Invoque le fragment … bon c’est le Template Type Travaille sur la classe 'Type' Invoque le fragment … bon c’est le Template Attribut Travaille sur la classe 'Attribute'
Exemple 2 : metamodèle d’Expression
Exemple 2 : Expression / préfixée Notation préfixée operator + ( operator * ( 3 , 2 ) , 1 ) En BNF expr ::= operator * ( expr , expr ) | operator + ( expr , expr ) | integer Notation infixée 3 * 2 + 1
Exemple 2 : Expression / infixée <AdditiveOp> ::= <Term> ‘+’ <Expr> <MultiplicativeOp> ::= <Factor> ‘*’ <Term> <NumberInteger> ::= [0-9]+ <Expression> ::= <AdditiveOp> | <Term> <Term> ::= <MultiplicativeOp> | <Factor> <Factor> ::= <NumberInteger>
Spécification une syntaxe concrète textuelle Mapping bidirectionnel Conclusion Spécification une syntaxe concrète textuelle Mapping bidirectionnel Syntaxe concrète vers syntaxe abstraite Syntaxe abstraite vers syntaxe concrète Un outil Lecture par descente récursive Impression par visite en profondeur