Un analyseur Haskell doit-il autoriser les chiffres Unicode dans les littéraux numériques?

15

Comme exercice, j'écris un analyseur pour Haskell à partir de zéro. En faisant le lexer, j'ai remarqué les règles suivantes sur le rapport Haskell 2010 :

digitascDigit | uniDigit
ascDigit0| 1| … | 9
uniDigit → tout
octet de chiffre décimal Unicode → 0| 1| … | 7
hexitchiffre | A| … | F| a| … |f

décimalchiffre { chiffre }
octaloctit { octit }
hexadécimalhexit { hexit }

entierdécimal | 0o octal | 0O octal | 0x hexadécimal | float 0X hexadécimaldécimal décimal [ exposant ] | exposant décimal exposant → ( | ) [ | ] décimal
.
eE+-

Les littéraux décimaux et hexadécimaux, ainsi que les littéraux flottants, sont tous basés sur digit , qui admet tout chiffre décimal Unicode, au lieu de ascDigit , qui n'admet que les chiffres de base 0-9 de ASCII. Étrangement, octal est basé sur octit , qui n'admet à la place que les chiffres ASCII 0-7. Je suppose que ces "chiffres décimaux Unicode" sont des points de code Unicode avec la catégorie générale "Nd". Cependant, cela inclut des caractères tels que les chiffres pleine largeur 0-9 et les chiffres Devanagari ०-९. Je peux voir pourquoi il pourrait être souhaitable de les autoriser dans les identifiants, mais je ne vois aucun avantage à permettre d'écrire ९0pour le littéral 90.

GHC semble d'accord avec moi. Lorsque j'essaie de compiler ce fichier,

module DigitTest where
x1 = 

il crache cette erreur.

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

Cependant, ce fichier

module DigitTest where
x = 1

compile très bien. Suis-je en train de lire la spécification de langue de manière incorrecte? Le comportement (sensé) de GHC est-il réellement correct ou va-t-il techniquement à l'encontre des spécifications du rapport? Je ne trouve aucune mention de cela nulle part.

Ian Scherer
la source
4
Drôle. Je soupçonne que cela est arrivé à quelque chose comme "Ok, donc les littéraux ne sont composés que de chiffres ASCII, c'est facile." "Ne vous en faites pas, pensons à l'internationalisation, Unicode ... ils ont aussi d'autres symboles numériques, non?" "Oh ouais, hein, je n'ai jamais traité de ça ... mais ok, insérons une clause pour ça ..." "Génial." ... et puis il a juste été oublié et personne n'a vraiment pris la peine de le mettre en œuvre, ou a remarqué que cela n'a pas de sens de permettre de mélanger différentes familles de chiffres.
leftaroundabout
Oui. Ouais, ne t'embête pas avec ça.
Boann

Réponses:

8

Dans le fichier de code source GHC compiler/parser/Lexer.x, vous pouvez trouver le code suivant:

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

Ici, $decdigitest utilisé pour analyser les littéraux décimaux et hexadécimaux (et leurs variantes à virgule flottante), tandis que $digitest utilisé pour la partie "numérique" des identificateurs alphanumériques. La note "ToDo" indique clairement qu'il s'agit d'un écart reconnu entre GHC et la norme linguistique.

Donc, vous lisez correctement la spécification, et GHC viole semi-intentionnellement la spécification. Il existe un ticket ouvert qui suggère au moins de documenter l'écart, mais je ne pense pas que quiconque ait exprimé un intérêt à le corriger.

KA Buhr
la source
Les trois écarts énumérés ici sont tout à fait raisonnables. Je peux voir pourquoi il n'y a pas d'exigence pour les "réparer".
Ian Scherer