Verschachtelte generische Syntax-Ambiguität

9

Anscheinend ist C # für "& gt; & gt;" lexer dilemma wie auch C ++ .

Dieser C # -Code ist ziemlich gültig, er kompiliert und läuft gut:

%Vor%

Sie müssten '& lt; überladen' und "& gt; & gt;" Operatoren für die Dummy-Klasse oben.

Aber der Compiler kann raten, dass im 'x' Fall die lokalen Variablen List, Nullable und Guid verwendet werden. Und im, y 'Fall beschließt es plötzlich, sie als Namen bekannter Typen zu behandeln.

Hier ist ein bisschen detailliertere Beschreibung mit einem anderen Beispiel: Ссылка

Die Frage ist: Wie löst der C # -Compiler 'a & lt; b & lt; c & gt; & gt;' zum arithmetischen Ausdruck oder generischen Typ / Methode?

Sicherlich versucht es nicht, mehrfach über den Text des Programms zu gehen, bis es gelingt, oder? Das würde unbegrenzte Vorausschau erfordern und auch sehr komplex.

    
Oleg Mihailik 16.05.2012, 00:06
quelle

2 Antworten

5

Ich wurde auf den Abschnitt 7.6.4.2 in der C # -Sprachspezifikation verwiesen:

Ссылка

  

Die Produktionen für Simple-Name (§7.6.2) und Member-Access (§7.6.4) können zu Mehrdeutigkeiten in der Grammatik für Ausdrücke führen.

...

  

Wenn eine Folge von Token als ein einfacher Name (im Kontext) (§7.6.2), Member-Zugriff (§7.6.4) oder Zeiger-Mitglied-Zugriff (§18.5.2) geendet werden kann mit einer Typ-Argument-Liste (§4.4.1), das Token unmittelbar nach dem Schließen & gt; Token wird überprüft. Wenn es eines von

ist      

()]}:; . ? ==! = | ^

     

dann wird die Typ-Argument-Liste als Teil des Einfach-Namens, Mitglieder-Zugriffs oder Zeiger-Mitglied-Zugriffs beibehalten und jede andere mögliche Syntaxanalyse der Token-Sequenz wird verworfen. Andernfalls wird die Typ-Argument-Liste nicht als Teil des einfachen Namens, des Member-Zugriffs oder des Zeiger-Mitglied-Zugriffs betrachtet, selbst wenn es keine andere mögliche Syntaxanalyse der Folge von Token gibt. Beachten Sie, dass diese Regeln nicht angewendet werden, wenn Sie eine Typ-Argument-Liste in einem Namensraum-oder-Typ-Namen (§3.8) analysieren.

Es kann also zu einer Zweideutigkeit kommen, wenn eine Typ-Argument-Liste involviert ist, und sie haben einen billigen Weg, sie zu lösen, indem sie einen Token voraus schauen.

Es ist immer noch ein ungebundener Blick nach vorn, denn zwischen "& gt; & gt;" und folgen Token, aber zumindest ist die Regel mehr oder weniger klar. Und am wichtigsten ist, dass keine spekulative Tiefenanalyse benötigt wird.

    
Oleg Mihailik 16.05.2012, 19:12
quelle
-1

EDIT: Ich bestehe darauf, dass es keine Zweideutigkeit gibt: In Ihrem Beispiel gibt es keine Zweideutigkeit. Dies könnte niemals als List<Guid?> ausgewertet werden. Der Kontext (die zusätzlichen 10) zeigt dem Compiler, wie er zu interpretieren ist.

%Vor%

Würde der Compiler dies kompilieren?:

%Vor%

Es ist klar, dass es nicht so wäre. Also bin ich immer noch auf der Suche nach der Mehrdeutigkeit.

OTOH, der zweite Ausdruck:

%Vor%

muss als List<Guid?> ausgewertet werden, da Sie die Methode .Equals aufrufen. Auch dies kann auf andere Weise interpretiert werden.

Es gibt kein Paradoxon. Der Compiler analysiert es perfekt. Ich frage mich immer noch, was die Apradox ist.

Sie haben einen großen Fehler. Der Compiler interpretiert ganze Ausdrücke und verwendet die Sprachgrammatik, um sie zu verstehen. Es betrachtet kein Code-Fragment, wie Sie es tun, ohne den Rest des Ausdrucks zu berücksichtigen.

Diese Ausdrücke werden gemäß zur C # -Grammatik analysiert. Und die Grammatik ist klar genug, um den Code richtig zu interpretieren. I.e. in

%Vor%

Es ist klar, dass 10 ein Literal ist. Wenn Sie die Grammatik nachverfolgen, finden Sie Folgendes: 10 ist ein * literal , also ist es primary-no-array-creation-expression , was ein * primärer_ausdruck , der ein * unärer Ausdruck ist, der ein * multiplikativer Ausdruck ist, der ein * additiver Ausdruck ist Wenn Sie auf der rechten Seite eines * & gt; & gt; nach einem additiven Ausdruck suchen, müssen Sie einen * shift-expression finden, also die linke Seite des * & gt; & gt; muss als * additive-expression usw. interpretiert werden.

Wenn Sie einen anderen Weg finden könnten, die Grammatik zu verwenden und ein anderes Ergebnis für denselben Ausdruck zu erhalten, dann müsste ich Ihnen zustimmen, aber lassen Sie mich widersprechen!

Schließlich:

  • ist sehr verwirrend für Menschen
  • ist absolut klar und eindeutig für den Compiler

Weil:

  • wir Menschen identifizieren Muster, die uns vertraute Fragmente des ganzen Textes, wie List<Nullable<Guid>> , aufnehmen und sie so interpretieren, wie wir wollen
  • Compiler interprettieren den Code nicht wie wir und nehmen bekannte Fragmente wie List<Nullable<Guid>> . Sie nehmen den ganzen Ausdruck und passen ihn der Grammatik der Sprache an.
JotaBe 16.05.2012 01:20
quelle

Tags und Links