Est le C++, libre de tout contexte ou contextuelle?
J'entends souvent des réclamations que le C++ est un contexte sensible de la langue. Prenons l'exemple suivant:
a b(c);
Est-ce une définition de variable ou d'une déclaration de fonction? Cela dépend de la signification du symbole c
. Si c
est un variable, puis a b(c);
définit une variable nommée b
de type a
. Il est initialisée directement avec c
. Mais si c
est un type, puis a b(c);
déclare une fonction nommée b
qui prend un c
et renvoie un a
.
Si vous regardez la définition du contexte langues, il va vous dire que toutes les règles de grammaire doit avoir de gauche qui consistent exactement un non-terminal symbole. Contexte de grammaires, d'autre part, de permettre à des chaînes arbitraires de terminaux et non-terminaux sur le côté gauche.
La navigation par le biais de l'Annexe A de la "Le Langage de Programmation C++", je ne pouvais pas trouver une seule règle de grammaire qui n'avait rien d'autre à part un non-terminal symbole sur son côté gauche. Cela impliquerait que le C++ est libre de tout contexte. (Bien sûr, chaque contexte du langage est également sensible au contexte, dans le sens que le contexte langues forment un sous-ensemble de l'contextuelle langues, mais ce n'est pas le point.)
Donc, est le C++, libre de tout contexte ou contextuelle?
- Votre exemple montre clairement qu'il soit sensible au contexte.
- Montrez-moi une seule règle de grammaire de C++ qui n'est pas constitué d'une seule non-terminal symbole sur son côté gauche, et je vais immédiatement vous croire.
- IIUC ça dépend un peu sur l'endroit où vous dessinez la ligne pour la sensibilité au contexte. Je pense que j'ai vu de gens affirment que presque tous les typé statiquement les langages de programmation sont sensibles au contexte, non pas parce que vous ne pouvez pas construire une pratique compilateur pour eux avec CFG analyse des outils, mais parce que de telles implémentations de "tricher" par l'analyse de certains invalides des programmes et que les rejeter plus tard, lors de la vérification de type. Donc, si vous envisagez de mal tapé des programmes de ne pas être dans la langue (dans le CS sens, c'est à dire un ensemble de chaînes de caractères), l'analyseur doit accepter, plus de langues que C++ sont sensibles au contexte.
- Ces gens sont dans l'erreur. Théorie des langages formels est une belle distinction entre les étapes, et sensible au contexte se réfère spécifiquement à l'analyse uniquement, pas de sémantique impliqués.
- Honnêtement, je pensais que "sensible au contexte de la langue" est bien défini. Peut-être que je me trompe et il y a plusieurs définitions établies? Si c'est le cas, je serai heureux d'accepter la première réponse à m'expliquer 🙂
- Non, vous vous trompez. Il n'y a pas de "analyse" ou "sémantique" dans le langage formel de la théorie du tout, juste de la "langue" qui est un ensemble de chaînes de caractères.
- Pas de réponses à ce jour ont effectivement abordé votre définition de "context-free grammar". À mon avis, la réponse correcte à cette question, soit de la cites, la production dans l'annexe A qui ne correspond pas à votre définition, ou démontre que votre définition est incorrecte ou insuffisante. Stand your ground!
- Pas tous les "définitions" sont Formelles, c'est pourquoi j'ai voté pour ré-ouvrir: les alternatives étaient en train de gagner! Dans ce genre de questions, il aide vraiment à l'accent de référence/le point particulier de guide [initial] des réponses.
- Voir en fait D la grammaire vraiment libre de tout contexte?. En fait, je pense que tous ici devrait lire cette question et ses réponses!
- Ne annexe A prétendre qu'il est à la fois nécessaire et suffisante définition complète du langage C++? Alors qu'est-ce que le reste de la norme document (moins la partie de la bibliothèque standard) sur?
- Je viens de mettre la clé de citation de l'Annexe A dans ma réponse, ci-dessous. L'annexe A ne prétend pas être une définition de la langue.
- Ressemble à aucune des réponses (y compris le mien) en fait répondre à la question! (Pour commencer, je ne vois pas comment un contexte sensible de la grammaire pourrait résoudre un de ces problèmes que les gens ont mentionné sans hacks.)
- vous pourriez ne pas avoir vu cette citation dans ma réponse quelque part à quelqu'un d'autre: "Mathématiquement, un contexte sensible de la langue est l'équivalent d'un linéaire bornée de la machine de Turing non déterministe, également appelé un linéaire bornée automate". Je ne sais plus quoi vous vous attendez à une réponse.
- voir mon autre commentaire ci-dessous votre réponse.
- c'est parce que la solution réelle, il faudrait une planète vaut la peine de productions. Le fait qu'il est turing montre qu'il est possible d'écrire. Je ne pense pas que vous avez besoin de plus d'une réponse.
- Personne n'a demandé une solution pour le C++, quel que soit le contexte sensible de la langue qui présente le même problème/solution suffirait
- math.stackexchange.com/questions/163830/...
- Cependant, je ne vois pas où OP demandé pour cela. Vous l'avez fait. Soins à poser une autre question?
- Je pourrais le faire, mais j'ai envie de répondre que les revendications C++ est sensible au contexte doit être prêt à expliquer comment un contexte sensible de la grammaire serait en mesure de l'analyser.
- FredOverflow: Ok, maintenant je vois, @rici réponse est ce que vous cherchez! Assurez-vous de suivre le lien! Il décrit comment une CSG pouvez regarder des copies de symboles, qui est ce dont nous avons besoin pour le C++.
- Si, comme vous le dites, "très libre de tout contexte de la langue est également sensible au contexte" et les deux seules options (par la question) est "C++ libre de tout contexte ou contextuelle?" alors la réponse est clairement qu'il est moins sensible au contexte. Si, toutefois, vous voulez dire à votre question réponse "oui/non", alors peut-être :-p
- Liés copie exacte de la question n'est pas aussi bien construit que celui-ci. En désaccord avec les proches.
- Je pense que la question liée est bien, mais les principales réponses sont incorrectes. Ils devraient probablement être fusionnées.
- Thunk Pourrait vous tuer l'acceptation de ma réponse. Je suis convaincu que DeamMG et coll. sont droit, mais je ne peux pas les supprimer.
- Le problème avec ce titre c'est qu'il suppose que C++ est à moins sensible au contexte; il ne l'est pas. Je voudrais le changer s'il ne serait pas invalider tant dans les réponses.
- Cela ne signifie pas que ce n'est pas un doublon. Cependant, je serai d'accord avec un compromis pour fermer cette question comme un doublon de celui-ci, pour ce qui va devenir "raisons historiques".
- Voir aussi: Comment Clang gère le type / nom de la variable de l'ambiguïté de C/C++ eli.thegreenplace.net/2012/07/05/...
- Si Une question est bonne, et la question B est mauvais, ne fermez pas la question A. Fermer l'autre comme un double, et de laisser le bon. L'autre question n'avait aucune information utile dans ses réponses. Celui-ci a de grandes choses.
- Je me demande je ne suis pas venu à cette question... -
I often hear claims that C++ is a context-sensitive language
-- Oui, ensemble de tous les possible de corriger les programmes d'un langage formel est de la LCF en effet de " C " la langue est un CFL -- contrainte comme la déclaration d'abord, puis l'utiliser plus tard CSL - Vous ne pouvez pas trouver toute seule règle de CSG parce que le Compilateur est écrit en utilisant le problème est que nous ne savons pas efficaces pour l'analyse technique de l'ASC, de Sorte que nous utilisons CFG et poignées caractéristiques explicitement par programmation. - Ici, dans ma réponse: quelqu'un Peut-il donner un simple mais non-toy exemple d'un contexte sensible de la grammaire? j'ai essayé d'expliquer pourquoi une langue est de la CSL, même avec la même syntaxe. L'applicabilité de la syntaxe correcte de la règle de sur type est aussi un CS-fonction qui est dans votre exemple. Mais la compilation de résoudre et de choisir règle de grammaire à l'aide des informations stockées dans le symbole-table explicitement (il n'y a pas de grammaire, vous trouverez en Annexe).
Vous devez vous connecter pour publier un commentaire.
Ci-dessous est ma (courant) préféré démonstration de pourquoi l'analyse C++ est (probablement) Turing-complet, car il montre un programme qui est syntaxiquement correcte si et seulement si un nombre entier est premier.
J'ai donc affirmer que C++ est ni le contexte, ni du contexte.
Si vous le permettez arbitraire symbole de séquences sur les deux côtés de la production, vous produisez un Type-0 de la grammaire ("libre") dans le Hiérarchie de Chomsky, qui est plus puissant que un contexte sensible de la grammaire; sans restriction grammaires sont Turing-complet. Une sensibilité au contexte (Type 1) de la grammaire permet de multiples symboles du contexte sur le côté gauche de production, mais le même contexte doit apparaître sur le côté droit de la production (d'où le nom de "sensible au contexte"). [1] le Contexte sensible de grammaires sont équivalentes à linéaire borné des machines de Turing.
Dans le programme d'exemple, le premier calcul peut être effectué par un linéaire bornée de la machine de Turing, donc il n'a pas tout à prouver Turing équivalence, mais l'important, c'est que l'analyseur doit exécuter le calcul afin de pouvoir effectuer une analyse syntaxique. Il aurait pu être n'importe quel calcul peut s'exprimer comme une instanciation du modèle et il y a toutes les raisons de croire que le C++ instanciation du modèle est Turing-complet. Voir, par exemple, Todd L. Veldhuizen de 2003 de papier.
Peu importe, C++ peut être analysé par un ordinateur, de sorte qu'il peut certainement être analysé par une machine de Turing. Par conséquent, un droit illimité de grammaire pourrait-il reconnaître. En fait écrire une telle grammaire serait pas pratique, c'est pourquoi la norme n'essayez pas de le faire. (Voir ci-dessous).
Le problème avec "l'ambiguïté" de certaines expressions est surtout un hareng rouge. Pour commencer, l'ambiguïté est une fonction d'une grammaire particulière, pas une langue. Même si une langue peut être prouvé sans équivoque grammaires, si elle peut être reconnue par une grammaire libre de tout contexte, il est libre de tout contexte. De même, si elle ne peut pas être reconnu par un contexte libre de la grammaire, mais il peut être reconnu par un contexte sensible de la grammaire, il est sensible au contexte. L'ambiguïté n'est pas pertinent.
Mais dans tous les cas, à l'instar de la ligne 21 (c'est à dire
auto b = foo<IsPrime<234799>>::typen<1>();
) dans le programme ci-dessous, les expressions ne sont pas ambigus, ils sont tout simplement analysée différemment selon le contexte. Dans l'expression la plus simple de la question, la catégorie syntaxique de certains identifiants dépend de la manière dont ils ont été déclarés (types et fonctions, par exemple), ce qui signifie que la langue officielle aurait à reconnaître le fait que les deux arbitraire des chaînes de longueur dans le même programme sont identiques (déclaration et utilisation). Ce peut être modélisé par la "copie" de la grammaire, qui est la grammaire qui reconnaît deux années consécutives des copies exactes d'un même mot. Il est facile de prouver avec les lemme de pompage que cette langue n'est pas libre de tout contexte. Un contexte sensible de la grammaire de cette langue est possible, et un Type-0 grammaire est fourni dans la réponse à cette question: https://math.stackexchange.com/questions/163830/context-sensitive-grammar-for-the-copy-language .Si l'on tentait d'écrire un contexte sensible (ou libre) de la grammaire à l'analyser en C++, il serait tout à fait peut-être remplir l'univers avec des gribouillages. L'écriture d'une machine de Turing pour analyser le C++ serait tout aussi impossible de l'entreprise. Même l'écriture d'un programme C++ est difficile, et autant que je sache, personne n'a été prouvé correct. C'est pourquoi la norme ne tente pas de fournir une grammaire formelle, et pourquoi il choisit d'écrire une partie de l'analyse de règles en anglais technique.
Ce qui ressemble à une grammaire formelle dans la norme C++ n'est pas complète définition formelle de la syntaxe du langage C++. Il n'est même pas complète définition formelle de la langue après le prétraitement, qui pourrait être plus facile à formaliser. (Ce ne serait pas la langue, mais: le langage C++ tel que défini par la norme comprend l'préprocesseur, et le fonctionnement du préprocesseur est décrite de manière algorithmique, car il serait extrêmement difficile de décrire en toute grammaticales formalisme. C'est dans cette section de la norme lexicale de décomposition est décrite, y compris les règles, où il doit être appliqué plus d'une fois.)
Les différentes grammaires (les deux se chevauchent les grammaires pour l'analyse lexicale, qui a lieu avant le prétraitement et l'autre, si nécessaire, par la suite, en plus de la "syntaxique" de la grammaire) sont rassemblés dans l'Annexe A, avec cette remarque importante (italiques ajoutés):
Enfin, voici la promesse de programme. La ligne 21 est syntaxiquement correct si et seulement si les N dans
IsPrime<N>
est premier. Sinon,typen
est un entier, non pas un modèle, de sortetypen<1>()
est analysée comme(typen<1)>()
qui est syntaxiquement incorrecte, car()
n'est pas un point de vue syntaxique expression valide.[1] Pour mettre plus techniquement, chaque production dans un contexte sensible de la grammaire doit être de la forme:
αAβ → αγβ
où
A
est un non-terminal etα
,β
sont éventuellement vide séquences de symboles de la grammaire, etγ
est une séquence non-vide. (La grammaire des symboles peuvent être soit des terminaux ou non terminaux).Cela peut être lu comme
A → γ
seulement dans le contexte[α, β]
. Dans un contexte (Type 2), de la grammaire,α
etβ
doit être vide.Il s'avère que vous pouvez également limiter les grammaires avec le "monotone" restriction, où chaque production doit être de la forme:
α → β
où|α| ≥ |β| > 0
(|α|
signifie "la longueur deα
")Il est possible de prouver que l'ensemble des langages reconnus par une fonction monotone des grammaires est exactement le même que l'ensemble des langages reconnus par le contexte sensible de grammaires, et c'est souvent le cas que c'est plus facile à la base de preuves sur monotone des grammaires. Par conséquent, il est assez fréquent de voir des "sensible au contexte", utilisé comme s'il signifiait "monotone".
<
,>
, et>>
(parfois comme des opérateurs, et parfois entre parenthèses), il est nécessaire de savoir si un symbole qui précède une<
est un modèle avant qu'il soit possible de savoir ce lexeme le suit. Une fois>
est connu pour être un opérateur,value > ()
est une erreur de syntaxe.0
à l'intérieur de()
, pour une simple), mais je pense qu'il est plus intéressant de cette façon, car il montre que vous avez besoin de l'instanciation d'un modèle même de reconnaître si une chaîne est une syntaxiquement correcte programme en C++. Si les deux branches de la compilation, alors je dois travailler plus fort, pour contester l'argument que la différence est "sémantique". Curieusement, même si je suis souvent du mal à définir "syntaxique", personne n'a jamais proposé une définition de la "sémantique" autres que les "choses" je ne pense pas syntaxique" 🙂template
mot-clé seulement lorsque l'identifiant qui nomme le modèle est une personne à charge nom. Ça ne s'applique pas dans le cas de mon programme. Si l'identifiant n'est pas une personne à charge, le nomtemplate
mot-clé est, euh, une erreur de syntaxe. (Ce qui m'a surpris, mais c'est vrai. Essayez-la.) Par la façon dont, personnellement, je ne pense pas que le fichier est analysé jusqu'à ce que le dernier caractère est analysée, mais votre définition d'œuvres: Le compilateur ne sait pas quetypen
est un modèle jusqu'à ce que après il instanciefoo<IsPrime<234799>>
(car il ne serait pas avecfoo<IsPrime<234797>>
).template
même si le compilateur peut le comprendre pour lui-même. (Tant que le nom est qualifié.) Donc, en effet, j'aurais pu écriretemplate typen
, ce qui aurait causé l'erreur de syntaxe à être remarqué un couple de jetons plus tôt, car il serait alors immédiatement une erreur après le non-premierfoo<IsPrime<234797>>
modèle a été instancié, au lieu d'attendre jusqu'à ce que le>
est analysée comme un opérateur de comparaison et la()
est pas parseable comme une expression.()
comme une expression, c'est tout. (Bien sûr, le vrai problème est que dans ce cas particulier, il n'est pas facile de prévoir que<
est un opérateur; en particulier, les êtres humains se tromper parce que nous n'en réalité (et parfois à tort) l'utilisation des espaces sensibles de l'analyse. Mais le compilateur connait la syntaxe de mieux). De toute façon, je n'étais pas à parler la langue de la légalité; je parlais de grammaire formelle de la théorie.IsPrime<...>
exemple (avec programme) a été extrême exagéré pour un simple point... de façon plus simple (comme dans le moins alambiqué) exemple aurait été quelque chose comme:nullptr_t n = std::conditional<true, nullptr_t, int>::type{};
qui est "syntaxiquement correct" (que l'OP a formulé) si et seulement si le premier paramètre du modèle esttrue
.IsPrime
sortait d'une enquête de la façon dont la syntaxe, de la couleur de C++; elle faisait partie de ma prise de conscience que c'est vraiment pas pratique pour définitivement décider si<
est un opérateur ou un support. (Heureusement, il y a de bonnes heuristiques et de la syntaxe-la coloration est autorisé à être mal dans les cas pathologiques.)IsPrime
exemple était un peu "ésotérique" pour le simple point vous étiez en train de faire. En fin de compte, si oui ou non votre programme compilé dépendait 1) le résultat d'un modèle de méta-programmation, et 2) si oui ou non la résultante rvalue type est implicitement convertible à la lvalue type. Cela semble être une question sémantique, et non pas syntaxique, une.auto
donc il n'y a pas de type de conversion à tous; je pense que vous êtes l'incompréhension de la nature du programme. Le syntaxiques question est de savoir sitypen<1>()
est (a) une instanciation d'un modèle ou (b) une expression simple. En d'autres termes, si le<
et>
sont modèle des crochets ou des opérateurs de comparaison. Dans le premier cas,()
est un paramètre vide de la liste; dans ce dernier cas, c'est une erreur de syntaxe. Je ne vois pas comment vous pouvez appeler cette erreur de syntaxe rien d'autre qu'une erreur de syntaxe, et qui a été le point de l'exemple.auto b = std::enable_if< true/false , SomeType >();
... si oui ou non il compile dépend du C++ principe deSFINAE
, qui est certainement une question sémantique. Je vois ce que vous dites à propos de l'analyse du membre de droite de l'expression comme(foo<false>::typen < 1) > ()
comme un "plus délicate à analyser" le scénario qui résulte en une erreur de syntaxe au()
que le 2ème argument deoperator>
. Il est assez intéressant de faire ses propres DONC, la question pour le C++ experts de disect.typen<1>(42)', then it would not be a syntax error regardless of whether
IsPrime " est instancié avec un premier ou pas, mais dans les deux cas, produire radicalement différent de la traite. Ce que vous êtes peut-être manque, c'est quetypen
pourrait être un modèle d'alias, ou il peut être un static const int; vous avez besoin de savoir qui il est afin d'analyser ce qui suittypen
. Par l'analyse, je veux dire analyser. D'où la syntaxe.struct foo { typedef int type; };
struct bar { const int type = 0; };
et soitauto b = foo::type();
ouauto b = bar::type();
... Lafoo
cas est très bien comme il crée un par défautint
. Lebar
cas devientauto b = 0();
qui est, en fait, une erreur de syntaxe dans cette forme simplifiée. Cependant, dans son modèle de formulaire, il "semble" plus comme une sémantique puisqu'elle dépend des résultats d'un modèle de méta-programme (bien qu'une banale), qui doit être évalués.<false>
cas plus précisément revient àauto b = 0<1>();
qui remonte à mon point précédent que cela pourrait être analysée commeauto b = ((0 < 1) > ());
auquel cas l'erreur de syntaxe se produit lors de la 2ème argument deoperator>
rend l'ensemble de l'expression non valide. La raisontypen<1>(42)
fonctionne, c'est que c'est le même queX<1>(42)
qui implicitement construit uneX
int valeur 42. Si le constructeur ont été déclaréesexplicit
, qui ne serait pas possible (une fois de plus, la sémantique).typen<1>
fonctionne, c'est quetypen
est un modèle. C'est indépendant de la nature explicite du constructeur. Si typen était un non-type de modèle, puistypen<1>
serait une autre erreur de syntaxe, parce qu'un nom ne peut pas être un opérande de l'opérateur<
. Par ailleurs, il n'y est pas de l'optionalité à propos de l'analyse. doit être analysé soit comme basé sur un modèle du constructeur ou une expression, en fonction du "type" de la membre symboletypen
; c'est pas a résolu l'ambiguïté, à la différence de la "délicate à analyser". Mais assez.typen
est untemplate<int> struct X
dans le<true>
cas, et donctypen<1>
estX<1>
, etX<1>(42)
implicitement construit unX<1>
. Là où vous avez tort est dans le<false>
cas, oùtypen
est unconst int
, qui peut évidemment de l'opérande à unoperator<
invocation, ce qui rend possible de l'analyser comme le 1er argument à unoperator<
pourint
arguments. Je suis d'accord avec le "assez" partie, nous semblent avoir un déconnecter ici. Par exemple, je l'ai dittypen<1>(42)
et de vous liretypen<1>
, etc.Tout d'abord, vous l'avez fort justement observé qu'il y a pas de règles contextuelles dans la grammaire à la fin du C++ standard, de sorte que la grammaire est libre de tout contexte.
Cependant, que la grammaire n'est pas de décrire avec précision le langage C++, car elle produit non-programmes C++ comme
ou
Le langage C++ définit comme "l'ensemble des bien formé programmes C++" n'est pas libre de tout contexte (il est possible de montrer que le fait de simplement exigeant des variables déclarées en fait si). Étant donné que vous pouvez théoriquement écrire Turing-complet des programmes dans les modèles et faire d'un programme un mal formé en fonction de leur résultat, il n'est même pas sensible au contexte.
Maintenant, (ignorant) de personnes (généralement pas la langue des théoriciens, mais analyseur concepteurs utilisent généralement "pas libre de tout contexte" dans certains de la signification suivante
La grammaire à l'arrière de la norme n'est pas satisfaire à ces catégories (c'est à dire qu'il est ambigu, pas LL(k)...) donc C++ grammaire "n'est pas libre de tout contexte" pour eux. Et dans un sens, ils ont raison c'est sacrément bien dur pour produire un travail analyseur C++.
Noter que les propriétés utilisée ici ne sont que faiblement lié au contexte des langues - l'ambiguïté n'a rien à voir avec sensibilité au contexte (en fait, sensible au contexte des règles généralement aide à distinguer les productions), les deux autres sont simplement des sous-ensembles de contextes langues. Et l'analyse du contexte de libre-langues n'est pas un processus linéaire (bien que l'analyse déterministe de l'est).
ambiguity doesn't have anything to do with context-sensitivity
C'était mon intuition aussi, je suis heureux de voir quelqu'un (une) d'accord, et (b) expliquer où je ne pouvais pas. Je crois qu'il disqualifie tous les arguments qui sont fondés sura b(c);
, et partiellement satisfaire à la question d'origine, dont le principe a été "souvent entendu" les revendications de la sensibilité au contexte en cours en raison de l'ambiguïté... surtout quand, pour la grammaire il n'y a pas d'ambiguïté, même dans le titre de MVP.Oui. L'expression suivante a un autre ordre des opérations selon type résolu contexte:
Edit: Lorsque la commande de fonctionnement varie, il est incroyablement difficile d'utiliser un "régulier" du compilateur qui analyse à un non AST avant de les décorer. il (se propageant type d'information). D'autres sensibles au contexte choses mentionnées sont "plutôt facile" par rapport à cela (pas ce modèle d'évaluation est facile).
Suivie par:
Pour répondre à votre question, il faut distinguer deux questions différentes.
La simple syntaxe de presque chaque langage de programmation est libre de tout contexte. Généralement, il est donné comme un extended Backus-Naur form ou context-free grammar rencontrent.
Cependant, même si un programme est conforme avec le contexte-free grammar rencontrent défini par le langage de programmation, il n'est pas nécessairement un valide programme. Il y a beaucoup de non-libre de tout contexte poperties qu'un programme doit satisfaire afin d'être d'un programme valide. E. g., le plus simple de ces biens est la portée des variables.
Pour conclure, si oui ou non C++ est libre de tout contexte dépend de la question que vous vous posez.
VARDECL : TYPENAME IDENTIFIER
, mais vous pas ont que, parce que vous ne pouvez pas distinguer les noms de type de d'autres identifiants à un CF de niveau. Un autre exemple: lors d'une FC, vous ne pouvez pas décider d'analysera*b
comme une déclaration de variable (b
de type pointeur versa
) ou comme une multiplication.Ouais C++ est sensible au contexte, très sensibles au contexte. Vous ne pouvez pas construire l'arbre de syntaxe par la simple analyse du fichier à l'aide d'un contexte de libre-analyseur parce que, dans certains cas, vous devez connaître le symbole de la connaissance précédente de décider (ie. construire une table des symboles lors de l'analyse).
Premier exemple:
Est-ce une multiplication d'expression?
OU
Est-ce une déclaration de
B
variable est un pointeur de typeA
?Si A est une variable, alors c'est une expression, si A est de type, c'est une déclaration de pointeur.
Deuxième exemple:
Est-ce un prototype de fonction prend un argument de
bar
type?OU
Est-ce déclarer la variable
B
de typeA
et appelle Un constructeur avecbar
constante comme un initialiseur?Vous avez besoin de savoir encore si
bar
est une variable ou d'un type de table de symboles.Troisième exemple:
C'est le cas lors de la construction de la table des symboles lors de l'analyse n'aide pas parce que la déclaration de x et y vient après la définition de la fonction. Si vous avez besoin de numériser à travers la définition de la classe de première, et de regarder les définitions de méthode dans un second passage, pour dire x*y est une expression, et non pas une déclaration de pointeur ou de quoi que ce soit.
A B();
est une déclaration de fonction, même dans une définition de fonction. Recherchez plus délicate à analyser...Vous voudrez peut-être jeter un oeil à Le Design & Évolution de C++, par Bjarne Stroustrup. Il y décrit ses problèmes en essayant d'utiliser yacc (ou similaire) pour analyser une première version de C++, et souhaitant qu'il avait utilisé récursive descente à la place.
C++ est analysé avec GLR de l'analyseur. Cela signifie que lors de l'analyse du code source, l'analyseur peut la rencontre de l'ambiguïté, mais il doit continuer et de décider quelle règle de grammaire à utiliser plus tard.
look aussi,
Pourquoi C++ ne peut pas être analysé avec un LR(1) analyseur?
Se rappeler que le contexte grammaire ne peut pas décrire TOUS les règles d'un langage de programmation syntaxe. Par exemple, l'Attribut de la grammaire est utilisée pour vérifier la validité d'un type d'expression.
Vous ne peut pas décrire les aspects suivants de la règle de la grammaire libre de tout contexte :
Le Côté Droit de la mission doivent être du même type de la Gauche.
J'ai le sentiment qu'il y a une certaine confusion entre la définition officielle du terme "sensible au contexte" et le secteur informel de l'utilisation de "sensible au contexte". La première a une bien définis. Ce dernier est utilisé pour dire "vous avez besoin de contexte afin d'analyser l'entrée".
C'est aussi posée ici:
Sensibilité au contexte vs Ambiguïté.
Voici une grammaire libre de tout contexte:
C'est ambigu, dans le but d'analyser l'entrée "x" vous avez besoin d'un contexte (ou en direct avec l'ambiguïté, ou émettre des "Avertissement: E8271 d'Entrée est ambigu dans la ligne 115"). Mais ce n'est certainement pas un contexte sensible de la grammaire.
Pas Algol-comme le langage est libre de tout contexte, parce qu'ils ont des règles qui limitent les instructions et expressions que les identificateurs peuvent apparaître en fonction de leur type, et parce qu'il n'y a pas de limite sur le nombre de déclarations qui peuvent se produire entre la déclaration et l'utilisation.
La solution habituelle est d'écrire un contexte de libre parser qui accepte réellement un sur-ensemble de l'valide les programmes et de mettre le contexte-les parties sensibles dans ad hoc "sémantique" code attaché à des règles.
C++ va bien au-delà de cela, grâce à son Turing-complet système de template. Voir Un Débordement De Pile Question 794015.
Vrai 🙂
J. Stanley Warford. Les systèmes informatiques. Pages 341-346.
Il est sensible au contexte, comme
a b(c);
a deux valides analyse - déclaration et variable. Quand vous dites "Sic
est un type", c'est le contexte, là, et vous avez décrit exactement comment C++ est sensible. Si vous n'avez pas eu ce contexte de "qu'est-Ce quec
?", vous pourriez ne pas analyser cette ambiguïté.Ici, le contexte est exprimé dans le choix des jetons - l'analyseur lit un identificateur de typename jeton si il le nom d'un type. C'est la résolution la plus simple, et évite une grande partie de la complexité de l'être sensible au contexte (dans ce cas).
Edit: Il y a, bien sûr, plus de problèmes de sensibilité de contexte, j'ai simplement porté sur celui que vous avez indiqué. Les modèles sont particulièrement désagréables pour cela.
a<b<c>>d
, droit? (Votre exemple est en fait un classique de C, où il est le que obstruction d'être libre de tout contexte.)Les productions dans la norme C++ sont écrits libre de tout contexte, mais comme nous le savons tous n'ont pas vraiment définir la langue avec précision. Certains de ce que la plupart des gens considèrent comme une ambiguïté dans le langage courant pourrait (je crois) être résolu sans ambiguïté avec un contexte sensible de la grammaire.
Pour l'exemple le plus évident, considérons la Plus Délicate à Analyser:
int f(X);
. SiX
est une valeur, alors ceci définitf
comme une variable qui sera initialisé avecX
. SiX
est un type, il définitf
comme une fonction prenant un seul paramètre de typeX
.À la recherche à partir d'un point de vue grammatical, on pourrait l'afficher comme ceci:
Bien sûr, pour être tout à fait correct, nous aurions besoin d'ajouter des extra "trucs" pour tenir compte de la possibilité d'intervention des déclarations d'autres types (c, A et B doivent à la fois être vraiment "déclarations y compris la déclaration de X...", ou quelque chose de cet ordre).
C'est encore assez différents à partir d'un type CSG bien (ou au moins ce que je me souviens d'entre eux). Cela dépend d'un symbole de la table en cours de construction -- la partie qui reconnaît spécifiquement
X
comme un type ou de la valeur, pas seulement un certain type de déclaration précédente, mais le bon type de déclaration pour le droit de symbole/identificateur.En tant que tel, je devrais faire quelques recherche pour être sûr, mais ma conjecture est que ce n'est pas vraiment qualifier de CSG, à moins que le terme est utilisé normalement.
Le plus simple des cas de non-context-free grammar implique l'analyse des expressions impliquant des modèles.
Cela peut analyser comme
Ou
Les deux ASTs ne peut être désambiguïsés par l'examen de la déclaration de 'a' - ex AST si 'a' est un modèle, ou le dernier si ce n'.
<
doit être un support s'il pouvait être (eg., il en résulte un identifiant portant le nom d'un modèle). C++11 a ajouté l'exigence que>
et le premier caractère de>>
être interprétées comme des crochets fermants, si cet usage est tout à fait plausible. Cela affecte l'analyse dea<b>c>
oùa
est un modèle, mais n'a aucun effet sura<b<c>
.a();
(qui est soitexpr.call
ouexpr.type.conv
)?Parfois, c'est pire: Ce que les gens veulent dire quand ils disent que C++ est "indécidable de la grammaire"?
Modèles C++ ont été montré pour être Turing Puissant. Bien que n'étant pas un officiel de référence, voici un lieu de chercher à cet égard:
http://cpptruths.blogspot.com/2005/11/c-templates-are-turing-complete.html
Je vais tenter une conjecture (vieux comme un folkoric et concis CACM de preuve indiquant que l'ALGOL dans les années 60 n'a pas pu être représentée par un CFG) et de dire que le C++ ne peut donc pas être correctement analysée que par une CFG. CFGs, en collaboration avec les divers TP mécanismes dans un arbre de passer ou au cours de la réduction des événements -- ceci est une autre histoire. Dans un sens général, en raison du Problème de l'Arrêt, il existe un programme en C++ qui ne peut être montré pour être correct/incorrect, mais est néanmoins correct/incorrect.
{PS - Comme l'auteur de la Méta-S (mentionné par plusieurs personnes ci-dessus) - je peux assurément dire que Thothic est ni disparu, ni le logiciel est disponible gratuitement. Peut-être que j'ai rédigé cette version de ma réponse que je n'ai pas été supprimé ou ont voté jusqu'à -3.}
C++ n'est pas sans contexte. J'ai appris il y a quelque temps dans les compilateurs de conférence. Une recherche rapide a donné ce lien, où la "Syntaxe ou de la sémantique" section explique pourquoi le C et le C++ ne sont pas sans contexte:
Wikipédia Parler: Context-Free grammar
Ce qui concerne,
Ovanes
Évidemment, si vous prenez la question verbatim, près de toutes les langues avec les identifiants sont sensibles au contexte.
Un besoin de savoir si un identificateur est un nom de type (un nom de classe, un nom introduit par la définition de type, un typename paramètre du modèle), le nom d'un modèle ou d'un autre nom pour être en mesure de correctement certains de l'utilisation de l'identificateur. Par exemple:
est une fonte si
name
est un nom de type et d'un appel de fonction siname
est un nom de fonction. Un autre cas est la soi-disant "plus délicate à analyser" où il n'est pas possible de différencier la définition des variables et déclaration de fonction (il y a une règle disant que c'est une déclaration de fonction).Que la difficulté a introduit la nécessité de
typename
ettemplate
ayant à charge des noms. Le reste de C++ n'est pas sensible au contexte pour autant que je sais (c'est à dire qu'il est possible d'écrire un contexte de grammaire pour elle).Le lien correct est l'analyse enigines
Méta-S a été la propriété d'une société défunte appelé Thothic. Je peux vous envoyer un exemplaire gratuit de la Méta-S à toute personne intéressée et je l'ai utilisé dans l'analyse de l'arn de la recherche. Veuillez noter que les pseudonoeud grammaire" inclus dans les exemples de dossiers a été écrit par un non-bioinformatique, amature programmeur et, fondamentalement, ne fonctionne pas. Mon grammaires de prendre une approche différente et fonctionnent très bien.
Un gros problème ici est que les termes "context-free" et "sensible au contexte" sont un petit peu intuitive au sein de l'informatique. Pour C++, sensibilité au contexte ressemble beaucoup à l'ambiguïté, mais ce n'est pas nécessairement vrai dans le cas général.
/C++, une instruction if est permis qu'à l'intérieur du corps d'une fonction. Qui semble la rendre sensible au contexte, à droite? Eh bien, non. Libre de tout contexte grammaires n'ont pas réellement besoin de la propriété où vous pouvez arracher quelques lignes de code et de déterminer si elle est valide. Ce n'est pas réellement ce contexte signifie. C'est vraiment juste une étiquette que vaguement implique quelque chose de gentil liées à ce que cela ressemble.
Maintenant, si une instruction dans un corps de la fonction est analysée différemment en fonction de quelque chose de défini à l'extérieur immédiat de grammaire ancêtres (par exemple, si un identificateur décrit un type ou variable), comme dans le
a * b;
cas, alors il est, en effet, sensible au contexte. Il n'y a aucune ambiguïté là; il sera analysée comme une déclaration d'un pointeur sia
est un type et une multiplication autrement.Être sensible au contexte ne signifie pas nécessairement "difficile à analyser". C est pas difficile, car l'infâme
a * b;
"ambiguïté" peut-être résolu avec une table de symboles contenanttypedef
s rencontrés précédemment. Il ne nécessite pas n'importe quel modèle d'instanciations (qui ont été prouvées pour être Turing Complet) pour résoudre ce cas, comme le C++ n'est qu'à l'occasion. Ce n'est pas vraiment possible d'écrire un programme C qui ne sont pas compilés dans une quantité limitée de temps, même si il a la même sensibilité au contexte que le C++ ne.Python (et d'autres espaces sensibles langues) est également dépendante du contexte, car il exige de l'état dans l'analyseur lexical pour générer de retrait et de dedent jetons, mais qui n'en est pas plus difficile à analyser que les typiques LL-1 de la grammaire. En fait, il utilise un analyseur générateur, qui est en partie pourquoi Python a peu la syntaxe des messages d'erreur. Il est également important de noter ici qu'il n'y est pas de "l'ambiguïté", comme le
a * b;
problème en Python, en donnant un bon exemple concret d'un contexte sensible à la langue sans "ambigu" de la grammaire (comme mentionné dans le premier paragraphe).