Ada程序文本的实际字符集定义在哪里?



我正在尝试制作一个树- siter解析器,以便ide(在本例中是Vim)可以解析并对Ada程序文本进行更高级的操作,例如提取子程序和重命名变量。但是在字符集的定义上似乎有一些问题。

在Ada 2012参考手册中,我发现了一个模糊的类别描述列表,其形式为"一般类别为X的任何字符",这意味着例如,除了下划线之外,所有这些(⁔︳︴宿命宿命_)也允许在标识符中出现,这似乎是荒谬的,GNAT拒绝"非法字符"。该列表以以下语句开头:

"没有指定实现用于可视化表示Ada程序文本的图形符号的实际集合。">

这真的意味着没有办法知道哪些字符应该被接受吗?

两页后,这些例子被明确地作为有效标识符给出,但GNAT 2021拒绝了它们:

procedure Main is
Πλάτων  : constant := 12;     -- Plato
Чайковский : constant := 12;  -- Tchaikovsky
θ, φ : constant := 12;        -- Angles
begin
null;
end Main;
$ gprbuild
using project file foo.gpr
Compile
[Ada]          main.adb
main.adb:2:04: error: declaration expected
main.adb:2:05: error: illegal character
main.adb:3:04: error: declaration expected
main.adb:3:05: error: illegal character
main.adb:4:05: error: illegal character
gprbuild: *** compilation phase failed

Ada程序的实际字符集定义在哪里?GNAT 2021错了吗?

下面是一个在标识符中使用Unicode字符的示例程序,供您进行实验。请注意,在字面值字符串中使用宽字符超出了问题的范围。

main.adb:

with Ada.Wide_Text_IO; use Ada.Wide_Text_IO;
procedure Main is
δεδομένα_πράμα : constant Wide_String := "Ο Πλάτων θα ενέκρινε";
begin
Put_Line (Δεδομένα_πράμα);
end Main;

foo.gpr

project foo is
for Source_Dirs use (".");
for Main use ("main.adb");
package Compiler is
for Default_Switches ("ada") use ("-gnatW8", "-gnatiw");
end Compiler;
end foo;

构建&运行:

gprbuild
./main

自Ada 2005以来的所有Ada版本都要求实现支持UTF-8源代码,但对于Ada 83 &95兼容性不要求它是默认的编码。GNAT的默认源编码是Latin-1,但如果找到字节顺序标记,它会有用地切换到UTF-8。要显式地指定文件编码,您可以传递-gnatW8标志,或许多其他选项之一。

然而,虽然在源文件中允许UTF-8,但在GNAT中标识符仍然限于Latin-1,您还必须传递-gnatiw标志以允许标识符中的宽字符。GNAT似乎没有默认使用它,因为您可以制作非常奇怪的标识符(如您所述),但也因为标识符将不再正确地区分大小写;GNAT在任何宽字符集上进行最小的大小写折叠,除了在它支持的其他编码中存在的字符。

ARM§2.3规定了标识符的要求:identifier ::= identifier_start {identifier_start | identifier_extend},其中identifier_start可以概括为Unicode通用类别L中的任何字符,其余字符可以是数字、punctuation_connector、小数点和非空白组合标记,附加的限制是"标识符不得包含punctuation_connector类别中连续的两个字符,或者以该类别中的字符结尾。"

除了你的问题之外,请注意,尽管有所有这些标志,字符串仍然被编码为Latin-1(矛盾的是,字符串字面值是UTF-8,而不是底层字符串:/)。您需要使用Ada.Strings.UTF_Encoding,Wide_Wide_Strings和/或像VSS这样的库来处理Unicode字符串。

最新更新