Chapitre 3 Syntaxe et sémantique
Chapitre 3: Sujets Introduction Décrire la syntaxe Méthodes formelles de description Grammaires avec attributs Décrire la signification des programmes: la sémantique
Introduction Syntaxe: la forme ou la structure des expressions, énoncés, et autres composantes d'un langage Sémantique: la signification des expressions, énoncés, et autres composantes La définition d'un langage est donnée par sa syntaxe et sa sémantique Qui utilise la définition? Les concepteurs Ceux qui effectuent l'implémentation Les programmeurs (usagers)
Décrire la syntaxe: Terminologie Un mot est une chaîne de caractère sur un alphabet donné Un langage est un ensemble de mots Un lexème est la plus petite unité lexicale d'un langage (e.g., *, somme, begin). On peut voir un programme comme une suite de lexèmes. Les lexèmes sont divisés en groupes appelés token (e.g., identificateur, opérateur)
Décrire la syntaxe: exemple index = 2 * count + 17; lexèmes tokens index identificateur = op_affectation 2 litéral_int * op_mult count identificateur + op_add 17 litéral_int ; point_virgule
Définition formelle des langages Reconnaisseurs Programme qui lit un mot d'entrée et décide si le mot appartient au langage Exemple: l'analyseur syntaxique d'un compilateur Chapitre 4 Générateurs Système permettant de générer les mots du langage On peut déterminer si la syntaxe d'un mot appartient au langage en le comparant à la structure du générateur. Exemple: Grammaires formelles
Méthodes formelles pour décrire la syntaxe Grammaires hors-contextes Méthode la plus utilisée pour décrire la syntaxe d'un langage Grammaire HC étendues Améliore la lisibilité et la facilité d'écriture Grammaires et reconnaisseurs
Grammaire et forme de Backus-Naur Grammaires génératives Développées par Noam Chomsky au milieu des années 50 Les générateurs de langages servent à décrire la syntaxe des langues naturelles Définie une classe de langages: les langages hors-contextes
Forme de Backus-Naur (BNF) métalangage utilisé pour décrire un autre langage Inventé par John Backus pour décrire Algol 58 (simplifié par la suite par Peter Naur) équivalent aux grammaires HC
Introduction aux grammaires Deux types de symboles: Terminaux: lexèmes ou tokens Non-terminaux: variables Grammaire: collection de règles permettant de substituer un non- terminal par une suite de symboles (terminaux et non- terminaux)
Les règles Une règle possède une partie gauche et une partie droite (séparées par une flèche) La partie droite est un non-terminal La partie gauche est une suite de symboles (terminaux et non-terminaux) Une grammaire est un ensemble fini de règles et possède une variable particulière que l'on appelle symbole de départ. Une variable (ou non-terminal) peut apparaître à la gauche de plusieurs règles <stmt> --> <single_stmt> <stmt> --> begin <stmt_list> end
Description d'une liste Une liste de longueur variable peut être décrite en utilisant la récursion: <stmt_list> <single_stmt> | <single_stmt> ; <stmt_list> Une dérivation est l'application répétée de règles qui commence avec le symbole de départ et se termine avec une séquence de terminaux.
Exemple d'une grammaire <program> <stmts> <stmts> <stmt> | <stmt> ; <stmts> <stmt> <var> = <expr> <var> a | b | c | d <expr> <term> + <term> | <term> - <term> <term> <var> | const
Exemple de dérivation <program> <stmts> <stmts> <stmt> | <stmt> ; <stmts> <stmt> <var> = <expr> <var> a | b | c | d <expr> <term> + <term> | <term> - <term> <term> <var> | const <program> => <stmts> => <stmt> => <var> = <expr> => a =<expr> => a = <term> + <term> => a = <var> + <term> => a = b + <term> => a = b + const
Dérivation À chaque étape d'une dérivation, on obtient un mot appelé forme sententielle. Une phrase est une forme sententielle ne contenenant que des terminaux Une dérivation à gauche (leftmost derivation) en est une où, à chaque étape, on applique une règle à la variable la plus à gauche de la forme sententielle.
Arbre syntaxique (Parse Tree) Représentation d'une dérivation <program> <stmts> <stmt> <var> = <expr> a <term> + <term> <var> const b
Ambiguïté dans une grammaire Une grammaire est ambiguë s'il existe une forme sententielle pouvant être générée par deux arbres syntaxiques différents.
Exemple d'ambiguïté <expr> <expr> <op> <expr> | const <op> / | -
Exemple d'ambiguïté <expr> <expr> <op> <expr> | const <op> / | - <expr> <expr> <op> <expr> <expr> <op> <expr> const - const / const
Exemple d'ambiguïté <expr> <expr> <op> <expr> | const <op> / | - <expr> <expr> <expr> <op> <expr> <expr> <op> <op> <expr> <expr> <op> <expr> <expr> <op> <expr> const - const / const const - const / const
Enlever l'ambiguïté d'une grammaire On doit modifier la grammaire pour représenter la priorité des opérateurs: <expr> <expr> - <term> | <term> <term> <term> / const| const <expr> <expr> - <term> <term> <term> / const const const
Associativité des opérateurs L'associativité des opérateurs peut aussi être représenté par la grammaire: <expr> -> <expr> + <expr> | const (ambiguë) <expr> -> <expr> + const | const (non ambiguë) <expr> <expr> <expr> + const <expr> + const const
Grammaires HC étendues Parties optionnelles placées entre crochets [ ] <selection> if (<expr>) <statement> [else <statement>] Alternatives placées entre parenthèses et séparées par une barre verticale <term> <term> (+|-) const Répétitions (0 où plus) sont placées entre accolades { } <ident> letter {letter|digit}
Grammaires: HC vs HC étendue <expr> <expr> + <term> | <expr> - <term> | <term> <term> <term> * <factor> | <term> / <factor> | <factor> HC étendue <expr> <term> {(+ | -) <term>} <term> <factor> {(* | /) <factor>}
Grammaires attribuées Les grammaires hors-contextes ne peuvent pas décrire tous les aspects syntaxiques d'un langage de programmation. Exemple 1: En Java un point-flottant ne peut pas être affecté dans un entier. Si on tenait compte de toutes les contraintes de ce type, alors on obtiendrait une grammaire énorme et inutilisable. Exemple 2: Il est impossible avec une grammaire HC de préciser qu'une variable doit être déclarée avant d'être utilisée.
Sémantique Contrairement à la syntaxe, il n'y a pas de formalisme largement répandu et accepté permettant de décrire la sémantique d'un langage de programmation. 3 principales méthodes: Sémantique opérationelle: On traduit les instructions dans un langage clair s'exécutant sur une machine virtuelle. Sémantique axiomatique: On utilise la logique mathématique pour indiquer la signification des instruction. Aussi utilisé pour démontrer l'exactitude des programmes. Sémantique dénotationelle: La plus rigoureuse des méthodes. Utilise la théorie des fonctions récursives.