Чи повинен аналізатор Haskell допускати цифри Unicode в числових літералах?


15

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

цифраascDigit | uniDigit
ascDigit0| 1| … | 9
uniDigit → будь-який десятковий
октіт Unicode → 0| 1| … | 7
hexitцифра | A| … | F| a| … |f

десятковацифра { цифра }
восьмеричнаоктіт { октіт }
шістнадцятковагексит { гексит }

ціле числодесятковий | 0o вісімковий | 0O вісімковий | 0x шістнадцятковий | 0X шістнадцятковий
поплавокдесяткова . десяткова [ показник ] | десятковий показник
експонента → ( e| E) [ +| -] десятковий

Десяткові та шістнадцяткові літерали, поряд з плаваючими літералами, базуються на цифрі , яка допускає будь-яку десяткову цифру Unicode, а не ascDigit , яка допускає лише основні цифри 0-9 від ASCII. Як не дивно, восьмерика заснована на октіті , який замість цього допускає лише цифри ASCII 0-7. Я б здогадався, що ці "десяткові цифри Unicode" є будь-якими кодовими точками Unicode із загальною категорією "Nd". Однак сюди входять такі символи, як цифри повної ширини 0-0 та цифри Devanagari ०-९. Я бачу, чому може бути бажаним дозволити це в ідентифікаторах, але я не бачу ніякої користі за те, щоб дозволити писати ९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 ... вони також мають інші цифри, так?" "О так, так, ніколи не займалися цим ... але гаразд, давайте вставити для цього пункт ..." "Чудово". ... а потім це було просто забуто, і ніхто насправді не заважав ніколи його реалізовувати, або не помічав, що не має сенсу допускати змішування різних сімейств цифр.
близько

Yikes. Так, не турбуйся цим.
Боан

Відповіді:


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 напів умисно порушує специфікацію. Існує відкритий квиток, який пропонує хоча б документувати відхилення, але я не думаю, що хтось висловлював зацікавленість у його виправленні.


Усі три перераховані там відхилення є цілком обґрунтованими. Я бачу, чому немає вимоги "виправити" їх.
Ян Шерер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.