Haruskah parser Haskell memperbolehkan digit Unicode dalam literal angka?

15

Sebagai latihan, saya menulis parser untuk Haskell dari awal. Dalam membuat lexer, saya perhatikan aturan berikut pada Laporan Haskell 2010 :

digitascDigit | uniDigit
ascDigit0| 1| … | 9
uniDigit → setiap Unicode desimal digit
octit0| 1| … | 7
hexitdigit | A| … | F| a| … |f

desimaldigit { digit }
oktaloktit { oktit }
heksadesimalhexit { heksit }

integerdesimal | 0o oktal | 0O oktal | 0x heksadesimal | 0X hexadecimal
floatdesimal . desimal [ eksponen ] | eksponen
eksponen desimal → ( e| E) [ +| -] desimal

Literal desimal dan heksadesimal, bersama dengan float literals, semuanya didasarkan pada digit , yang menerima digit desimal Unicode, alih-alih ascDigit , yang hanya menerima digit dasar 0-9 dari ASCII. Anehnya, oktal didasarkan pada octit , yang sebaliknya hanya mengakui angka ASCII 0-7. Saya akan menebak bahwa ini "Unicode desimal digit" s adalah setiap codepoint Unicode dengan Kategori Umum "Nd". Namun, ini termasuk karakter seperti digit Lebar Penuh 0-9 dan angka Devanagari ०-९. Saya dapat melihat mengapa mungkin diinginkan untuk memungkinkan ini dalam pengidentifikasi, tetapi saya tidak dapat melihat manfaat apa pun untuk membiarkan seseorang menulis ९0untuk literal 90.

GHC tampaknya setuju dengan saya. Ketika saya mencoba mengkompilasi file ini,

module DigitTest where
x1 = 

itu memuntahkan kesalahan ini.

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

Namun, file ini

module DigitTest where
x = 1

mengkompilasi dengan baik. Apakah saya salah membaca spesifikasi bahasa? Apakah perilaku (masuk akal) GHC benar, atau apakah secara teknis bertentangan dengan spesifikasi dalam Laporan? Saya tidak dapat menemukan ini di mana pun.

Ian Scherer
sumber
4
Lucu. Saya menduga ini muncul kira-kira seperti, "Oke, jadi literal hanya terdiri dari angka ASCII, mudah." "Jangan tunggu, mari kita pikirkan internasionalisasi, Unicode ... mereka juga memiliki simbol angka lainnya, kan?" "Oh yeah, eh, tidak pernah berurusan dengan itu ... tapi ok, mari kita memasukkan klausa untuk itu ..." "Hebat." ... dan kemudian hanya dilupakan dan tidak ada yang benar-benar peduli untuk mengimplementasikannya, atau memperhatikan bahwa tidak masuk akal untuk memungkinkan pencampuran keluarga digit yang berbeda.
leftaroundabout
Astaga. Ya, jangan repot-repot dengan ini.
Boann

Jawaban:

8

Di file kode sumber GHC compiler/parser/Lexer.x, Anda dapat menemukan kode berikut:

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

Di sini, $decdigitdigunakan untuk parsing desimal dan heksadesimal (dan varian floating point mereka), sementara $digitdigunakan untuk bagian "numerik" pengidentifikasi alfanumerik. Catatan "ToDo" memperjelas bahwa ini adalah penyimpangan GHC yang diakui dari standar bahasa.

Jadi, Anda membaca spek dengan benar, dan GHC secara sengaja melanggar spek. Ada tiket terbuka yang menyarankan setidaknya mendokumentasikan penyimpangan, tetapi saya tidak berpikir ada orang yang menyatakan minat untuk memperbaikinya.

KA Buhr
sumber
Ketiga penyimpangan yang tercantum di sana cukup masuk akal. Saya bisa melihat mengapa tidak ada permintaan untuk "memperbaikinya".
Ian Scherer