Um analisador Haskell deve permitir dígitos Unicode em literais numéricos?

15

Como exercício, estou escrevendo um analisador para Haskell do zero. Ao fazer o lexer, observei as seguintes regras no Relatório Haskell 2010 :

dígitoascDigit | uniDigit
ascDigit0| 1| ... 9
uniDigit → qualquer dígito decimal Unicode
octit0| 1| ... 7
hexágonodígito | A| ... F| a| ...f

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

número inteirodecimal | 0o octal | 0O octal | 0x hexadecimal | flutuação 0X hexadecimaldecimal decimal [ expoente ] | decimal expoente expoente → ( | ) [ | ] decimal
.
eE+-

Literais decimais e hexadecimais, junto com literais flutuantes, são todos baseados em dígitos , que admitem qualquer dígito decimal Unicode, em vez de ascDigit , que admite apenas os dígitos básicos de 0 a 9 do ASCII. Estranhamente, octal é baseado em octit , que em vez disso apenas admite os dígitos ASCII de 0 a 7. Eu acho que esses "dígitos decimais Unicode" são quaisquer pontos de código Unicode com a categoria geral "Nd". No entanto, isso inclui caracteres como os dígitos de largura total 0-9 e os números de Devanagari ०-९. Percebo por que seria desejável permitir isso nos identificadores, mas não vejo nenhum benefício em permitir que se escreva ९0para o literal 90.

O GHC parece concordar comigo. Quando tento compilar este arquivo,

module DigitTest where
x1 = 

cospe esse erro.

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

No entanto, esse arquivo

module DigitTest where
x = 1

compila muito bem. Estou lendo a especificação do idioma incorretamente? O comportamento (sensato) do GHC é realmente correto ou tecnicamente vai contra a especificação do relatório? Não encontro menção a isso em lugar nenhum.

Ian Scherer
fonte
4
Engraçado. Eu suspeito que isso tenha acontecido algo como "Ok, então literais consistem apenas em dígitos ASCII, fácil". "Não espere, vamos pensar na internacionalização, Unicode ... eles também têm outros símbolos de dígitos, certo?" "Ah sim, eh, nunca lidei com isso ... mas tudo bem, vamos inserir uma cláusula para isso ..." "Ótimo." ... e então foi esquecido e ninguém realmente se incomodou em implementá-lo, ou percebeu que não faz sentido permitir misturar diferentes famílias de dígitos.
leftaroundabout
Caramba. Sim, não se preocupe com isso.
Boann 27/01

Respostas:

8

No arquivo de código-fonte do GHC compiler/parser/Lexer.x, você pode encontrar o seguinte 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

Aqui, $decdigité usado para analisar literais decimais e hexadecimais (e suas variantes de ponto flutuante), enquanto $digité usado para a parte "numérica" ​​dos identificadores alfanuméricos. A nota "ToDo" deixa claro que este é um desvio reconhecido do GHC do padrão de idioma.

Então, você está lendo as especificações corretamente e o GHC está violando semi-intencionalmente as especificações. Há um ticket aberto que sugere pelo menos documentar o desvio, mas acho que ninguém manifestou interesse em corrigi-lo.

KA Buhr
fonte
Todos os três desvios listados são bastante razoáveis. Eu posso ver por que não há uma demanda para "consertá-los".
Ian Scherer