使用 File_Type 作为记录组件?
Using File_Type as a record component?
我正在尝试用 Ada 编写词法分析器,但遇到了 运行 问题。
procedure main is
...
type lexer is tagged record
input : ada.text_io.file_type;
index : integer;
end record;
...
my_lexer : lexer;
input_file_name : bounded_string;
input_file : ada.text_io.file_type;
next_token : token;
begin
input_file_name := get_input_file;
ada.text_io.open(
file => input_file,
mode => ada.text_io.in_file,
name => to_string(input_file_name)
);
my_lexer := (input => input_file, index => 0);
next_token := my_lexer.get_next_token;
ada.text_io.put_line(to_string(next_token.text));
end main;
在线my_lexer := (input => input_file);
我收到以下错误:
main.adb:22:17: nonlimited tagged type cannot have limited components
我知道这是一个问题,因为 ada.text_io.in_file
是一个受限类型,但如果我只是将其从记录中删除,而是将其作为参数传递给 get_next_token
,
...
type lexer is tagged record
index : integer;
end record;
function get_next_token(this: lexer'class; input_file: ada.text_io.file_type) return token;
...
然后,如果您要在 get_next_token
的调用之间切换 input_file
从而破坏它,这将使词法分析器的状态无效。
有没有办法在 Ada 中像在 C 中那样创建类似的东西?
struct lexer {
FILE *input;
int index;
};
允许 lexer
类型为 tagged limited
的一种方法是就地创建受限对象,以便其组件(特别是受限 file_type
组件)' t 在别处创建(合法)然后分配(复制,非法)。在这种情况下,lexer
的 file
组件被传递给 Open
调用,该调用就地更新它。
procedure lex2 is
type lexer is tagged limited record
input : ada.text_io.file_type;
index : integer;
end record;
input_file_name : unbounded_string;
my_lexer : lexer;
-- next_token : token;
begin
input_file_name := get_input_file;
my_lexer.index := 0;
ada.text_io.open( file => my_lexer.input,
mode => ada.text_io.in_file,
name => to_string(input_file_name));
-- next_token := my_lexer.get_next_token;
-- ada.text_io.put_line(to_string(next_token.text));
end lex2;
我不确定这是否是最佳解决方案,但这是我想出的:
procedure main is
type file_access is access all ada.text_io.file_type;
...
type lexer is tagged record
input : file_access;
index : integer;
end record;
...
my_lexer : lexer;
input_file_name : bounded_string;
input_file : aliased ada.text_io.file_type;
next_token : token;
begin
input_file_name := get_input_file;
ada.text_io.open(
file => input_file,
mode => ada.text_io.in_file,
name => to_string(input_file_name)
);
my_lexer := (input => input_file'access, index => 0);
next_token := my_lexer.get_next_token;
ada.text_io.put_line(to_string(next_token.text));
end main;
似乎有点令人费解,但我相信这是一种确保 input_file
的访问与过程一样长的方法。
我要做的是隐藏所有这些细节并创建一个抽象:
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;
显然,有趣的部分留作 reader 的练习。
通常当你运行遇到这样的问题时,有两种解决方案
- 定义一个新类型,它是对
limited
类型的访问,并在您的记录中使用它,或者
- 打字
limited
。这可能(在我看来)是更清洁的解决方案,因为您不必处理分配、释放和其他事情。 (就个人而言,我尽量避免访问类型)。当然,限制它会阻止你分配它,但在词法分析器的情况下这可能不是主要问题。
我正在尝试用 Ada 编写词法分析器,但遇到了 运行 问题。
procedure main is
...
type lexer is tagged record
input : ada.text_io.file_type;
index : integer;
end record;
...
my_lexer : lexer;
input_file_name : bounded_string;
input_file : ada.text_io.file_type;
next_token : token;
begin
input_file_name := get_input_file;
ada.text_io.open(
file => input_file,
mode => ada.text_io.in_file,
name => to_string(input_file_name)
);
my_lexer := (input => input_file, index => 0);
next_token := my_lexer.get_next_token;
ada.text_io.put_line(to_string(next_token.text));
end main;
在线my_lexer := (input => input_file);
我收到以下错误:
main.adb:22:17: nonlimited tagged type cannot have limited components
我知道这是一个问题,因为 ada.text_io.in_file
是一个受限类型,但如果我只是将其从记录中删除,而是将其作为参数传递给 get_next_token
,
...
type lexer is tagged record
index : integer;
end record;
function get_next_token(this: lexer'class; input_file: ada.text_io.file_type) return token;
...
然后,如果您要在 get_next_token
的调用之间切换 input_file
从而破坏它,这将使词法分析器的状态无效。
有没有办法在 Ada 中像在 C 中那样创建类似的东西?
struct lexer {
FILE *input;
int index;
};
允许 lexer
类型为 tagged limited
的一种方法是就地创建受限对象,以便其组件(特别是受限 file_type
组件)' t 在别处创建(合法)然后分配(复制,非法)。在这种情况下,lexer
的 file
组件被传递给 Open
调用,该调用就地更新它。
procedure lex2 is
type lexer is tagged limited record
input : ada.text_io.file_type;
index : integer;
end record;
input_file_name : unbounded_string;
my_lexer : lexer;
-- next_token : token;
begin
input_file_name := get_input_file;
my_lexer.index := 0;
ada.text_io.open( file => my_lexer.input,
mode => ada.text_io.in_file,
name => to_string(input_file_name));
-- next_token := my_lexer.get_next_token;
-- ada.text_io.put_line(to_string(next_token.text));
end lex2;
我不确定这是否是最佳解决方案,但这是我想出的:
procedure main is
type file_access is access all ada.text_io.file_type;
...
type lexer is tagged record
input : file_access;
index : integer;
end record;
...
my_lexer : lexer;
input_file_name : bounded_string;
input_file : aliased ada.text_io.file_type;
next_token : token;
begin
input_file_name := get_input_file;
ada.text_io.open(
file => input_file,
mode => ada.text_io.in_file,
name => to_string(input_file_name)
);
my_lexer := (input => input_file'access, index => 0);
next_token := my_lexer.get_next_token;
ada.text_io.put_line(to_string(next_token.text));
end main;
似乎有点令人费解,但我相信这是一种确保 input_file
的访问与过程一样长的方法。
我要做的是隐藏所有这些细节并创建一个抽象:
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;
显然,有趣的部分留作 reader 的练习。
通常当你运行遇到这样的问题时,有两种解决方案
- 定义一个新类型,它是对
limited
类型的访问,并在您的记录中使用它,或者 - 打字
limited
。这可能(在我看来)是更清洁的解决方案,因为您不必处理分配、释放和其他事情。 (就个人而言,我尽量避免访问类型)。当然,限制它会阻止你分配它,但在词法分析器的情况下这可能不是主要问题。