Syntax diagrams

Un article de SmartEiffelWiki, l'encyclopéde libre.

L'ensemble des diagrammes syntaxiques du langage Eiffel.


Tous les éléments syntaxiques par ordre alphabétique : Agent_creation, Assertion, Assignment, Binary_operator, Call, Check, Class_declaration, Class_name, Class_type, Clients, Comment, Compound, Create_expression, Create_instruction, Creation_clause, Current, Debug, Entity_declaration_list, Expression, Feature_clause, Feature_declaration, Feature_name, Formal_generic_list, If_then_else, Infix_operator, Inspect, Instruction, Loop, Manifest_notation, Manifest_string, New_export_item, Open_target_or_operand, Parent_list, Parent_type, Precursor_call, Prefix_operator, Result, Retry, Routine, Routine_body, Type, Unary_operator, Unqualified_call, Void, Writable.



Comment pour les commentaires

Un commentaire commence par deux tirets consécutifs -- et se termine en fin de ligne. Pour prolonger le commentaire sur la ligne suivante, il faut répéter la sequence -- et ainsi de suite :

Comment

À l'intérieur des commentaires, la convention pour mettre en valeur ce qui correspond à des entités Eiffel (i.e. variables, paramètres et noms de primitives) consiste à encadrer le nom en question entre ` et ' comme par exemple :

