如何在 Ada 中读取 yaml 文件

How to read yaml file in Ada

我正在尝试了解如何使用 Ada 和 AdaYaml 库 (https://github.com/yaml/AdaYaml/)。我有几个 yaml 文件,我需要将它们转换为 Ada 记录以供进一步处理。

玩了几个小时后,我不知道如何使用 Accessor 访问 yaml 数据。

我的最小工作代码是

with Ada.Text_IO;
with Ada.Command_Line;

with Yaml.Source.File;
with Yaml.Source.Text_IO;
with Yaml.Dom.Loading;
with Yaml.Dom.Node;
with Yaml; use Yaml;
with Text; use Text;

procedure Load_Dom is
   Input : Source.Pointer;
begin
   
   if Ada.Command_Line.Argument_Count = 0 then
      Input := Yaml.Source.Text_IO.As_Source (Ada.Text_IO.Standard_Input);
   else
      Input := Yaml.Source.File.As_Source (Ada.Command_Line.Argument (1));
   end if;
   
   declare
      
      Document : Yaml.Dom.Document_Reference :=
        Yaml.Dom.Loading.From_Source (Input);
     
   begin
      Ada.Text_IO.Put_Line ("Root node is a " & Yaml.Dom.Node.Instance'(Document.Root.Value).Kind'Img);
      Ada.Text_IO.Put_Line ("Root node is a " & Yaml.Dom.Node.Instance'(Document.Root.Value).Tag);
      Ada.Text_IO.Put_Line ("Root node is a " & Yaml.Dom.Node.Instance'(Document.Root.Value).Mapping_Style'Img);
   end;
end Load_Dom;

我认为显式转换 Yaml.Dom.Node.Instance'(Document.Root.Value) 不正确,我一定是遗漏了什么。

任何想法或代码示例如何以正确的方式读取 yaml 文件?

我是 AdaYaml 的作者。

Document.Root.Value返回的Accessor定义如下:

type Accessor (Data : not null access Node.Instance) is limited private
     with Implicit_Dereference => Data;

与任何具有判别式的类型一样,您可以通过其名称 Data 访问 Node.Instance。所以这个显式表达式检索根节点的种类:

Document.Root.Value.Data.all.Kind

现在 Ada 允许我们隐式取消引用指针,删除 .all:

Document.Root.Value.Data.Kind

并且 AccessorImplicit_Dereference 属性允许我们删除 .Data:

Document.Root.Value.Kind

所以你想做的是

declare
   Document : Yaml.Dom.Document_Reference :=
      Yaml.Dom.Loading.From_Source (Input);
   Root : Yaml.Dom.Accessor := Document.Root.Value; 
begin
   Ada.Text_IO.Put_Line ("Root node is a " & Root.Kind'Img);
   Ada.Text_IO.Put_Line ("Root node is a " & Root.Tag);
   Ada.Text_IO.Put_Line ("Root node is a " & Root.Mapping_Style'Img);
end;

这在 the documentation but not explained. For further reading, this gem 中进行了简要展示,您可能会感兴趣。

不是一个答案,而是(就其价值而言)对我对@flyx 的答案所做的评论(一个实际上看起来正确的答案)的补充。编译错误的问题(在 GNAT CE 2020 中)似乎是由包 Yaml.Dom 中使用的 limited with Yaml.Dom.Node 构造以及类型 [=17= 上的 Implicit_Dereference 方面触发的].可以使用下面的示例重现该问题。我目前不知道错误是否真的合法。

parent.ads

limited with Parent.Child;

package Parent is

  type Accessor (Data : not null access Child.Instance) is null record
     with Implicit_Dereference => Data;

end Parent;

parent-child.ads

package Parent.Child is
   
   type Instance (Value : Integer) is null record;

end Parent.Child;

main.adb

with Ada.Text_IO;
with Parent;
with Parent.Child;

procedure Main is
   Ref : Parent.Accessor (new Parent.Child.Instance (0));   
begin
   Ada.Text_IO.Put_Line (Ref.Value'Image);       --  Error
   Ada.Text_IO.Put_Line (Ref.Data.Value'Image);  --  OK
end Main;

输出(编译器)

$ gprbuild -P default.gpr 
Compile
   [Ada]          main.adb
main.adb:8:29: undefined selector "Value" for overloaded prefix
gprbuild: *** compilation phase failed

这是我设法工作的最小示例

with Ada.Text_IO;
with Ada.Command_Line;

with Yaml; use Yaml; -- this line is missing in https://ada.yaml.io/doc/Yaml.Dom/

with Yaml.Source.Text_IO;
with Yaml.Source.File;
with Yaml.Dom.Loading;
with Yaml.Dom.Node;

pragma Unreferenced (Yaml.Dom.Node);

procedure Load_Dom is
   use type Dom.Node_Kind;

   Input : Source.Pointer :=
     (if Ada.Command_Line.Argument_Count = 0 then
         Source.Text_IO.As_Source (Ada.Text_IO.Standard_Input)
      else
         Source.File.As_Source (Ada.Command_Line.Argument (1)));
   
   Document : Yaml.Dom.Document_Reference :=
     Dom.Loading.From_Source (Input);
   
   Root : constant not null access Dom.Node.Instance
     := Document.Root.Value.Data;
   
begin
   Ada.Text_IO.Put_Line
     ("Root node is a " & Root.Kind'Img);
end Load_Dom;