Ada 是否将文件类型用作记录组件?

Ada 是否将文件类型用作记录组件?,ada,Ada,我正试图用Ada写一个lexer,但遇到了一个问题 过程是主要的 ... 类型lexer被标记为记录 输入:ada.text\u io.file\u类型; 索引:整数; 结束记录; ... 我的lexer:lexer; 输入文件名称:有界字符串; 输入文件:ada.text\u io.file\u类型; 下一个令牌:令牌; 开始 输入文件名称:=获取输入文件; ada.text\u io.open( file=>input_文件, mode=>ada.text\u io.in\u文件, 名称=>

我正试图用Ada写一个lexer,但遇到了一个问题

过程是主要的
...
类型lexer被标记为记录
输入:ada.text\u io.file\u类型;
索引:整数;
结束记录;
...
我的lexer:lexer;
输入文件名称:有界字符串;
输入文件:ada.text\u io.file\u类型;
下一个令牌:令牌;
开始
输入文件名称:=获取输入文件;
ada.text\u io.open(
file=>input_文件,
mode=>ada.text\u io.in\u文件,
名称=>到\u字符串(输入\u文件\u名称)
);
my_lexer:=(输入=>input_文件,索引=>0);
next\u token:=my\u lexer.get\u next\u token;
ada.text_io.put_行(到_字符串(next_token.text));
端干管;
my\u lexer:=(input=>input\u文件)行上我得到以下错误:

main.adb:22:17: nonlimited tagged type cannot have limited components
我理解这是一个问题,因为
ada.text\u io.in\u file
是一个有限的类型,但是如果我只是从记录中删除它,而是将其作为参数传递给
get\u next\u token

。。。
类型lexer被标记为记录
索引:整数;
结束记录;
函数get_next_token(this:lexer'class;input_file:ada.text_io.file_type)返回标记;
...
如果要在调用
get\u next\u令牌
之间切换
input\u文件
,则这将使lexer的状态无效,从而破坏它

在Ada中有没有一种方法可以像在C中一样创建这样的东西

struct lexer{
文件*输入;
整数指数;
};

允许将
lexer
类型标记为
有限的
的一种方法是在适当的位置创建有限的对象,以便其组件(特别是有限的
文件类型
组件)不会在其他位置创建(合法)然后分配(复制,非法)。在这种情况下,
lexer
文件
组件被传递到
Open
调用,该调用将对其进行就地更新

程序lex2是
类型lexer被标记为有限记录
输入:ada.text\u io.file\u类型;
索引:整数;
结束记录;
输入\u文件\u名称:无界\u字符串;
我的lexer:lexer;
--下一个令牌:令牌;
开始
输入文件名称:=获取输入文件;
my_lexer.index:=0;
ada.text\u io.open(file=>my\u lexer.input,
mode=>ada.text\u io.in\u文件,
name=>to_字符串(输入_文件_名称));
--next\u token:=my\u lexer.get\u next\u token;
--ada.text_io.put_行(到_字符串(next_token.text));
末端lex2;

允许将
lexer
类型标记为
有限的
的一种方法是在适当的位置创建有限的对象,以便其组件(特别是有限的
文件类型
组件)不会在其他位置创建(合法)然后分配(复制,非法)。在这种情况下,
lexer
文件
组件被传递到
Open
调用,该调用将对其进行就地更新

程序lex2是
类型lexer被标记为有限记录
输入:ada.text\u io.file\u类型;
索引:整数;
结束记录;
输入\u文件\u名称:无界\u字符串;
我的lexer:lexer;
--下一个令牌:令牌;
开始
输入文件名称:=获取输入文件;
my_lexer.index:=0;
ada.text\u io.open(file=>my\u lexer.input,
mode=>ada.text\u io.in\u文件,
name=>to_字符串(输入_文件_名称));
--next\u token:=my\u lexer.get\u next\u token;
--ada.text_io.put_行(到_字符串(next_token.text));
末端lex2;

我不确定这是否是最好的解决方案,但这就是我想到的:

过程是主要的
类型file\u access是access all ada.text\u io.file\u类型;
...
类型lexer被标记为记录
输入:文件访问;
索引:整数;
结束记录;
...
我的lexer:lexer;
输入文件名称:有界字符串;
输入文件:别名为ada.text\u io.file\u类型;
下一个令牌:令牌;
开始
输入文件名称:=获取输入文件;
ada.text\u io.open(
file=>input_文件,
mode=>ada.text\u io.in\u文件,
名称=>到\u字符串(输入\u文件\u名称)
);
my_lexer:=(输入=>input_文件访问,索引=>0);
next\u token:=my\u lexer.get\u next\u token;
ada.text_io.put_行(到_字符串(next_token.text));
端干管;

似乎有点复杂,但我相信这是一种确保对
输入文件的访问寿命与过程一样长的方法。

我不确定这是否是最好的解决方案,但这就是我想到的:

过程是主要的
类型file\u access是access all ada.text\u io.file\u类型;
...
类型lexer被标记为记录
输入:文件访问;
索引:整数;
结束记录;
...
我的lexer:lexer;
输入文件名称:有界字符串;
输入文件:别名为ada.text\u io.file\u类型;
下一个令牌:令牌;
开始
输入文件名称:=获取输入文件;
ada.text\u io.open(
file=>input_文件,
mode=>ada.text\u io.in\u文件,
名称=>到\u字符串(输入\u文件\u名称)
);
my_lexer:=(输入=>input_文件访问,索引=>0);
next\u token:=my\u lexer.get\u next\u token;
ada.text_io.put_行(到_字符串(next_token.text));
端干管;

看起来有点复杂,但我相信这是一种确保对
输入文件的访问在整个过程中持续的方法。

我要做的是隐藏所有这些细节并创建一个抽象:

package Lexing is
   type Info is tagged limited private;

   function Is_Open (State : in Info) return Boolean;
   -- Description of subprogram here

   procedure Open (State : in out Info; Name : in String) with
      Pre  => not State_Is_Open,
      Post => State.Is_Open;
   -- Description of subprogram here

   procedure Close (State : in out Info) with
      Pre  => State.Is_Open,
      Post => not State.Is_Open;
   -- Description of subprogram here

   type Token_Info is tagged private;

   function Next (State : in out Info) return Token_Info with
      Pre => State.Is_Open;
   -- Description of subprogram here

   function Text (Token : in Token_Info) return String;
   -- Description of subprogram here

   ...
private -- Lexing
   ...
end Lexing;

显然,有趣的部分留给读者作为练习。

我要做的是隐藏所有这些细节并创建一个抽象:

package Lexing is
   type Info is tagged limited private;

   function Is_Open (State : in Info) return Boolean;
   -- Description of subprogram here

   procedure Open (State : in out Info; Name : in String) with
      Pre  => not State_Is_Open,
      Post => State.Is_Open;
   -- Description of subprogram here

   procedure Close (State : in out Info) with
      Pre  => State.Is_Open,
      Post => not State.Is_Open;
   -- Description of subprogram here

   type Token_Info is tagged private;

   function Next (State : in out Info) return Token_Info with
      Pre => State.Is_Open;
   -- Description of subprogram here

   function Text (Token : in Token_Info) return String;
   -- Description of subprogram here

   ...
private -- Lexing
   ...
end Lexing;

显然,有趣的部分留给读者作为练习。

通常当你遇到这样的问题时,有两种解决方案

  • 定义一个可访问
    受限
    类型的新类型,并在记录中使用它,或
  • 使您的类型
    有限
    。这可能是(在我看来)更清洁的解决方案,因为你不必告诉我