Aller au contenu principal

Grammaires

Un automate fini est une description analytique d'un langage régulier : c'est un algorithme pour reconnaître les mots du langage. Les grammaires donnent une description générative d'un langage : elles explicitent des règles de construction des mots du langage. Nous connaissons déjà la notion de grammaire en langage naturel. Par exemple, en français, une phrase déclarative a la forme : "sujet" + "verbe" + "complément". La grammaire a pour rôle de fixer la structure des phrases. En informatique, les grammaires sont couramment utilisées pour définir la syntaxe des langages de programmation et pour construire les compilateurs.

Grammaire, dérivation, langage​

Une grammaire est un quadruplet G=(V,Σ,R,S)G=(V,\Sigma,R,S) où :

  • VV et Σ\Sigma sont deux alphabets disjoints. Les symboles de VV sont dits non terminaux, ceux de Σ\Sigma sont dits terminaux ;
  • R⊆(V∪Σ)∗×(V∪Σ)∗R \subseteq (V \cup \Sigma)^\ast \times (V \cup \Sigma)^\ast est un ensemble fini de règles (α,β)(\alpha,\beta) telles que α\alpha contient au moins un symbole non terminal ;
  • S∈VS \in V est le symbole non terminal initial.

Les symboles non terminaux (i.e. les symboles de VV) sont usuellement notés par des lettres majuscules A,B,…A,B,\ldots, alors que les symboles terminaux (i.e. les symboles de Σ\Sigma) sont représentés par des lettres minuscules a,b,…a,b,\ldots. L'ensemble RR définit les règles de substitution. Une règle (α,β)(\alpha,\beta) sera souvent représentée sous la forme α→β\alpha \rightarrow \beta. Elle signifie que β\beta peut être substitué à α\alpha. Le symbole non terminal initial est généralement noté SS. Lorsqu'une grammaire comporte plusieurs règles avec le même membre gauche, par exemple A→aAA \rightarrow aA et A→BbA \rightarrow Bb, on écrit souvent A→aA∣BbA \rightarrow aA \mid Bb pour simplifier.

Une grammaire G=(V,Σ,R,S)G=(V,\Sigma,R,S) dérive v∈(V∪Σ)∗v \in (V \cup \Sigma)^\ast à partir de u∈(V∪Σ)∗u \in (V \cup \Sigma)^\ast, noté u⇒vu \Rightarrow v, s'il est possible de décomposer u=xu′yu=xu'y et v=xv′yv=xv'y où u′→v′u' \rightarrow v' est une règle de RR. On note ⇒∗\Rightarrow^\ast la fermeture réflexive et transitive de ⇒\Rightarrow (dérivation en un nombre quelconque d'étapes).

Le langage généré par une grammaire G=(V,Σ,R,S)G=(V,\Sigma,R,S) est l'ensemble des mots dérivés depuis le symbole initial SS qui ne contiennent que des symboles terminaux : L(G)={ω∈Σ∗∣S⇒∗ω}\mathcal{L}(G)=\{\omega \in \Sigma^\ast \mid S \Rightarrow^\ast \omega\}.

Grammaires régulières et langages réguliers​

Dans cette section, on étudie les grammaires qui génèrent les langages réguliers.

Une grammaire G=(V,Σ,R,S)G=(V,\Sigma,R,S) est linéaire droite si toutes les règles de RR ont la forme A→ωBA \rightarrow \omega B ou A→ωA \rightarrow \omega pour A,B∈VA, B \in V et ω∈Σ∗\omega \in \Sigma^\ast. Elle est linéaire gauche si toutes ses règles ont la forme A→BωA \rightarrow B \omega ou A→ωA \rightarrow \omega.

On appelle grammaire régulière une grammaire qui est soit linéaire gauche, soit linéaire droite.

Théorème​

Un langage LL est régulier si et seulement s'il est généré par une grammaire régulière :

  • pour toute grammaire régulière G=(V,Σ,R,S)G=(V,\Sigma,R,S), il existe un automate fini AGA_G qui accepte le langage L(G)\mathcal{L}(G) ;
  • pour tout automate fini déterministe A=(Q,Σ,δ,q0,F)A=(Q,\Sigma,\delta,q_0,F), il existe une grammaire régulière qui génère le langage L(A)\mathcal{L}(A).

Au-delà des grammaires régulières​

Toutes les grammaires ne sont pas régulières. Il existe des grammaires (y compris linéaires, comme S→aSb∣εS \rightarrow aSb \mid \varepsilon) qui génèrent des langages non réguliers.

