Como os comentários são geralmente tratados em linguagens de programação e marcação? Estou escrevendo um analisador para alguma linguagem de marcação personalizada e quero seguir o princípio da menor surpresa , então estou tentando determinar a convenção geral.
Por exemplo, um comentário incorporado em um token 'interfere' com o token ou não? Geralmente, é algo como:
Sys/* comment */tem.out.println()
válido?
Além disso, se o idioma é sensível a novas linhas e o comentário abrange a nova linha, a nova linha deve ser considerada ou não?
stuff stuff /* this is comment
this is still comment */more stuff
ser tratado como
stuff stuff more stuff
ou
stuff stuff
more stuff
?
Sei o que alguns idiomas específicos fazem, nem procuro opiniões, mas procuro se há ou não: existe um consenso geral sobre o que geralmente é esperado por uma marcação em relação a tokens e novas linhas?
Meu contexto particular é uma marcação do tipo wiki.
Respostas:
Geralmente, os comentários são verificados (e descartados) como parte do processo de tokenização, mas antes da análise. Um comentário funciona como um separador de token, mesmo na ausência de espaço em branco ao seu redor.
Como você aponta, a especificação C afirma explicitamente que os comentários são substituídos por um único espaço. É apenas uma linguagem de especificação, já que um analisador do mundo real não substitui nada, mas apenas verifica e descarta um comentário da mesma maneira que verifica e descarta caracteres em branco. Mas explica de uma maneira simples que um comentário separa os tokens da mesma maneira que um espaço faria.
O conteúdo dos comentários é ignorado, portanto, as quebras de linha nos comentários de várias linhas não têm efeito. Os idiomas sensíveis a quebras de linha (Python e Visual Basic) geralmente não têm comentários de várias linhas, mas o JavaScript é uma exceção. Por exemplo:
É equivalente a
não
Comentários de linha única preservam a quebra de linha, ou seja,
é equivalente a
não
Como os comentários são verificados, mas não analisados, eles tendem a não se aninhar. tão
é um erro de sintaxe, pois o comentário é aberto pelo primeiro
/*
e fechado pelo primeiro*/
fonte
/* like this */
) são considerados iguais a um único espaço em branco e os comentários terminados em EOL (// like this
) a uma linha em branco.(define x #| this is #| a sub-comment |# the main comment |# 3) x
yields3
.Para responder à pergunta:
Eu diria que ninguém esperaria que um comentário incorporado dentro de um token fosse legal.
Como regra geral, os comentários devem ser tratados da mesma forma que os espaços em branco. Qualquer lugar que seria válido para ter espaços em branco externos também deve ter um comentário incorporado. A única exceção seria strings:
Seria bastante estranho apoiar comentários dentro de strings, e tornaria escapar deles tedioso!
fonte
Hello /* world*/!
vez de suprimir os delimitadores de comentários. Bem-vindo também aos programadores!Em idiomas não sensíveis a espaços em branco, caracteres ignorados (por exemplo, espaços em branco ou aqueles que fazem parte de um comentário) delimitam os tokens.
Por exemplo,
Sys tem
são dois tokens, enquantoSystem
é um. A utilidade disso pode ser mais aparente se você compararnew Foo()
enewFoo()
um deles criará uma instância deFoo
enquanto o outro chamanewFoo
.Os comentários podem desempenhar o mesmo papel que uma série de espaços em branco, por exemplo,
new/**/Foo()
funciona da mesma forma quenew Foo()
. Claro que isso pode ser mais complexo, por exemplo,new /**/ /**/ Foo()
ou outros enfeites.Tecnicamente, deve ser possível permitir comentários dentro dos identificadores, mas duvido que seja particularmente prático.
Agora, o que dizer das linguagens sensíveis ao espaço em branco?
O Python vem à mente e tem uma resposta muito simples: sem comentários em bloco. Você inicia um comentário
#
e o analisador funciona exatamente como se o resto da linha não existisse, mas era apenas uma nova linha.Em contraste com isso, o jade permite comentários em bloco , onde o bloco termina quando você volta ao mesmo nível de recuo. Exemplo:
Portanto, neste reino, eu não diria que você poderia dizer como as coisas são geralmente tratadas. O que parece ser uma semelhança, é que um comentário sempre termina com um final de linha, o que significa que todos os comentários agem exatamente da mesma forma que as novas linhas.
fonte
No passado, transformei comentários em um único token como parte da análise lexical. O mesmo vale para seqüências de caracteres. A partir daí, a vida é fácil.
No caso específico do último analisador que criei, uma regra de escape é passada para a rotina de análise de nível superior. A regra de escape é usada para manipular tokens, como tokens de comentário, alinhados com a gramática principal. Em geral, esses tokens foram descartados.
Uma consequência de fazer dessa maneira é que, no exemplo que você postou com um comentário no meio de um identificador, o identificador não seria um único identificador - esse é o comportamento esperado em todos os idiomas (da memória) com os quais trabalhei .
O caso de um comentário dentro de uma string deve ser implicitamente tratado pela análise lexical. As regras para manipular uma sequência não têm interesse em comentários e, como tal, o comentário é tratado como o conteúdo da sequência. O mesmo se aplica a uma string (ou literal entre aspas) dentro de um comentário - a string faz parte de um comentário, que é explicitamente um único token; as regras para processar um comentário não têm interesse em cadeias.
Espero que faça sentido / ajude.
fonte
console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")
, onde há aspas em um comentário e sintaxe de comentário em uma string, como o lexer saberia tokenizá-lo corretamente? Você pode editar sua resposta, fornecendo uma descrição geral desses casos?Depende de qual propósito seu analisador tem. Se você escrever um analisador para construir uma árvore de análise para compilar, um comentário não terá valor semântico além de separar os tokens potencialmente (por exemplo, método / comentário / (/ comentário /)). Neste caso, é tratado como espaços.
Se o seu analisador faz parte de um transpiler que traduz um idioma de origem para outro idioma de origem ou se o analisador é um pré-processador que pega uma unidade de compilação em um idioma de origem, analisa-o, modifica-o e grava a versão modificada novamente no mesmo idioma de origem, comenta como qualquer outra coisa se torna muito importante.
Além disso, se você possui meta informações nos comentários e se preocupa especialmente com os comentários, como ao gerar a documentação da API, como o JavaDoc, os comentários são repentinamente muito importantes.
Aqui, os comentários costumam ser anexados aos próprios tokens. Se você encontrar um comentário, anexe-o para ser um comentário de um token. Como um token pode ter vários tokens antes e depois, é novamente objetivo, dependendo de como lidar com esses comentários.
A idéia de anotar tokens sem comentários com comentários é remover completamente os comentários da gramática.
Depois de ter a árvore de análise, alguns AST começam a descompactar comentários representando cada token por seu próprio elemento AST, mas sendo anexados a outro elemento AST ao lado do relacionamento comum de contenção. Uma boa idéia é verificar todas as implementações do analisador / AST para os idiomas de origem disponíveis no IDE de código aberto.
Uma implementação muito boa é a infraestrutura do compilador Eclipse para a linguagem Java. Eles preservam os comentários durante a tokenização e representam comentários no AST - tanto quanto me lembro. Além disso, essa implementação do analisador / AST preserva a formatação.
fonte