Come vengono solitamente analizzati i commenti?

31

In che modo i commenti vengono generalmente trattati nei linguaggi di programmazione e nel markup? Sto scrivendo un parser per un linguaggio di markup personalizzato e voglio seguire il principio di sorpresa minima , quindi sto provando a determinare la convenzione generale.

Ad esempio, un commento incorporato in un token 'interferisce' con il token o no? In generale, è qualcosa del tipo:

Sys/* comment */tem.out.println()

valida?

Inoltre, se la lingua è sensibile alle nuove righe e il commento si estende sulla nuova riga, la nuova riga dovrebbe essere considerata o no?

stuff stuff /* this is comment
this is still comment */more stuff 

essere trattati come

stuff stuff more stuff

o

stuff stuff
more stuff

So cosa fanno alcuni linguaggi specifici, né sono in cerca di opinioni, ma cerco o meno: c'è un consenso generale che cosa ci si aspetta da un mark up per quanto riguarda token e nuove linee?

Il mio particolare contesto è un markup simile a un wiki.

    
posta ArtB 29.10.2015 - 17:35
fonte

5 risposte

40

Normalmente i commenti vengono scansionati (e scartati) come parte del processo di tokenizzazione, ma prima dell'analisi. Un commento funziona come un separatore di token anche in assenza di spazi bianchi attorno ad esso.

Come si fa notare, la specifica C afferma esplicitamente che i commenti sono sostituiti da un singolo spazio. È solo una specifica, tuttavia, dal momento che un parser reale non sostituirà nulla, ma scansionerà e scarterà un commento nello stesso modo in cui analizza e scarta i caratteri bianchi. Ma spiega in un modo semplice che un commento separa i token allo stesso modo in cui sarebbe uno spazio.

Il contenuto dei commenti viene ignorato, pertanto gli interruzioni di riga all'interno dei commenti multilinea non hanno alcun effetto. Le lingue che sono sensibili alle interruzioni di riga (Python e Visual Basic) di solito non hanno commenti multilinea, ma JavaScript è un'eccezione. Ad esempio:

return /*
       */ 17

È equivalente a

return 17

non

return
17

I commenti a riga singola mantengono l'interruzione di riga, ovvero

return // single line comment
    17

è equivalente a

return
17

non

return 17

Poiché i commenti sono scansionati ma non analizzati, tendono a non annidarsi. Quindi

 /*  /* nested comment */ */

è un errore di sintassi, poiché il commento è aperto dal primo /* e chiuso dal primo */

    
risposta data 29.10.2015 - 18:07
fonte
8

Per rispondere alla domanda:

is there a general consensus what is generally expected by a mark up?

Direi che nessuno si aspetterebbe che un commento incorporato all'interno di un token sia legale.

Come regola generale, i commenti dovrebbero essere trattati allo stesso modo degli spazi bianchi. A qualsiasi posto che sarebbe valido avere spazi bianchi estranei dovrebbe anche essere permesso di avere un commento incorporato. L'unica eccezione sarebbe stringhe:

trace("Hello /*world*/") // should print Hello /*world*/

Sarebbe abbastanza strano supportare i commenti all'interno delle stringhe e renderebbe noioso sfuggire a loro!

    
risposta data 29.10.2015 - 18:12
fonte
7

Nei linguaggi insensibili agli spazi, i caratteri ignorati (ovvero gli spazi bianchi o quelli che fanno parte di un commento) delimitano i token.

Quindi per esempio Sys tem sono due token, mentre System è uno. L'utilità di ciò potrebbe essere più evidente se confronti new Foo() e newFoo() uno dei quali costruisce un'istanza di Foo mentre l'altro chiama newFoo .

I commenti possono svolgere lo stesso ruolo di una serie di spazi bianchi, ad es. new/**/Foo() funziona come new Foo() . Naturalmente questo può essere più complesso, ad es. new /**/ /**/ Foo() o whatnot.

