Должен ли синтаксический анализатор Haskell допускать цифры Unicode в цифрах c? - PullRequest
15 голосов
/ 27 января 2020

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

di gitascDi git | uniDi git
ascDi git0 | 1 | … | 9
uniDi git → любой десятичный код Unicode di git
октит 0 | 1 | … | 7
hexit di git | A | … | F | a | … | f

десятичный di git { di git}
восьмеричное октит { октит }
шестнадцатеричный hexit { hexit }

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

Десятичные и шестнадцатеричные литералы, а также литералы с плавающей точкой основаны на di git, который допускает любой десятичный код Unicode di git вместо ascDi git, который допускает только базовые c цифры 0-9 от ASCII. Странно, но восьмеричное основано на восьмеричном , который вместо этого допускает только цифры ASCII 0-7. Я бы предположил, что эти "Unicode decimal di git" - это любые кодовые точки Unicode с общей категорией "Nd". Однако сюда входят такие символы, как цифры полной ширины 0-9 и цифры деванагари ०-९. Я понимаю, почему было бы желательно разрешить это в идентификаторах, но я не вижу никакой выгоды, если разрешить писать ९0 для литерала 90.

GH C, похоже, согласен с меня. Когда я пытаюсь скомпилировать этот файл,

module DigitTest where
x1 = 1

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

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

Однако этот файл

module DigitTest where
x1 = 1

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

1 Ответ

8 голосов
/ 27 января 2020

В файле исходного кода GH C 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 используется для части "цифра c" идентификаторов alphanumeri c. В примечании «ToDo» разъясняется, что это признанное отклонение GH C от языкового стандарта.

Итак, вы правильно читаете spe c, а GH C полу -намышленно нарушая спец. c. Существует открытый билет , который предполагает, по крайней мере, документировать отклонение, но я не думаю, что кто-либо выразил какую-либо заинтересованность в его исправлении.

...