Étant donné la quantité de matériel qui tente d'expliquer ce qu'est une grammaire sans contexte (CFG), j'ai trouvé étonnant que très peu (dans mon échantillon, moins d'un sur 20) expliquent pourquoi de telles grammaires sont appelées "contexte". libre". Et, à mon avis, aucun ne réussit à le faire.
Ma question est la suivante: pourquoi les grammaires sans contexte sont-elles appelées sans contexte? Qu'est-ce que "le contexte"? J'avais l'intuition que le contexte pourrait être constitué d'autres constructions de langage entourant le construit actuellement analysé, mais cela ne semble pas être le cas. Quelqu'un pourrait-il fournir une explication précise?
Réponses:
Cela signifie que toutes ses règles de production ont un seul non-terminal sur leur gauche.
Par exemple, cette grammaire qui reconnaît les chaînes de parenthèses identiques ("()", "() ()", "(()) ()", ...) est sans contexte:
Le côté gauche de chaque règle consiste en un seul non-terminal (dans ce cas, c'est toujours
S
, mais il pourrait y en avoir plus.)Considérons maintenant cette autre grammaire qui reconnaît les chaînes de la forme {a ^ nb ^ nc ^ n: n> = 1} (par exemple, "abc", "aabbcc", "aaabbbccc"):
Si le non-terminal
B
est précédé du caractère terminal / littéralc
, vous réécrivez ce terme enWB
mais s'il est précédé deb
, vous développezbb
plutôt. C’est ce à quoi la sensibilité au contexte des grammaires sensibles au contexte fait allusion.Un langage sans contexte peut être reconnu comme un automate à pile . Alors qu’une machine à états finis n’utilise pas de mémoire auxiliaire, c’est-à-dire que sa décision ne repose que sur son état et son entrée actuels, un automate à pile possède également une pile et peut regarder au sommet de la pile pour prendre des décisions.
Pour voir cela en action, vous pouvez analyser les parenthèses imbriquées en vous déplaçant de gauche à droite et en plaçant une parenthèse gauche sur une pile à chaque fois que vous en rencontrez une, et en sautant à chaque fois que vous rencontrez une parenthèse droite. Si vous ne tentez jamais de sortir d'une pile vide et que celle-ci est vide à la fin de la chaîne, celle-ci est valide.
Pour un langage contextuel, un PDA ne suffit pas. Vous aurez besoin d'un automate à bornes linéaires qui ressemble à une machine de Turing dont la bande n'est pas illimitée (bien que la quantité de bande disponible soit proportionnelle à l'entrée). Notez que cela décrit assez bien les ordinateurs - nous aimons les considérer comme des machines de Turing, mais dans le monde réel, vous ne pouvez pas capturer arbitrairement plus de mémoire vive à mi-programme. S'il n'est pas évident pour vous de comprendre pourquoi un LBA est plus puissant qu'un PDA, il peut émuler un PDA en utilisant une partie de sa bande en tant que pile, mais il peut également choisir d'utiliser sa bande de différentes manières.
(Si vous vous demandez ce qu'une machine à états finis peut reconnaître, la réponse est des expressions régulières. Mais pas les expressions rationnelles sur les stéroïdes avec des groupes de capture et une vision en arrière que vous voyez dans les langages de programme; je veux dire celles que vous pouvez construire. avec des opérateurs comme
[abc]
,|
,*
,+
et?
. Vous pouvez voir que lesabbbz
matchs regexab*z
juste en gardant votre position actuelle dans la chaîne et regex, pas la pile nécessaire.)la source
Les autres réponses sont assez longues, même si elles sont précises et correctes. C'est la version courte.
Si vous avez une chaîne de caractères (terminaux et non-terminaux) et que vous souhaitez remplacer un non-terminal dans la chaîne, une grammaire sans contexte vous permet de le faire quels que soient les caractères entourant le non-terminal.
Prenez en compte les règles suivantes (minuscules sont les terminaux, majuscules sont non finales):
Dans la première règle, vous pouvez remplacer un
A
indépendamment de ce qui apparaît autour de lui (contexte). Dans la deuxième règle, vous ne pouvez pas remplacerA
sauf si elle est suivie parB
. Alors que les deux terminaux seront remplacés dans ce cas, le point important est que les terminaux entourent laA
question. On ne peut pas remplacerBA
para
, ouB
para
: seulement unA
suivi d'un,B
car l'ordre, le contexte des non-terminaux est important. Cela signifie que le contexte d'un non terminal compte dans la deuxième règle, ce qui le rend sensible au contexte, tandis que la première règle est sans contexte.la source
a
partir deAB
moinsA
est suivie auB
lieu de dire « vous ne pouvez pas remplacerA
» , qui pourrait ne pas être possible , car en fait vous remplacezAB
n'est pas il?A
ouAB
dans la deuxième règle (sensible au contexte)? Je pense que vous essayez toujours de remplacer,A
comme indiqué dans votre réponse.Pour comprendre la distinction et la terminologie mieux, il est une bonne idée de comparer un langage hors-contexte comme un n b n avec un contexte sensible comme un n b n c n . (Notation: a, b et c sont des littéraux ici et l'exposant n signifie répéter le littéral n fois, n > 0, par exemple.) Par exemple,
aabbc
ouaabbbcc
n'est pas dans la dernière langue, alors queaabbcc
.Un accepteur pour la langue sans contexte un n b n peut contracter une paire de
a
etb
quel que soit ce qui est autour d' elle (c. -à- quel que soit le contexte dans lequel ab apparaît) et il fonctionne correctement, accepter que des chaînes dans la langue et le rejet de toute autre chose, c'est-à-dire que la grammaire estS -> aSb | ab
. Notez qu'il n'y a pas de terminaux sur le côté gauche de la (des) production (s) . (Il existe deux règles de production, mais nous les écrivons simplement de manière compacte.) L'accepteur peut en principe prendre une décision locale, sans contexte.En revanche, vous ne pouvez pas faire quelque chose comme ça pour la langue contextuelle a n b n c n , parce que , pour celui- ci , vous devez vous rappeler en quelque sorte le contexte que vous étiez, à savoir le nombre de contractions ab que vous faites pour les faire correspondre avec des contractions de bc. Une grammaire pour cette dernière langue est
Notez que vous avez les terminaux et les non-terminaux à gauche dans les deux dernières règles. Les terminaux de gauche représentent le contexte dans lequel les non-terminaux peuvent être développés.
Bootnote concernant la terminologie «contrat» vs «développer», etc.: bien que les grammaires formelles soient [formellement, hah] génératives, la façon dont elles sont implémentées dans les analyseurs syntaxiques est réellement réductionniste, c'est-à-dire que vous communiquez tout à un non-terminal, essentiellement. appliquer les règles "à l'envers", c'est pourquoi même la première grammaire donnée ci-dessus n'est pas pratique dans un programme (cela vous donnerait le fameux conflit de décalage-réduction car vous ne pouvez pas décider quelle règle appliquer), mais les deux précédentes les grammaires suffisent à illustrer la distinction entre sans contexte et sensible au contexte. La question de l’ambiguïté dans les grammaires sans contexte est assez compliquée, et ce n’est pas vraiment le sujet de cette question, je ne vais donc pas en dire plus ici, d’autant plus que c’est parce que Wikipédia a un bon article à ce sujet.. En revanche, ses articles sur les environnements sans contexte et en particulier celui sur les langages sensibles au contexte sont! @ # $ @! # $, Surtout si vous êtes novice dans le sujet ... Je suppose que cela fait davantage partie de ma liste de choses à faire.
la source
Les réponses ci-dessus donnent une très bonne définition de ce que c'est. Voyons si je peux le formuler avec mes propres mots, pour que vous ayez 23 explications au lieu de 20. Le but d'une grammaire, toute grammaire, est de déterminer si une phrase particulière est une phrase dans la langue donnée. Cependant, ce que nous utilisons réellement pour les grammaires et l'analyse syntaxique est de comprendre le sens de la phrase. C'est comme le vieux diagramme d'une phrase que vous pourriez avoir ou non fait en classe d'anglais à l'école. Une phrase est composée d'une partie de sujet et d'une partie de prédicat, une partie de sujet a un nom et peut-être quelques adjectifs, une partie de prédicat a un verbe et peut-être un nom d'objet, avec quelques adjectifs supplémentaires, etc.
S'il existait une grammaire anglaise (et je ne pense pas qu'il en existe, pas au sens informatique), elle aurait des règles de la forme suivante, appelées productions.
etc...
Vous pouvez ensuite écrire un programme et lui transmettre n'importe quelle phrase. Le programme pourrait également utiliser la grammaire pour déterminer la partie de la phrase de chaque mot et la relation entre eux.
Si dans chaque production, il n'y a qu'une chose du côté gauche, cela signifie que chaque fois que vous voyez le côté droit de la phrase, vous êtes autorisé à le remplacer par le côté gauche. Par exemple, chaque fois que vous voyez un nom adjectif, vous pouvez dire "Voilà un sujet" sans faire attention à rien en dehors de cette phrase.
Cependant, l'anglais (même la description simplifiée de l'anglais que j'ai donnée ci-dessus) est sensible au contexte. Le "nom adjectif" n'est pas toujours un SubjectPart, il pourrait s'agir d'un NounPhrase dans un PredicatePart. Ça dépend du contexte. Développons un peu notre pseudo-grammaire anglaise:
Vous ne pouvez créer un "nom adjectif" dans un ObjectNounPhrase que s'il vient juste après un VerbPhrase.
Fondamentalement, si vous avez une production et que vous pouvez l'appliquer à tout moment, peu importe ce qui l'entoure, elle est sans contexte.
Vous pouvez toujours savoir si une grammaire est sans contexte facilement. Il suffit de vérifier s’il ya plus d’un symbole à gauche des flèches.
Toute langue peut être décrite par plus d'une grammaire. Si une grammaire pour une langue est sans contexte, la langue est sans contexte. On peut prouver pour certaines langues qu’il n’ya pas de grammaire sans contexte possible. Je suppose qu'il pourrait exister une grammaire sans contexte pour le sous-ensemble de pseudo-anglais simplifié que je décris ci-dessus.
Pour ce qui est de savoir pourquoi cela compte, il faut un type de programme plus simple pour analyser une grammaire sans contexte. Comme indiqué dans les autres réponses, il n’est pas nécessaire de disposer de toute la puissance d’une machine de Turing pour analyser une grammaire sans contexte. Un analyseur syntaxique LR (1) à la recherche (qui est une sorte de machine à dérouler) pour une grammaire particulière sans contexte peut analyser n'importe quelle phrase de cette grammaire dans le temps et dans l'espace linéairement à la longueur de la phrase. Si la phrase est dans le langage, l'analyseur produira un arbre de structure identifiant la signification de chaque symbole dans la phrase (ou au moins le rôle qu'il joue dans la structure). Si la phrase ne figure pas dans la grammaire, l'analyseur remarquera et s'arrêtera sur le premier symbole impossible à réconcilier avec la grammaire et les symboles précédents (sur le premier "erreur").
Ce qui est encore mieux, c’est qu’il existe des programmes pour décrire une grammaire et une liste d’instructions sur ce qu’il faut faire avec chaque partie (en un sens associant un "sens" à chaque production) et que le programme écrira l’analyseur. pour vous. Le programme va analyser la phrase, trouver la structure et exécuter vos instructions sur chaque partie de la structure. Ce type de programme s'appelle un analyseur-générateur ou un compilateur-compilateur.
Ce type d’analyse linguistique a été inventé pour l’analyse automatique du langage naturel (comme l’anglais), mais il s’avère que c’est très utile pour l’analyse des langages informatiques. Un concepteur de langage peut écrire une grammaire qui capture son nouveau langage, puis l'exécuter à travers l'analyseur-générateur pour obtenir un programme qui analyse son langage et qui traduit, interprète, compile, exécute, etc. s'il le souhaite.
En fait, dans la plupart des cas, vous ne pouvez pas vraiment faire cela. Par exemple, les parenthèses équilibrées sont un langage sans contexte, mais un langage dans lequel il est nécessaire de déclarer toutes les variables avant de les utiliser est sensible au contexte. L'analyseur est une partie du compilateur, mais une logique supplémentaire est nécessaire pour appliquer ces autres exigences. Ce que vous devez ensuite faire, c'est écrire une grammaire qui capture le plus possible votre langage, l'exécuter à l'aide d'un générateur d'analyseurs syntaxiques, puis écrire un code qui applique le reste des exigences (gestionnaire de table de symboles, etc.).
Nous n'utilisons généralement pas de grammaires contextuelles car elles sont beaucoup plus mal prises en charge. Je ne sais pas s'il existe un équivalent à un générateur d'analyseur syntaxique LR (k) pour les langages contextuels. Oui, une machine de Turing (ou une machine liée linéaire) peut en analyser une, mais je ne sais pas s'il existe un algorithme général permettant de transformer une grammaire contextuelle en un programme pour une machine de Turing, en ce sens qu'une LR (1 ) générateur crée des tables d'analyse pour une machine à pression. À mon avis, les tables sous-jacentes à l'analyseur seraient exponentiellement plus grandes. Dans tous les cas, les élèves CS (comme moi, à l'époque) apprennent généralement des grammaires sans contexte et des générateurs d'analyseurs LR (1) tels que YACC.
la source
Les grammaires sans contexte ne considèrent aucun contexte pour les règles de production. Les contextes sont des terminaux ou des non-terminaux.
Donc: Les grammaires sans contexte n'ont qu'un seul non-terminal du côté gauche des règles de production.
la source