Tecnicamente, dovrebbe essere possibile consentire i commenti all'interno degli identificatori, ma dubito che sia particolarmente pratico.

Ora, che dire delle lingue sensibili allo spazio bianco?

Mi viene in mente Python e ha una risposta molto semplice: nessun commento di blocco. Inizi un commento con # e il parser funziona esattamente come se il resto della riga non esistesse, ma fosse solo una nuova riga.

Al contrario, jade consente di bloccare i commenti , dove il blocco termina quando torni allo stesso livello di indentazione. Esempio:

body
  //-
    As much text as you want
    can go here.
  p this is no longer part of the comment

Quindi, in questo regno, non direi che potresti dire come sono di solito le cose gestite. Ciò che sembra essere una comunanza, è che un commento finisce sempre con un fine riga, il che significa che tutti i commenti si comportano esattamente come le nuove linee.

    
risposta data 29.10.2015 - 18:25
fonte
2

In passato ho trasformato i commenti in un singolo token come parte dell'analisi lessicale. Lo stesso vale per le stringhe. Da lì, la vita è facile.

Nel caso specifico dell'ultimo parser che ho creato, una regola di escape viene passata alla routine di analisi di primo livello. La regola di escape viene utilizzata per gestire token come token di commenti in linea con la grammatica principale. In generale, questi token sono stati scartati.

Una conseguenza del fare in questo modo è che l'esempio che hai postato con un commento nel mezzo di un identificatore, l'identificatore non sarebbe un identificatore singolo - questo è il comportamento previsto in tutte le lingue (dalla memoria) che io ' Ho lavorato con.

Il caso di un commento all'interno di una stringa dovrebbe essere implicitamente gestito dall'analisi lessicale. Le regole per gestire una stringa non hanno alcun interesse nei commenti, e in quanto tale il commento viene trattato come il contenuto della stringa. Lo stesso vale per una stringa (o letterale quotata) all'interno di un commento - la stringa è una parte di un commento, che è esplicitamente un singolo token; le regole per elaborare un commento non hanno interesse per le stringhe.

Spero che abbia senso / aiuti.

    
risposta data 30.10.2015 - 06:34
fonte
1

Dipende dallo scopo del parser. Se si scrive un parser per creare un albero di analisi per la compilazione di un commento non ha valore semantico oltre a separare potenzialmente token (metodo e.g / commento / (/ commento /)). In questo caso, è trattato come spazi.

Se il parser fa parte di un transpiler che traduce una lingua di partenza in un'altra lingua di partenza o se il parser è un preprocessore che prende un'unità di compilazione in una lingua di origine, lo analizza, lo modifica e scrive di nuovo la versione modificata nella stessa fonte lingua, i commenti come qualsiasi altra cosa diventano molto importanti.

Inoltre, se nei commenti ci sono metadati e in particolare ti interessano commenti come la generazione di documentazione API come JavaDoc, i commenti sono all'improvviso molto importanti.

Qui i commenti sono spesso allegati ai token stessi. Se trovi un commento, lo allega come commento di un token. Poiché un token può avere più token prima e dopo, è di nuovo lo scopo, in base a come gestire tali commenti.

L'idea di annotare i token non commentati con i commenti è di rimuovere del tutto i commenti dalla grammatica.

Una volta ottenuto l'albero di analisi, alcuni AST iniziano a decomprimere i commenti che rappresentano ciascun token dal proprio elemento AST ma sono collegati ad un altro elemento AST accanto alla consueta relazione-contenuti. Una buona idea è controllare tutte le implementazioni di parser / AST per le lingue di origine disponibili nell'IDE open source.

Un'ottima implementazione è l'infrastruttura del compilatore Eclipse per il linguaggio Java. Conservano i commenti durante la tokenizzazione e rappresentano commenti all'interno dell'AST, per quanto mi ricordi. Inoltre, questa implementazione di parser / AST conserva la formattazione.

    
risposta data 26.12.2017 - 11:02
fonte

Leggi altre domande sui tag