-- Here `my_variable' is supposed to be bla bla bla ...

Cette convention permet aux outils comme eiffeldoc, short ou aussi emacs de différencier visuellement, par exemple avec une autre couleur, le fait que my_variable correspond à un identifateur dans le code Eiffel. attention, cette convention ne s'applique pas aux noms de classes (Class_name) qui ne doivent pas être mis entre quotes, mais saisis normalement, c'est à dire avec des majuscules comme dans :

-- My FOO clas is bla bla bla bla ...

Notez également que les commentaires peuvent suivre une syntaxe similaire à ce wiki ; dans ce cas, l'outil eiffeldoc s'occupera de transformer vos étoiles en puces et vos crochets en liens.

Par exemple, le commentaire suivant affiché par eiffeldoc aurait pour effet de nous renvoyer ici même :

-- See also [[Syntax_diagrams#Comment]]

Class_declaration : définition d'une classe

Class_declaration

Ce schéma donne l'organisation globale d'une classe. Notons qu'une classe doit toujours être mise toute seule dans un fichier dont le nom correspond exactement au nom de cette classe en caractères minuscule avec comme extension le suffixe ".e". Par exemple, le texte source de la classe ARRAY doit être dans le fichier "array.e". La classe LINKED_LIST doit être dans le fichier "linked_list.e".

Si la définition de la classe commence par le mot clef deferred c'est qu'il s'agit d'une classe abstraite. Si la classe commence par le mot clef expanded c'est qu'il s'agit d'une classe correspondant à des objets expanded.

En plus de la traditionnelle liste de parents après le mot clef inherit il est également possible d'indiquer une liste de parents après le mot clef insert. Voir la page concernant les règles de typage pour plus d'informations.

Autres éléments, navigation: Assertion, Class_name, Creation_clause, Feature_clause, Formal_generic_list, Manifest_string, Parent_list.

Formal_generic_list : paramêtres formels génériques

Formal_generic_list

On se sert de ce schéma uniquement si la classe que l'on est en train de définir doit être générique, c'est à dire s'il s'agit d'une classe qui dépend d'un ou plusieurs paramètres formels génériques. Voici quelques exemples de classes génériques de notre bibliothèque : ARRAY[E_], COLLECTION[E_], DICTIONARY[K_, K_] ou encore SET[E_] par exemple.

Dans ce cas, l'Identifier est le nom du paramètre formel générique et, par simple convention, il s'agit en général d'une simple lettre majuscule suivie d'un caractère _ (voir Class_name). La partie Class_type quand elle est utilisée, correspond à la contrainte générique.

Autres éléments, navigation: Class_type.

Parent_list  liste des ancêtres

Parent_list

Autres éléments, navigation: Feature_name, New_export_item.

New_export_item : changement du statut d'exportation

New_export_item

Autres éléments, navigation: Clients, Feature_name.

Creation_clause : liste des constructeurs

Creation_clause

Autres éléments, navigation: Clients, Comment, Feature_name.

Feature_clause

Feature_clause

Autres éléments, navigation: Clients, Comment, Feature_declaration.

Clients , pour doser l'exportation

Clients

Le diagramme Clients sert à indiquer les autorisations d'utilisation de primitives. L'utilisation du diagramme Clients la plus courante sert, à partir du diagramme Feature_clause, à décider depuis quelle classe il est autorisé d'utiliser une primitive. La même syntaxe Clients sert également à indiquer les classes qui ont ou pas le droit de créer des objets de la classe englobante (soit à partir du diagramme Creation_clause soit à partir du diagramme New_export_item). Dans tous les cas, il s'agit d'autoriser ou non une classe donnée à faire quelque chose ou pas. Le principe reste le même.

Pour n'autoriser aucune classe, il suffit d'utiliser une liste vide et donc de noter {}, soit, par exemple lorsque l'on se prépare à définir des primitives ne devant être utilisable que dans la classe courante, il faut écrire :

feature {}

Si l'on souhaite définir des primitives qui peuvent être appelées depuis la classe FOO, il faut par exemple d'indiquer :

feature {FOO}

Pour autoriser à la fois FOO et BAR :

feature {FOO, BAR}

Notons que les autorisations d'exportations sont toujours héritées. Si par exemple on autorise la classe COLLECTION à utiliser quelque chose, alors, toutes ses sous classes héritent du pouvoir accordé. Ainsi, indiquer COLLECTION dans une liste Clients transmet automatiquement l'autorisation aux sous-classes (ARRAY, RING_ARRAY, FAST_ARRAY, LINKED_LIST, etc).

Par conséquent, comme la classe ANY est la racine commune de toutes les classes, si l'on souhaite autoriser l'utilisation d'une série de primitives depuis n'importe quelle classe, il suffit de noter :

feature {ANY}

Toute définition de primitive située après l'indication {ANY} d'exportation est utilisable depuis n'importe quelle classe.

Autres éléments, navigation: Class_name.

Feature_declaration : définition d'une primitive

Feature_declaration

Ce diagramme décrit la définition des primitives : attributs, fonctions et procédures. Le mot clef frozen permet d'indiquer que la définition en question ne pourra pas être redéfinie dans les sous-classes.

Dans le cas de la définition d'une constante, Manifest_constant doit uniquement correspondre à une constante dont le type est un type pris dans l'ensemble suivant : { BOOLEAN, CHARACTER, INTEGER_8, INTEGER_16, INTEGER_32, INTEGER, INTEGER_64, REAL_32, REAL_64, REAL, REAL_80, REAL_128, REAL_EXTENDED, STRING, UNICODE_STRING }. Pour avoir tous les détails en ce qui concerne la notation des constantes, lisez le fichier SmartEiffel/tutorial/manifest_notation.e.

Autres éléments, navigation: Entity_declaration_list, Feature_name, Routine, Type.

Routine

Routine

Se diagramme correspond à la définition des routines : procédures et fonctions.

La branche obsolete permet d'étiqueter une routine comme étant obsolete, c'est à dire d'indiquer qu'une routine ne devrait plus être utilisée. La chaîne de caractères qui suit le mot clef obsolete sert à indiquer la raison pour laquelle cette routine est obsolete. L'utilisation d'une routine obsolete est signalée par les outils de compilation. Notons également, qu'une routine obsolete n'est plus affiché par l'outil short afin de ne pas promouvoir son utilisation.

La branche require correspond à la précondition de la routine.

La branche local correspond à la déclaration des variables locales de la routine. Toutes les variable locales de la routine doivent être déclarée à cet endroit.

La branche ensure correspond à la postcondition de la routine.

La branche rescue permet de rattraper les éventuelles exceptions.

Autres éléments, navigation: Assertion, Compound, Entity_declaration_list, Feature_name, Manifest_string. Routine_body.

Routine_body

Routine_body

En prenant la branche deferred on indique que la routine que l'on est en train de définir est abstraite. On utilise cette possibilité lorsque l'on a pas assez d'informations dans la classe englobante pour implanter la routine en question. Dans ce cas, on laisse le soin au sous-classes de donner la définition qui convient pour cette routine qui est bien entendu destinée à être héritée.

Inversement, passer par la branche do permet de donner le corps de la routine sous la forme d'une liste d'instructions. Notons qu'il ne faut pas confondre une routine avec un corps vide (i.e. do sans instruction) avec une routine abstraite (i.e. deferred).

La branche once permet de définir une routine à exécution unique. Quelquesoit le nombre d'instances de la classe englobante, cette routine ne sera exécutée qu'une seule fois au maximum. Au maximum, dans une bibliothèque de classes, il y a autant d'exécution de routines once que d'écritures du mot clef once.

Dans le cas d'une fonction once, le résultat calculé lors de la première et unique évaluation est mémorisé de manière interne. Tout les appels qui suivront seront remplacés par la valeur mémorisée lors du premier appel. Une fonction once est la seule façon en Eiffel de conserver une donnée globale. Pas de variables globales en Eiffel.

La branche external sert à indiquer que la routine que l'on est en train de définir est en fait une brique de base prise en compte par le compilateur ou bien encore qu'il s'agit d'une routine écrite dans un autre langage qu'Eiffel.

Autres éléments, navigation: Compound, Manifest_string.

Entity_declaration_list

Entity_declaration_list

Ce schéma sert à la fois dans le cas d'une liste de déclaration de variables locales (voir Routine) et pour la déclaration des paramètres des routines (voir FeatureDeclaration). Ainsi, dans ce schéma, Identifier est soit le nom d'une variable locale, soit le nom d'un paramètre d'une méthode. Dans tous les cas, Identifier est uniquement composé de caractères minuscules avec en plus la possibilité d'utiliser le caractère '_' underscore.

Autres éléments, navigation: Type.

Type : toutes les notations de types

Type

Ce diagrame indique toutes les notations utilisables pour les noms des types.
Une notation incluant le mot clef like correspond à ce qu'on appelle dans le jargon Eiffel, un type ancré, c'est à dire à un type qui dépend d'une autre entité. Dans ce cas, Identifier doit correspondre soit au nom d'une autre fonction de la classe, d'un autre attribut ou encore, uniquement lorsque l'on est en train de définir une routine, au nom d'un des paramètres de la routine en question.

L'élément Formal_generic_name doit être un des éléments de la liste des arguments génériques formel (Formal_generic_list) de la classe englobante.

Autres éléments, navigation: Class_name.

Class_name , nom de classe

Un nom de classe ne doit comporter que des lettres et chiffres en majuscules ainsi qu'éventuellement le caractère '_' underscore. Le premier caractère doit être une lettre. Les bonnes habitudes consistent à ne pas utiliser deux caractères '_' de façon consécutive (un '_' juste après un '_'). Enfin, l'utilisation de '_' en tant que dernier caractère du nom doit être évité (nous réservons cette convention pour les noms des paramètres formels génériques comme E_ par exemple).

Voici quelques exemples de noms de classe correctement écrits : ARRAY, INTEGER_64, ANY, LINKED_LIST ou TWO_WAY_LINKED_LIST.

Class_type : type simple, sans ancrage, complètement désigné

Class_type

Une notation de la catégorie Class_type est exclusivement composée de nom de classes existantes. L'ensemble des types que l'on peut dénoter avec Class_type est un sous-ensemble de l'ensemble des types que l'on peut dénoter avec Type.

Autres éléments, navigation: Class_name.

Parent_type : les types autorisés pour les parents d'une classe

Parent_type

Une notation de la catégorie Parent_type correspond aux notations de types autorisées pour les parents d'une classe (Parent_list). L'élément Formal_generic_name doit être un des éléments de la liste des arguments génériques formel (Formal_generic_list) de la classe englobante.

L'ensemble des types que l'on peut dénoter avec Parent_type est un sous-ensemble de l'ensemble des types que l'on peut dénoter avec Type. L'ensemble des notations de Parent_type comprend toutes les notation du diagramme Class_type.

Autres éléments, navigation: Class_name.

Binary_operator

Following operators can be redefined in your own class:

Binary_operator

Infix_operator

Infix_operator

Autres éléments, navigation: Binary_operator, Free_operator.

Prefix_operator

Prefix_operator

Autres éléments, navigation: Unary_operator, Free_operator.

Unary_operator

Unary_operator

Writable : ce qui peut être modifié

Ce que nous appelons Writable correspond à ce qui peut se retrouver par exemple à gauche de l'opérateur d'affectation :=. Il n'y a jamais d'expression complexe du coté gauche d'un symbole d'affectation. Seule les trois possibilités suivantes sont valides en tant que Writable :

  • le nom d'une variable locale de la méthode englobante,
  • le nom d'un attribut modifiable de Current,
  • et enfin, la variable Result utilisée pour préparer la valeur de retour de la fonction englobante.


Notons qu'il est par exemple interdit de placer le nom d'un argument de la méthode englobante à gauche d'un symbole d'affectation. Un argument de méthode n'est pas un Writable. Comme indiqué précédemment, il n'y a que trois possibilités : variable locale, attribut modifiable ou Result.

Feature_name

Feature_name

Un nom de primitive est soit un nom ordinaire, soit un nom d'opérateur binaire (branche infix), soit enfin, le nom d'un opérateur unaire préfixé (branche prefix). Pour avoir des exemples de méthodes dont le nom est en fait un opérateur, regardez par exemple les classes BOOLEAN ou CHARACTER par exemple.

Autres éléments, navigation: Infix_operator, Prefix_operator.

Compound

Compound

Autres éléments, navigation: Instruction.

Instruction

Instruction

Voir aussi la définition du terme instruction dans le glossaire.

Autres éléments, navigation: Assignment, Call, Check, Create_instruction, Debug, If_then_else, Inspect, Loop, Precursor_call, Retry.

Assignment : affectation

Assignment

Autres éléments, navigation: Expression, Writable.

Call : appel de procédure ou de fonction et lecture d'attribut

Call

Such a construct can be either an Expression or an Instruction.

Autres éléments, navigation: Expression, Unqualified_call.

Precursor_call : appel de la définition héritée

Precursor_call

Cette notation réalise l'appel à la définition héritée de la routine englobante. La notation Precursor n'est acceptée qu'à l'intérieur d'une routine en cours de redéfinition. L'appel de la version héritée s'effectue avec le même objet courant (avec Current). La signature de l'appel Precursor doit respecter la signature de la routine englobante. Ainsi, un appel à Precursor est une Expression lorsque l'on est à l'intérieur d'une fonction et est une Instruction lorsque l'on est à l'intérieur d'une procédure.

La branche Parent_type ne sert qu'en cas d'ambiguité en raison de l'héritage multiple, c'est à dire lorsqu'il existe plusieurs définitions héritée.

Pour les explications concernant la branche $, reportez vous à Unqualified_call.

Autres éléments, navigation: Expression, Parent_type.


Loop : la seule façon d'écrire une itération (une boucle)

Loop

Autres éléments, navigation: Assertion, Compound, Expression.

If_then_else : instruction conditionelle

If_then_else

Autres éléments, navigation: Assertion, Compound, Expression.

Inspect : sélection à plusieurs branches

Inspect

The order in which the when branches are written does not influence the effect of an inspect instruction.

Also note that the Expression can only be of type INTEGER, CHARACTER or STRING. All used Constants must have the same type as the type of Expression. Furthermore, all constants must be statically computable in order to allow the compiler to check for disjunction of various when parts (only one Compound is ever selected).

By writing no else part at all (no keyword else used), you state that you do not expect the Expression ever to take on a value not covered by the inspect constants. If your expectations prove wrong, the effect is to trigger a run-time error when the code is compiled with appropriate options.

Autres éléments, navigation: Expression, Compound.

Create_instruction

Create_instruction

See also the Create_expression variant form.

Autres éléments, navigation: Type, Unqualified_call, Writable.

Check_list : liste de vérifications

A check instruction helps express a property that you believe will be satisfied whenever system execution reaches this instruction.

check

Autres éléments, navigation: Assertion.

Debug , pour placer du code de débogage

The Debug instruction serves to request the conditional execution of a certain sequence of Instructions, depending on a compilation option.

Debug

Autres éléments, navigation: Compound, Instruction.

Retry pour les exceptions

L'instruction retry concerne uniquement la programmation du traitement des exceptions. L'instruction retry n'est valide qu'à l'intérieur de la clause rescue de la routine englobante. La forme d'une instruction retry est simplement :

Retry

L'effet de retry consiste à reprendre l'exécution de la routine englobante presque comme si on repartait de zéro. En fait, la précondition (require) est bien revérifiée mais les variables locales, Result inclu, conservent leurs valeurs.

Expression

Expression


Voir aussi la définition du terme expression dans le glossaire.

Autres éléments, navigation: Agent_creation, Binary_operator, Call, Create_expression, Current, Manifest_notation, Open_target_or_operand, Result, Type, Unary_operator, Void, Writable.

Current , l'expression qui désigne l'objet courant

Et cette Expression denote l'objet courant, Current, noté simplement :

Current

Void , l'expression qui indique l'absence d'objet

La notation est simplement :

Void

Lisez la page spéciale sur Void pour avoir tous les détails.

Result , la variable locale pour préparer le résultat des fonctions

La variable Result n'est valide que lorsque l'on est dans une définition de fonction. La notation est simplement :

Result

La variable Result sert à préparer la valeur qui doit être retournée lorsque la fonction en question terminera son exécution. Le type qui est automatiquement attribué à Result est le type résultat de cette fonction. En fait, Result s'utilise comme on utilise une variable locale ordinaire. Comme une variable locale, Result est automatiquement initialisée avec la valeur par défaut pour le type correspondant (voir la partie sur l'initialisation automatique). Manipuler Result, même à gauche du signe d'affectation, ne provoque en aucun cas la sortie de la fonction englobante : c'est comme une variable locale.

Manifest_notation

Ces notations concernent les constantes du genre :

  • True et False pour le type BOOLEAN,
  • 'A', 'B', 'C', ... pour le type CHARACTER,
  • 1, 2, 3, ... pour le type INTEGER,
  • ...

Reportez vous au fichier SmartEiffel/tutorial/manifest_notation.e pour avoir une explication détaillée ainsi que des exemples pour toutes les notations concernant les types : BOOLEAN, CHARACTER, INTEGER, REAL, STRING and UNICODE_STRING.

De plus, le même fichier, SmartEiffel/tutorial/manifest_notation.e, contient également les exemples et les explications concernant la creation d'objet pour les types ARRAY, FAST_ARRAY, RING_ARRAY, LINKED_LIST, HASHED_DICTIONARY, HASHED_SET, etc.

Manifest_string

Manifest_string

Pour dénoter la creation d'une nouvelle chaîne de caractères (initialisée avec du texte) de type STRING. Pour avoir tous les détails sur les différents caractères d'échappement à utiliser dans la partie String, ainsi que sur les possibilités d'écriture sur plusieurs lignes, lire le fichier SmartEiffel/tutorial/manifest_notation.e.

Create_expression

Create_expression

Ce schéma correspond à la forme syntaxique de create en tant qu'expression : un nouvel objet du Type en question est retourné par cette Create_expression. Voir aussi la variante Create_instruction.

Autres éléments, navigation: Type, Unqualified_call.

Agent_creation

Agent_creation

Une expression Agent_creation permet de construire un object que l'on appelle un agent et qui correspond à une Expression dont l'évaluation est retardée. Le type d'un agent est soit PROCEDURE, FUNCTION ou encore PREDICATE. Voir SmartEiffel/tutorial/agent pour des exemples et plus d'explications.

Autres éléments, navigation: Expression, Open_target_or_operand.

Open_target_or_operand

Open_target_or_operand

Une expression Open_target_or_operand n'a de sens que dans le cadre d'une création d'agent (voir Agent_creation). Une expression Open_target_or_operand dénote une opérande dont la valeur n'est pas encore connue au moment de la création de l'agent.

Autres éléments, navigation: Type.

Unqualified_call

Unqualified_call

Quand il n'est pas précédé d'une cible explicite (voir le diagramme Call), un appel non qualifié, Unqualified_call, concerne en fait l'objet courant, Current. Il peut s'agir à la fois d'une Expression ou bien d'une Instruction.

Dans ce schéma, Identifier_1 est le nom de la primitive (fonction, procédure ou attribut) qui doit être appelée. En cas d'absence de parenthèses, Identifier_1 est soit un attribut soit une fonction sans argument, soit encore une procédure sans argument. Quand des parenthèses, sont utilisées, Identifier_1 est forcément soit une procédure avec au moins un argument, soit une fonction avec au moins un argument.

La partie avec Identifier_2 n'est pas d'un usage très fréquent et concerne l'interfaçage avec les autres langages (du code écrit en langage C par exemple). Le caractère $ qui précède sert à marquer le fait que l'on souhaite passer l'adresse de Identifier_2. Ne sont valides que les cas où Identifier_2 correspond à une variable locale de la routine englobante, ou Result, ou enfin, quand Identifier_2 est un attribut de Current.

Autres éléments, navigation: Expression.

Assertion

Assertion

L'essentiel dans une assertion, c'est bien entendu l'Expression qui doit être une expression à résultat booléen, c'est à dire une expression de type BOOLEAN. Le principe consiste à écrire une expression sensée être toujours vraie, de valeur True, lors de l'exécution, d'où le nom d'assertion.

Dans ce schéma, Identifier est juste une étiquette donnée avec l'assertion. Cette étiquette est optionelle et ne sert que lorsque le code de l'Expression n'est pas évident à comprendre. Notons que l'étiquette Identifier est imprimée en cas de violation de l'assertion en complément (ou en remplacement) du code qui n'est pas évident. La syntaxe à utiliser pour Identifier est la même que pour les variables locales, les attributs ou les noms d'arguments : on utilise uniquement des caractères en minuscule et comme d'habitude, si besoin le caractère '_' underscore.

Lorsque l'on est vraiment pas capable d'écrire une Expression (ce qui est plutôt une mauvaise nouvelle) le commentaire Comment de remplacement est équivalent à la constante True.

Notons finalement que le point virgule utilisé comme séparateur peut être considéré comme équivalent à l'opérateur logique and de la classe BOOLEAN entre les différentes assertions.

Autres éléments, navigation: Comment, Expression.

Outils personels
Autres langues