Le linguiste et informaticien Noam Chomsky a défini la classification suivante des grammaires.

Type 3​

Les grammaires régulières, dont les règles sont toutes linéaires droites (A→ωBA \rightarrow \omega B, A→ωA \rightarrow \omega) ou toutes linéaires gauches (A→BωA \rightarrow B\omega, A→ωA \rightarrow \omega), où A,B∈VA,B \in V et ω∈Σ∗\omega \in \Sigma^\ast. Le membre gauche d'une règle est seulement constitué d'un symbole non terminal. Le membre droit contient au plus un symbole non terminal, à droite (resp. à gauche) des symboles terminaux. Le langage généré par une grammaire régulière est régulier, et donc accepté par un automate fini.

Type 2​

Les grammaires hors contexte, dont les productions sont de la forme A→βA \rightarrow \beta où A∈VA \in V et β∈(V∪Σ)∗\beta \in (V \cup \Sigma)^\ast. Seul le membre gauche est contraint : il ne peut s'agir que d'un seul symbole non terminal. Le langage d'une grammaire hors contexte est accepté par un automate à pile (non déterministe).

Type 1​

Les grammaires contextuelles ont des productions de la forme α→β\alpha \rightarrow \beta, où α,β∈(V∪Σ)∗\alpha,\beta \in (V \cup \Sigma)^\ast, α\alpha contient au moins un symbole non terminal, et β\beta contient au moins autant de symboles que α\alpha : ∣α∣≤∣β∣|\alpha| \leq |\beta|. La règle S→εS \rightarrow \varepsilon est autorisée si SS n'apparaît en membre droit d'aucune règle. Les langages contextuels sont acceptés par des automates linéairement bornés.

Type 0​

Aucune restriction. Les langages définis par de telles grammaires sont reconnus par des machines de Turing, sans garantie de terminaison sur les mots qui n'appartiennent pas au langage (langages récursivement énumérables).

On peut montrer que les familles de langages associées à ces types sont incluses les unes dans les autres, mais non égales. Ainsi, tous les langages générés par une grammaire de type ii (1≤i≤31 \leq i \leq 3) peuvent être générés par une grammaire de type i−1i-1. De plus, pour chaque 0≤i≤20 \leq i \leq 2, il existe des langages générés par une grammaire de type ii mais par aucune grammaire de type i+1i+1. Il existe également des langages qui ne sont générés par aucune grammaire.

Arbre de dérivation, ambiguïté​

Les grammaires sont fréquemment utilisées pour décrire des langages naturels, des langages de programmation, ou encore des langages de description. Elles permettent de décrire de manière formelle ces langages et donc de construire des compilateurs pour ces langages. Le compilateur vérifie qu'un mot appartient au langage, et il reconstitue en général la structure de ce mot afin de pouvoir lui appliquer des transformations.

Un arbre de dérivation d'un mot ω\omega par une grammaire hors contexte G=(V,Σ,R,S)G=(V,\Sigma,R,S) est un arbre fini :

  • de racine SS ;
  • dont les feuilles sont étiquetées par des symboles terminaux (ou par ε\varepsilon) ;
  • dont les nœuds intermédiaires sont étiquetés par des symboles non terminaux ;
  • tel que, si un nœud nn étiqueté par un symbole non terminal A∈VA \in V possède les fils n1,…,nkn_1,\ldots,n_k dans cet ordre, alors A→n1…nkA \rightarrow n_1 \ldots n_k est une règle de GG ;
  • et tel que la concaténation des feuilles de l'arbre de gauche à droite donne le mot ω\omega.

Un arbre de dérivation explicite donc comment un mot est généré par la grammaire, en partant du symbole initial SS et en remplaçant successivement les symboles non terminaux à l'aide d'une des règles de la grammaire. Il s'agit d'une description structurée de la dérivation d'un mot par une grammaire, telle que définie précédemment.

Une grammaire G=(V,Σ,R,S)G=(V,\Sigma,R,S) est ambiguë s'il existe un mot ω∈Σ∗\omega \in \Sigma^\ast généré par GG pour lequel il existe (au moins) deux arbres de dérivation distincts. Une grammaire qui admet au plus un arbre de dérivation pour tout mot ω∈Σ∗\omega \in \Sigma^\ast est dite non ambiguë.

Déterminer si une grammaire hors contexte est ambiguë est un problème indécidable : aucun algorithme ne permet de le décider pour toute grammaire.