В качестве упражнения я пишу парсер для Haskell с нуля. Создавая лексер, я заметил следующие правила в отчете Haskell 2010 :
цифра → ascDigit | uniDigit
ascDigit →0
|1
| … |9
uniDigit → любая десятичная цифра Unicode
октит →0
|1
| … |7
hexit → цифра |A
| … |F
|a
| … |f
десятичное → значный { цифра }
восьмеричное → octit { octit }
шестнадцатеричное → hexit { hexit }целое число → десятичное число |
0o
восьмеричный |0O
восьмеричный |0x
шестнадцатеричный |0X
шестнадцатеричное число с
плавающей запятой → десятичное.
десятичное [ экспонента ] | показатель
степени десятичной дроби → (e
|E
) [+
|-
] десятичный
Десятичные и шестнадцатеричные литералы, а также литералы с плавающей запятой, все основаны на цифре , которая допускает любую десятичную цифру Unicode, вместо ascDigit , который допускает только основные цифры 0-9 из ASCII. Как ни странно, восьмеричное основано на октите , который вместо этого допускает только цифры ASCII 0-7. Я предполагаю, что эти десятичные цифры Unicode - это любые кодовые точки Unicode с общей категорией «Nd». Однако сюда входят такие символы, как цифры полной ширины 0-9 и цифры деванагари ०-९. Я могу понять, почему было бы желательно разрешить это в идентификаторах, но я не вижу никакой выгоды, позволяющей писать ९0
для литерала 90
.
GHC, похоже, согласен со мной. Когда я пытаюсь скомпилировать этот файл,
module DigitTest where
x1 = 1
это выплевывает эту ошибку.
digitTest1.hs:2:6: error: lexical error at character '\65297'
|
2 | x1 = 1
| ^
Тем не менее, этот файл
module DigitTest where
x1 = 1
компилируется просто отлично. Я неправильно читаю спецификацию языка? Является ли поведение GHC (разумное) действительно правильным, или оно технически противоречит спецификации в Отчете? Я не могу найти упоминания об этом нигде.