2013-07-11 10 views
11

mi chiedo perché in C# seguente va bene:Perché x ++ - + - ++ x legale ma x +++ - +++ x non lo è?

int y = x++-+-++x; 

Ma

int y = x+++-+++x; 

non lo è? Perché c'è un pregiudizio contro il +?

+8

Meglio domanda è: perché si vuole utilizzare questo? – Sayse

+0

Dipende dal compilatore (.Net 4.5 su reclami VS 2012) –

+0

Abbiamo bisogno di informazioni specifiche su quale compilatore stai usando, su quale cosa hai come target, ecc. – tnw

risposta

16

Le altre due risposte sono corrette; Vorrei aggiungere a loro che questo illustra alcuni principi di base di analisi lessicale:

  • L'analizzatore lessicale è miope - ha minimal "look-ahead"
  • L'analizzatore lessicale è avido - prova a rendere il gettone più lungo possibile al momento.
  • L'analizzatore lessicale non esegue il backtrack cercando di trovare soluzioni alternative quando si fallisce.

Questi principi implicano che +++x saranno lexed come ++ + x e non + ++ x.

Il parser quindi analizzare ++ + x come ++(+x), e (+x) non è una variabile , è un valore, quindi non può essere incrementato.

Consulta anche: http://blogs.msdn.com/b/ericlippert/archive/2010/10/11/10070831.aspx

+0

+1, anche se ciò renderebbe strano che Mono può compilare lo stesso codice. O la specifica è un po '"aperta" su quel lato, o uno dei compilatori non è all'altezza delle specifiche. –

+2

@JoachimIsaksson: Mono ha un piccolo bug; Sospetto che sia nell'analizzatore semantico, non nell'analizzatore lessicale. Cioè, è ** non ** il caso che Mono è lexing '+++ x' come' + ++ x'. Piuttosto, ho il sospetto che sia il lexing corretto come '++ + x', quindi l'analizzatore semantico sta trattando' + x' come 'x', ma dimenticando che' + x' è un valore, non una variabile, e quindi non idoneo come operando dell'incremento. –

+0

@JoachimIsaksson: Infatti. Il compilatore Microsoft C# conteneva un certo numero di errori di questo tipo in C# 2.0; Ho rimosso molti di loro in C# 3.0. Alcuni li abbiamo trattenuti perché erano innocui e prendere il cambiamento di rottura sarebbe stato di disturbo. –

5

Sto usando VS 2012. Questo è un po 'interessante.

Il primo può essere analizzato in:

int y = (x++) - (+(-(++x))); 

senza cambiare il risultato finale. Quindi puoi capire perché sarebbe valido.

Il secondo, tuttavia, ha un problema con lo +++x perché (sto indovinando) vede i due ++ e prova ad applicare quell'operatore unario al valore r, che è un altro + (e non un valore R valido). È possibile raggruppare in vari modi per farlo funzionare, però:

int y = (x++)+(-(+(++x))); 

è valido.

Sono sicuro che Jon Skeet o Eric Lippert o qualcuno si presenteranno e indicheranno la parte rilevante delle specifiche C#. Non sono nemmeno sicuro da dove cominciare. Ma seguendo solo l'analisi generale dei token da sinistra a destra, puoi vedere dove si soffocerebbe sul secondo.

+0

FYI l'intera grammatica è alla fine della specifica in un'appendice. –

+0

Non si vede nulla se non "uno di" sulla grammatica dell'operatore, se preferire "+" o "++" in qualsiasi momento sembra vago. –

+0

@JoachimIsaksson: La sezione 2.3 della specifica dice * "Quando diverse produzioni grammaticali lessicali corrispondono a una sequenza di caratteri in un file sorgente, l'elaborazione lessicale costituisce sempre l'elemento lessicale più lungo possibile." * –

2

Il compilatore sta cercando una variabile o una proprietà dopo il secondo ++ in int y = x+++-+++x e non può determinare quello senza spazio o parentesi.

Si può fare qualcosa di simile:

int y = x+++-+(++x); 

o

int y = x++ + -+ ++x; 

se si voleva.

Il motivo per cui il primo esempio che hai elencato ha funzionato è perché il compilatore può determinare che +- da ++x; mentre nel secondo esempio non è possibile determinare dove separare il +++ e naturalmente si aspetta una variabile dopo aver letto il primo ++; quindi, in breve, il compilatore tenta di utilizzare +x come variabile, che non è valido.

Entrambi sono probabilmente validi utilizzando un altro compilatore. Dipende dalla semantica.