【发布时间】:2020-05-12 08:38:12
【问题描述】:
作为一个练习,我正在从头开始为 Haskell 编写一个解析器。在制作词法分析器时,我注意到Haskell 2010 Report 上有以下规则:
数字 → ascDigit | uniDigit
ascDigit →0|1| … |9
uniDigit → 任何 Unicode 十进制数字
octit →0|1| … |7
hexit → 数字 |A| … |F|a| … |f十进制 → 数字{数字}
八进制 → 八进制 {八进制}
十六进制 → 十六进制{十六进制}整数 → 十进制 |
0o八进制 |0O八进制 |0x十六进制 |0X十六进制
浮点 → 十进制.十进制 [指数] | 十进制指数
指数 → (e|E) [+|-] 十进制
十进制和十六进制文字以及浮点文字都基于digit,它允许任何Unicode十进制数字,而不是ascDigit,它只允许基本数字来自 ASCII 的 0-9。奇怪的是,octal 是基于 octit 的,它只承认 ASCII 数字 0-7。我猜这些“Unicode 十进制数字”是任何具有“Nd”通用类别的 Unicode 代码点。但是,这包括全角数字 0-9 和梵文数字 ०-९ 等字符。我可以理解为什么在标识符中允许使用这些可能是可取的,但我认为允许将९0 写为文字90 没有任何好处。
GHC 似乎同意我的看法。当我尝试编译这个文件时,
module DigitTest where
x1 = 1
它会吐出这个错误。
digitTest1.hs:2:6: error: lexical error at character '\65297'
|
2 | x1 = 1
| ^
但是,这个文件
module DigitTest where
x1 = 1
编译得很好。我是否错误地阅读了语言规范? GHC 的(明智的)行为实际上是正确的,还是在技术上违反了报告中的规范?我在任何地方都找不到这件事。
【问题讨论】:
-
有趣。我怀疑这是因为“好吧,所以文字只包含 ASCII 数字,很简单”。 “别等了,让我们想想国际化,Unicode……它们也有其他数字符号,对吧?” “哦,是的,呃,从来没有处理过那个......但是好吧,让我们为此插入一个子句......” “太好了。” ...然后它就被遗忘了,没有人真正打扰过实现它,或者注意到允许混合不同的数字家族是没有意义的。
-
哎呀。是的,别管这个了。
标签: haskell syntax language-lawyer literals