【问题标题】:Escaped Characters Outside the Basic Multilingual Plane (BMP) in PrologProlog 中基本多语言平面 (BMP) 之外的转义字符
【发布时间】:2018-01-22 11:06:44
【问题描述】:

作为参考,我在 Windows 10 64 位上使用 Prolog v7.4.2

在 REPL 中输入以下代码:

write("\U0001D7F6"). % Mathematical Monospace Digit Zero

在输出中给了我这个错误:

ERROR: Syntax error: Illegal character code
ERROR: write("
ERROR: ** here **
ERROR: \U0001D7F6") .

我知道 U+1D7F6 是一个有效的 Unicode 字符,这是怎么回事?

【问题讨论】:

    标签: unicode prolog swi-prolog unicode-escapes iso-prolog


    【解决方案1】:

    SWI-Prolog 内部使用 C wchar_t 来表示 Unicode 字符。在 Windows 上,这些是 16 位的,旨在保存 UTF-16 编码的字符串。然而,SWI-Prolog 使用 wchar_t 来获得漂亮的代码点数组,因此有效地仅支持 Windows 上的 UCS-2(代码点 u0000..uffff)。

    在非 Windows 系统上,wchar_t 通常为 32 位,因此支持完整的 Unicode 范围。

    处理wchar_t 并不是一件容易的事,因为 UTF-16 失去了数组的每个元素都是一个代码点的好属性,并且使用我们自己的 32 位类型意味着我们不能使用 C 库宽字符函数,并且必须在 SWI-Prolog 中重新实现它们。这不仅可行,而且用纯 C 版本替换它们也会失去现代 C 运行时库中通常存在的优化。

    【讨论】:

      【解决方案2】:

      字符代码的 ISO 核心标准语法看起来不同。例如,以下适用于 SICStus Prolog、Jekejeke Prolog、SWI-Prolog 等,因此更便携:

      在 Mac 上使用 SWI-Prolog:

      Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
      SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
      
      ?- set_prolog_flag(double_quotes, codes).
      true.
      
      ?- X = "\x1D7F6\".
      X = [120822].
      
      ?- write('\x1D7F6\'), nl.
      ?
      

      Mac 上的 Jekejeke Prolog:

      Jekejeke Prolog 2, Runtime Library 1.2.2
      (c) 1985-2017, XLOG Technologies GmbH, Switzerland
      
      ?- X = "\x1D7F6\".
      X = [120822]
      
      ?- write('\x1D7F6\'), nl.
      ?
      

      基本语法可在 ISO 核心标准第 6.4.2.1 节十六进制转义序列中找到。它的内容如下,比 U 语法短:

      hex_esc_seq --> "\x" hex_digit { hex_digit } "\".
      

      【讨论】:

        【解决方案3】:

        为了比较,我得到:

        ?- 写('\U0001D7F6')。 ?

        你的环境是什么?标志说明了什么?

        例如:

        $ 设置 | grep 朗 LANG=en_US.UTF-8

        还有:

        ?- current_prolog_flag(编码,F)。 F = utf8.

        【讨论】:

        • 我的编码显然是“文本”。我如何告诉 prolog 使用 UTF-8?
        • 查看encodingset_stream/2 的帮助。您可能需要设置一些环境变量或等效配置。
        • 你正在使用终端流。
        • 请参阅有关encodingset_stream/2 的部分。特别是,别名 current_inputcurrent_output 可能对您的情况很重要。使用 ?- set_stream(current_input, encoding(utf8)).?- set_stream(current_output, encoding(utf8)). 可能会有所帮助,但我现在只能猜测。
        • 它在读取期间报告了一个语法错误。如果你在 Unix 系统上运行这段代码,其 locale 不能代表这个字符,读没问题,但 writing 会引发 I/O 错误(不是在终端上;那里的值被转义)。
        猜你喜欢
        • 2018-02-03
        • 2012-04-03
        • 2011-12-13
        • 1970-01-01
        • 1970-01-01
        • 2011-05-01
        • 2013-10-23
        • 2015-10-27
        相关资源
        最近更新 更多