Sollte ein Haskell-Parser Unicode-Ziffern in numerischen Literalen zulassen?

15

Als Übung schreibe ich einen Parser für Haskell von Grund auf neu. Bei der Erstellung des Lexers habe ich die folgenden Regeln im Haskell 2010-Bericht beachtet :

ZifferascDigit | uniDigit
ascDigit0| 1| … | 9
uniDigit → beliebiges Unicode-Dezimalstellen-
Oktit0| 1| … | 7
hexitZiffer | A| … | F| a| … |f

DezimalZiffer { Ziffer }
OktalOktit { Oktit }
HexadezimalHexit { Hexit }

GanzzahlDezimalzahl | 0o oktal | 0O oktal | 0x hexadezimal | 0X hexadezimaler
Gleitkommawertdezimaler . Dezimalwert [ Exponent ] | Dezimalexponenten
Exponent → ( e| E) [ +| -] dezimal

Dezimal- und Hexadezimalliterale sowie Float-Literale basieren alle auf einer Ziffer , die eine beliebige Unicode-Dezimalstelle zulässt, anstelle von ascDigit , die nur die Grundziffern 0-9 aus ASCII zulässt. Seltsamerweise basiert Oktal auf Oktit , das stattdessen nur die ASCII-Ziffern 0-7 zulässt. Ich würde vermuten, dass diese "Unicode-Dezimalstellen" beliebige Unicode-Codepunkte mit der allgemeinen Kategorie "Nd" sind. Dies schließt jedoch Zeichen wie die Ziffern Full-9 in voller Breite und die Devanagari-Ziffern ०-९ ein. Ich kann sehen, warum es wünschenswert sein könnte, diese in Bezeichnern zuzulassen, aber ich kann überhaupt keinen Vorteil darin sehen, dass man ९0für das Literal schreiben darf 90.

GHC scheint mir zuzustimmen. Wenn ich versuche, diese Datei zu kompilieren,

module DigitTest where
x1 = 

es spuckt diesen Fehler aus.

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

Allerdings diese Datei

module DigitTest where
x = 1

kompiliert ganz gut. Lese ich die Sprachspezifikation falsch? Ist das (vernünftige) Verhalten von GHC tatsächlich korrekt oder widerspricht es technisch der Spezifikation im Bericht? Ich kann das nirgendwo erwähnen.

Ian Scherer
quelle
4
Komisch. Ich vermute, dass dies so etwas wie "Ok, also bestehen Literale nur aus ASCII-Ziffern, einfach." "Kein Moment, denken wir an Internationalisierung, Unicode ... sie haben auch andere Ziffernsymbole, oder?" "Oh ja, eh, habe mich nie damit befasst ... aber ok, lass uns eine Klausel dafür einfügen ..." "Großartig." ... und dann wurde es einfach vergessen und niemand hat sich die Mühe gemacht, es jemals zu implementieren, oder bemerkt, dass es keinen Sinn macht, das Mischen verschiedener Ziffernfamilien zuzulassen.
Links um den
Huch. Ja, kümmere dich nicht darum.
Boann

Antworten:

8

In der GHC-Quellcodedatei compiler/parser/Lexer.xfinden Sie den folgenden Code:

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

Hier $decdigitwird zum Parsen von Dezimal- und Hexadezimalliteralen (und ihren Gleitkommavarianten) verwendet, während $digitfür den "numerischen" Teil von alphanumerischen Bezeichnern verwendet wird. Der Hinweis "ToDo" macht deutlich, dass dies eine anerkannte Abweichung von GHC vom Sprachstandard ist.

Sie lesen die Spezifikation also richtig und GHC verletzt die Spezifikation absichtlich. Es gibt ein offenes Ticket , das zumindest die Dokumentation der Abweichung vorschlägt, aber ich glaube, niemand hat Interesse daran bekundet, sie zu beheben.

KA Buhr
quelle
Alle drei dort aufgeführten Abweichungen sind durchaus vernünftig. Ich kann sehen, warum es keine Nachfrage gibt, sie zu "reparieren".
Ian Scherer