【问题标题】:Should a Haskell parser allow Unicode digits in numeric literals?Haskell 解析器应该允许数字文字中的 Unicode 数字吗?
【发布时间】:2020-05-12 08:38:12
【问题描述】:

作为一个练习,我正在从头开始为 Haskell 编写一个解析器。在制作词法分析器时,我注意到Haskell 2010 Report 上有以下规则:

数字ascDigit | uniDigit
ascDigit0 | 1 | … | 9
uniDigit → 任何 Unicode 十进制数字
octit0 | 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


【解决方案1】:

在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 是在半有意地违反规范。有一个open ticket 建议至少记录偏差,但我认为没有人表示有兴趣修复它。

【讨论】:

  • 这里列出的所有三个偏差都是相当合理的。我明白为什么不需要“修复”它们了。
猜你喜欢
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2023-03-15
  • 2016-01-13
  • 2014-06-23
  • 1970-01-01
相关资源
最近更新 更多