Должен ли анализатор Haskell разрешать цифры Unicode в числовых литералах?

15

В качестве упражнения я пишу парсер для Haskell с нуля. Создавая лексер, я заметил следующие правила в отчете Haskell 2010 :

цифраascDigit | uniDigit
ascDigit0| 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 = 

это выплевывает эту ошибку.

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

Тем не менее, этот файл

module DigitTest where
x = 1

компилируется просто отлично. Я неправильно читаю спецификацию языка? Является ли поведение GHC (разумное) действительно правильным, или оно технически противоречит спецификации в Отчете? Я не могу найти упоминания об этом нигде.

Ян Шерер
источник
4
Веселая. Я подозреваю, что это произошло примерно так: «Хорошо, поэтому литералы просто состоят из цифр ASCII, просто». «Не стойте, давайте подумаем об интернационализации, Unicode ... у них также есть другие цифровые символы, верно?» «О, да, да, никогда не имел дело с этим ... но хорошо, давайте вставим пункт для этого ...» «Отлично». ... а потом об этом просто забыли, и никто даже не удосужился его реализовать, или заметили, что нет смысла смешивать разные семейства цифр.
оставил около
Хлоп. Да, не беспокойся об этом.
Boann

Ответы:

8

В файле исходного кода GHC compiler/parser/Lexer.xвы можете найти следующий код:

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

Здесь $decdigitиспользуется для анализа десятичных и шестнадцатеричных литералов (и их вариантов с плавающей запятой), а $digitиспользуется для «числовой» части буквенно-цифровых идентификаторов. В примечании «ToDo» разъясняется, что это признанное отклонение GHC от языкового стандарта.

Итак, вы правильно читаете спецификацию, а GHC намеренно нарушает спецификацию. Есть открытый билет, который предлагает, по крайней мере, документировать отклонение, но я не думаю, что кто-либо выразил какой-либо интерес к его исправлению.

К. А. Бур
источник
Все три перечисленных отклонения вполне разумны. Я понимаю, почему нет требования «исправить» их.
Ян Шерер