¿Debería un analizador Haskell permitir dígitos Unicode en literales numéricos?

15

Como ejercicio, estoy escribiendo un analizador para Haskell desde cero. Al hacer el lexer, noté las siguientes reglas en el Informe Haskell 2010 :

dígitoascDigit | uniDigit
ascDigit0| 1El | ... | 9
uniDigit → cualquier dígito decimal Unicode
octit0| 1El | ... | 7
hexitdígito | AEl | ... | FEl | aEl | ... |f

decimaldígito { dígito }
octaloctit { octit }
hexadecimalhexit { hexit }

enterodecimal | 0o octal | 0O octal | 0x hexadecimal | flotante 0X hexadecimaldecimal decimal [ exponente ] | decimal exponente exponente → ( | ) [ | ] decimal
.
eE+-

Los literales decimales y hexadecimales, junto con los literales flotantes, se basan en dígitos , que admiten cualquier dígito decimal Unicode, en lugar de ascDigit , que admite solo los dígitos básicos 0-9 de ASCII. Curiosamente, octal se basa en octit , que en cambio solo admite los dígitos ASCII 0-7. Supongo que estos "dígitos decimales Unicode" son puntos de código Unicode con la categoría general "Nd". Sin embargo, esto incluye caracteres como los dígitos de ancho completo 0-9 y los números de Devanagari ०-९. Puedo ver por qué sería deseable permitir estos en los identificadores, pero no veo ningún beneficio por permitir que uno escriba ९0para el literal 90.

GHC parece estar de acuerdo conmigo. Cuando intento compilar este archivo,

module DigitTest where
x1 = 

escupe este error.

digitTest1.hs:2:6: error: lexical error at character '\65297'
  |
2 | x1 = 
  |      ^

Sin embargo, este archivo

module DigitTest where
x = 1

compila muy bien. ¿Estoy leyendo la especificación del idioma incorrectamente? ¿Es correcto el comportamiento (sensible) de GHC, o técnicamente va en contra de la especificación en el Informe? No puedo encontrar ninguna mención de esto en ningún lado.

Ian Scherer
fuente
44
Gracioso. Sospecho que esto ocurrió como algo así como "Ok, entonces los literales solo consisten en dígitos ASCII, fácil". "No espere, pensemos en la internacionalización, Unicode ... también tienen otros símbolos de dígitos, ¿verdad?" "Oh sí, eh, nunca traté con eso ... pero está bien, insertemos una cláusula para eso ..." "Genial". ... y luego se olvidó y nadie se molestó en implementarlo, o se dio cuenta de que no tiene sentido permitir mezclar diferentes familias de dígitos.
Leftaroundabout
Yikes Sí, no te molestes con esto.
Boann

Respuestas:

8

En el archivo de código fuente de GHC compiler/parser/Lexer.x, puede encontrar el siguiente código:

ascdigit  = 0-9
$unidigit  = \x03 -- Trick Alex into handling Unicode. See [Unicode in Alex].
$decdigit  = $ascdigit -- for now, should really be $digit (ToDo)
$digit     = [$ascdigit $unidigit]
...
$binit     = 0-1
$octit     = 0-7
$hexit     = [$decdigit A-F a-f]
...
@numspc       = _*                   -- numeric spacer (#14473)
@decimal      = $decdigit(@numspc $decdigit)*
@binary       = $binit(@numspc $binit)*
@octal        = $octit(@numspc $octit)*
@hexadecimal  = $hexit(@numspc $hexit)*
@exponent     = @numspc [eE] [\-\+]? @decimal
@bin_exponent = @numspc [pP] [\-\+]? @decimal

Aquí, $decdigitse usa para analizar literales decimales y hexadecimales (y sus variantes de coma flotante), mientras que $digitse usa para la parte "numérica" ​​de los identificadores alfanuméricos. La nota "ToDo" deja en claro que esta es una desviación reconocida de GHC del estándar de idioma.

Entonces, está leyendo la especificación correctamente, y GHC está violando la especificación de forma semi intencional. Hay un boleto abierto que sugiere al menos documentar la desviación, pero no creo que nadie haya expresado ningún interés en solucionarlo.

KA Buhr
fuente
Las tres desviaciones enumeradas allí son bastante razonables. Puedo ver por qué no hay una demanda para "arreglarlos".
Ian Scherer