¿Cómo se tratan generalmente los comentarios en lenguajes de programación y marcado? Estoy escribiendo un analizador para un lenguaje de marcado personalizado y quiero seguir el principio de menor sorpresa , así que estoy tratando de determinar la convención general.
Por ejemplo, ¿debería un comentario incrustado dentro de un token 'interferir' con el token o no? En general, es algo como:
Sys/* comment */tem.out.println()
¿válido?
Además, si el lenguaje es sensible a las nuevas líneas y el comentario abarca la nueva línea, ¿debería considerarse o no la nueva línea?
stuff stuff /* this is comment
this is still comment */more stuff
ser tratado como
stuff stuff more stuff
o
stuff stuff
more stuff
?
Sé lo que hacen algunos idiomas específicos, ni estoy buscando opiniones, pero estoy buscando si hay o no: ¿hay un consenso general sobre lo que generalmente se espera con un marcado en lo que respecta a tokens y nuevas líneas?
Mi contexto particular es un marcado tipo wiki.
Respuestas:
Por lo general, los comentarios se escanean (y descartan) como parte del proceso de tokenización, pero antes del análisis. Un comentario funciona como un separador de token incluso en ausencia de espacios en blanco a su alrededor.
Como señala, la especificación C establece explícitamente que los comentarios se reemplazan por un solo espacio. Sin embargo, es solo una jerga de especificaciones, ya que un analizador del mundo real no reemplazará nada, sino que simplemente escaneará y descartará un comentario de la misma manera que escanea y descarta los caracteres de espacios en blanco. Pero explica de manera simple que un comentario separa los tokens de la misma manera que lo haría un espacio.
El contenido de los comentarios se ignora, por lo que los saltos de línea dentro de los comentarios multilínea no tienen ningún efecto. Los lenguajes sensibles a los saltos de línea (Python y Visual Basic) generalmente no tienen comentarios de varias líneas, pero JavaScript es una excepción. Por ejemplo:
Es equivalente a
no
Los comentarios de una sola línea conservan el salto de línea, es decir
es equivalente a
no
Dado que los comentarios se escanean pero no se analizan, tienden a no anidarse. Asi que
es un error de sintaxis, ya que el comentario se abre por el primero
/*
y se cierra por el primero*/
fuente
/* like this */
) se consideran iguales a un espacio en blanco y los comentarios terminados en EOL (// like this
) a una línea en blanco.(define x #| this is #| a sub-comment |# the main comment |# 3) x
rendimientos3
.Para responder la pregunta:
Diría que ninguno esperaría que un comentario incrustado dentro de un token sea legal.
Como regla general, los comentarios deben tratarse de la misma manera que los espacios en blanco. Cualquier lugar que sea válido para tener espacios en blanco extraños también debería tener un comentario incrustado. La única excepción serían las cadenas:
Sería bastante extraño apoyar los comentarios dentro de las cadenas, ¡y haría que escapar de ellos sea tedioso!
fuente
Hello /* world*/!
lugar de suprimir los delimitadores de comentarios. Además, ¡bienvenidos a los programadores!En los idiomas insensibles a espacios en blanco, los caracteres ignorados (es decir, espacios en blanco o aquellos que forman parte de un comentario) delimitan los tokens.
Entonces, por ejemplo,
Sys tem
son dos tokens, mientras queSystem
es uno. La utilidad de esto podría ser más evidente si comparanew Foo()
ynewFoo()
uno de ellos construirá una instanciaFoo
mientras que el otro llamanewFoo
.Los comentarios pueden desempeñar el mismo papel que una serie de espacios en blanco, por ejemplo,
new/**/Foo()
funciona igual quenew Foo()
. Por supuesto, esto puede ser más complejo, por ejemplo,new /**/ /**/ Foo()
o no.Técnicamente, debería ser posible permitir comentarios dentro de los identificadores, pero dudo que sea particularmente práctico.
Ahora, ¿qué pasa con los idiomas sensibles al espacio en blanco?
Python viene a mi mente y tiene una respuesta muy simple: no hay comentarios de bloque. Se empieza con un comentario
#
y luego el analizador funciona exactamente como si el resto de la línea no existía, pero eran sólo un salto de línea en su lugar.En contraste con eso, jade permite comentarios de bloque , donde el bloque termina cuando vuelve al mismo nivel de sangría. Ejemplo:
Así que en este ámbito, yo no diría que se podría decir cómo las cosas están por lo general manejan. Lo que parece ser algo en común es que un comentario siempre termina con un final de línea, lo que significa que todos los comentarios actúan exactamente igual que las nuevas líneas.
fuente
En el pasado, convertí los comentarios en un solo token como parte del análisis léxico. Lo mismo ocurre con las cuerdas. A partir de ahí, la vida es fácil.
En el caso específico del último analizador que construí, se pasa una regla de escape a la rutina de análisis de nivel superior. La regla de escape se usa para manejar tokens como tokens de comentarios en línea con la gramática central. En general, estos tokens fueron descartados.
Una consecuencia de hacerlo de esta manera es que el ejemplo que publicó con un comentario en el medio de un identificador, el identificador no sería un solo identificador; este es el comportamiento esperado en todos los idiomas (de memoria) con los que he trabajado .
El caso de un comentario dentro de una cadena debe ser manejado implícitamente por el análisis léxico. Las reglas para manejar una cadena no tienen interés en los comentarios y, como tal, el comentario se trata como el contenido de la cadena. Lo mismo se aplica a una cadena (o literal citado) dentro de un comentario: la cadena es parte de un comentario, que es explícitamente un token único; Las reglas para procesar un comentario no tienen interés en las cadenas.
Espero que tenga sentido / ayuda.
fuente
console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")
, donde hay comillas en un comentario y sintaxis de comentario en una cadena, ¿cómo sabría el lexer tokenizarlo correctamente? ¿Puede editar su respuesta, proporcionando una descripción general de esos casos?Depende de qué propósito tenga su analizador. Si escribe un analizador para construir un árbol de análisis para la compilación, un comentario no tiene valor semántico además de los tokens potencialmente separados (por ejemplo, método / comentario / (/ comentario /)). En este caso, se trata como espacios.
Si su analizador es parte de un transpilador que traduce un idioma de origen a otro idioma de origen o si su analizador es un preprocesador que toma una unidad de compilación en un idioma de origen, analiza, modifica y escribe la versión modificada en el mismo idioma de origen, comentarios como cualquier otra cosa se vuelve muy importante.
Además, si tiene metainformación en los comentarios y le interesan especialmente los comentarios como cuando se genera documentación API como lo hace JavaDoc, los comentarios de repente son muy importantes.
Aquí los comentarios a menudo se adjuntan a los tokens en sí. Si encuentra un comentario, lo adjunta para que sea un comentario de un token. Como un token puede tener múltiples tokens antes y después, nuevamente depende del propósito de cómo manejar esos comentarios.
La idea de anotar tokens sin comentarios con comentarios es eliminar los comentarios de la gramática por completo.
Una vez que tiene el árbol de análisis, algunos AST comienzan a desempaquetar los comentarios que representan cada token por su propio elemento AST, pero se adjuntan a otro elemento AST junto a la relación de contención habitual. Una buena idea es verificar todas las implementaciones de analizador / AST para los idiomas de origen disponibles en IDE de código abierto.
Una muy buena implementación es la infraestructura del compilador Eclipse para el lenguaje Java. Conservan los comentarios durante la tokenización y representan comentarios dentro del AST, por lo que recuerdo. Además, esta implementación de analizador / AST conserva el formato.
fuente