mirror of
https://github.com/AdaCore/langkit.git
synced 2026-02-12 12:28:12 -08:00
1033 lines
32 KiB
Ada
1033 lines
32 KiB
Ada
with Ada.Containers.Vectors;
|
|
with Ada.Directories;
|
|
with Ada.Exceptions; use Ada.Exceptions;
|
|
with Ada.Text_IO; use Ada.Text_IO;
|
|
|
|
with Langkit_Support.Errors; use Langkit_Support.Errors;
|
|
with Langkit_Support.Generic_API; use Langkit_Support.Generic_API;
|
|
with Langkit_Support.Generic_API.Analysis;
|
|
use Langkit_Support.Generic_API.Analysis;
|
|
with Langkit_Support.Generic_API.Introspection;
|
|
use Langkit_Support.Generic_API.Introspection;
|
|
with Langkit_Support.Names; use Langkit_Support.Names;
|
|
with Langkit_Support.Slocs; use Langkit_Support.Slocs;
|
|
with Langkit_Support.Text; use Langkit_Support.Text;
|
|
|
|
with Libfoolang.Analysis;
|
|
with Libfoolang.Common;
|
|
with Libfoolang.Generic_API; use Libfoolang.Generic_API;
|
|
with Libfoolang.Generic_API.Introspection;
|
|
use Libfoolang.Generic_API.Introspection;
|
|
|
|
procedure Analysis is
|
|
use type Libfoolang.Analysis.Analysis_Context;
|
|
use type Libfoolang.Analysis.Analysis_Unit;
|
|
use type Libfoolang.Analysis.Foo_Node;
|
|
|
|
Id : Language_Id renames Libfoolang.Generic_API.Foo_Lang_Id;
|
|
|
|
Ctx : Lk_Context;
|
|
U : Lk_Unit;
|
|
N : Lk_Node;
|
|
|
|
Comment_Tok : Lk_Token;
|
|
|
|
procedure Reparse_Original;
|
|
-- Reparse example.txt from the on-disk file
|
|
|
|
procedure Reparse_Modified;
|
|
-- Reparse example.txt from a modified buffer
|
|
|
|
----------------------
|
|
-- Reparse_Original --
|
|
----------------------
|
|
|
|
procedure Reparse_Original is
|
|
begin
|
|
U := Ctx.Get_From_File ("example.txt", Reparse => True);
|
|
end Reparse_Original;
|
|
|
|
----------------------
|
|
-- Reparse_Modified --
|
|
----------------------
|
|
|
|
procedure Reparse_Modified is
|
|
begin
|
|
U := Ctx.Get_From_Buffer
|
|
(Filename => "example.txt",
|
|
Buffer =>
|
|
"example foo" & ASCII.LF
|
|
& "var a = 0;" & ASCII.LF
|
|
& "var b = 1 + b;" & ASCII.LF
|
|
& "# Modified comment" & ASCII.LF);
|
|
end Reparse_Modified;
|
|
|
|
begin
|
|
New_Line;
|
|
|
|
Put_Line
|
|
("Language name: "
|
|
& Image (Format_Name (Language_Name (Id), Camel_With_Underscores)));
|
|
New_Line;
|
|
|
|
Put_Line ("Grammar rules:");
|
|
for I in 1 .. Last_Grammar_Rule (Id) loop
|
|
declare
|
|
Rule : constant Grammar_Rule_Ref := From_Index (Id, I);
|
|
Doc : constant Text_Type := Grammar_Rule_Doc (Rule);
|
|
begin
|
|
Put (" " & Image (Format_Name (Grammar_Rule_Name (Rule),
|
|
Camel_With_Underscores)));
|
|
if Rule = Default_Grammar_Rule (Id) then
|
|
Put (" (default)");
|
|
end if;
|
|
if Is_Public (Rule) then
|
|
Put (" (public)");
|
|
end if;
|
|
|
|
Put_Line
|
|
(": "
|
|
& Image (Format_Name (Node_Type_Name (Grammar_Rule_Type (Rule)),
|
|
Camel_With_Underscores)));
|
|
if Doc /= "" then
|
|
Put_Line (" doc: " & Image (Doc, With_Quotes => True));
|
|
end if;
|
|
end;
|
|
end loop;
|
|
New_Line;
|
|
|
|
Put_Line ("Token kinds:");
|
|
for I in 1 .. Last_Token_Kind (Id) loop
|
|
declare
|
|
Kind : constant Token_Kind_Ref := From_Index (Id, I);
|
|
Family : constant Token_Family_Ref := Token_Family (Kind);
|
|
Kind_Name : constant Text_Type :=
|
|
Format_Name (Token_Kind_Name (Kind), Camel_With_Underscores);
|
|
Family_Name : constant Text_Type :=
|
|
Format_Name (Token_Family_Name (Family), Camel_With_Underscores);
|
|
begin
|
|
Put (" " & Image (Kind_Name) & " (" & Image (Family_Name));
|
|
if Is_Comment (Kind) then
|
|
Put (", is_comment");
|
|
end if;
|
|
Put_Line (")");
|
|
end;
|
|
end loop;
|
|
New_Line;
|
|
|
|
Put_Line ("Token families:");
|
|
for I in 1 .. Last_Token_Family (Id) loop
|
|
declare
|
|
Family : constant Token_Family_Ref := From_Index (Id, I);
|
|
begin
|
|
Put_Line (" " & Image (Format_Name (Token_Family_Name (Family),
|
|
Camel_With_Underscores)));
|
|
end;
|
|
end loop;
|
|
New_Line;
|
|
|
|
Put_Line ("Use of null token kind:");
|
|
declare
|
|
Dummy : Name_Type;
|
|
begin
|
|
Dummy := Token_Kind_Name (No_Token_Kind_Ref);
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Use of null context:");
|
|
declare
|
|
Dummy : Boolean;
|
|
begin
|
|
Dummy := Ctx.Has_Unit ("foo.txt");
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Use of null unit:");
|
|
Put ("No_Lk_Unit.Root: ");
|
|
begin
|
|
-- Disable warnings about reading U before it is initialized: we have
|
|
-- special provision to handle that case in the API, and we want to
|
|
-- check that the behavior is deterministic here.
|
|
pragma Warnings (Off);
|
|
N := U.Root;
|
|
pragma Warnings (On);
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
Put ("No_Lk_Unit.Charset: ");
|
|
begin
|
|
Put_Line (No_Lk_Unit.Charset);
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Use of null node:");
|
|
begin
|
|
N := N.Parent;
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Has_With_Trivia on null context:");
|
|
declare
|
|
Dummy : Boolean;
|
|
begin
|
|
Dummy := No_Lk_Context.Has_With_Trivia;
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Ctx := Create_Context (Id);
|
|
Put_Line
|
|
("Create_Context (With_Trivia => <>): Has_With_Trivia = "
|
|
& Ctx.Has_With_Trivia'Image);
|
|
|
|
Ctx := Create_Context (Id, With_Trivia => False);
|
|
Put_Line
|
|
("Create_Context (With_Trivia => False): Has_With_Trivia = "
|
|
& Ctx.Has_With_Trivia'Image);
|
|
|
|
Ctx := Create_Context (Id, With_Trivia => True);
|
|
Put_Line
|
|
("Create_Context (With_Trivia => True): Has_With_Trivia = "
|
|
& Ctx.Has_With_Trivia'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("Parsing example.txt...");
|
|
U := Ctx.Get_From_File ("example.txt");
|
|
N := U.Root;
|
|
|
|
if U.Context /= Ctx then
|
|
raise Program_Error with "wrong unit->context backlink";
|
|
elsif N.Unit /= U then
|
|
raise Program_Error with "wrong node->unit backlink";
|
|
end if;
|
|
|
|
declare
|
|
Has_1 : constant Boolean := Ctx.Has_Unit ("example.txt");
|
|
Has_2 : constant Boolean := Ctx.Has_Unit ("foo.txt");
|
|
begin
|
|
Put_Line ("Has example.txt? -> " & Has_1'Image);
|
|
Put_Line ("Has foo.txt? -> " & Has_2'Image);
|
|
end;
|
|
|
|
Put_Line ("Line 2:");
|
|
Put_Line (" " & Image (U.Get_Line (2), With_Quotes => True));
|
|
|
|
Put_Line ("Traversing its parsing tree...");
|
|
declare
|
|
function Visit (N : Lk_Node) return Visit_Status;
|
|
|
|
-----------
|
|
-- Visit --
|
|
-----------
|
|
|
|
function Visit (N : Lk_Node) return Visit_Status is
|
|
begin
|
|
Put_Line (N.Image);
|
|
return Into;
|
|
end Visit;
|
|
|
|
begin
|
|
N.Traverse (Visit'Access);
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Unit.Text -> " & Image (U.Text, With_Quotes => True));
|
|
Put ("No_Lk_Unit.Text -> ");
|
|
declare
|
|
Dummy : Integer;
|
|
begin
|
|
Dummy := No_Lk_Node.Text'Length;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing Get_From_Buffer");
|
|
declare
|
|
U : Lk_Unit;
|
|
begin
|
|
Put_Line ("Base:");
|
|
U := Ctx.Get_From_Buffer ("buffer.txt", "var foo = 1;");
|
|
U.Root.Print;
|
|
|
|
Put_Line ("Reparsed:");
|
|
U := Ctx.Get_From_Buffer ("buffer.txt", "example foo");
|
|
U.Root.Print;
|
|
|
|
Put_Line ("Custom rule:");
|
|
U := Ctx.Get_From_Buffer
|
|
(Filename => "buffer_custom.txt",
|
|
Buffer => "my_id",
|
|
Rule => From_Index (Id, Last_Grammar_Rule (Id)));
|
|
U.Root.Print;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing Reparse_From_File");
|
|
declare
|
|
U : Lk_Unit;
|
|
begin
|
|
Put_Line ("Base:");
|
|
U := Ctx.Get_From_Buffer ("example.txt", "var foo = 1;");
|
|
U.Root.Print;
|
|
|
|
Put_Line ("Reparsed:");
|
|
U.Reparse_From_File;
|
|
U.Root.Print;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing Reparse_From_Buffer");
|
|
declare
|
|
U : Lk_Unit;
|
|
begin
|
|
Put_Line ("Base:");
|
|
U := Ctx.Get_From_Buffer ("example.txt", "var foo = 1;");
|
|
U.Root.Print;
|
|
|
|
Put_Line ("Reparsed:");
|
|
U.Reparse_From_Buffer ("var bar = 2;");
|
|
U.Root.Print;
|
|
end;
|
|
New_Line;
|
|
|
|
declare
|
|
Units : constant array (Positive range <>) of Lk_Unit :=
|
|
(Ctx.Get_From_Buffer
|
|
("without_error.txt", "var foo = 1;", Charset => "utf-8"),
|
|
Ctx.Get_From_Buffer
|
|
("with_error.txt", "var foo = 1", Charset => "ascii"),
|
|
Ctx.Get_From_File ("nosuchfile.txt"));
|
|
begin
|
|
Put_Line ("Testing diagnostics-related primitives");
|
|
for U of Units loop
|
|
Put_Line (Ada.Directories.Simple_Name (U.Filename) & ":");
|
|
Put_Line (" Charset: " & U.Charset);
|
|
Put_Line (" Has_Diagnostics? " & U.Has_Diagnostics'Image);
|
|
for D of U.Diagnostics loop
|
|
Put_Line (" " & U.Format_GNU_Diagnostic (D));
|
|
end loop;
|
|
end loop;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing Print debug helpers for units:");
|
|
for U of Units loop
|
|
Put_Line (Ada.Directories.Simple_Name (U.Filename) & ":");
|
|
U.Print;
|
|
New_Line;
|
|
end loop;
|
|
end;
|
|
|
|
U.Reparse_From_File;
|
|
N := U.Root;
|
|
Put_Line ("Testing various node operations:");
|
|
Put_Line ("Root.Is_Null -> " & N.Is_Null'Image);
|
|
|
|
N := N.Next_Sibling;
|
|
Put_Line ("Root.Next_Sibling.Image -> " & N.Image);
|
|
Put_Line ("Root.Next_Sibling.Is_Null -> " & N.Is_Null'Image);
|
|
|
|
Put ("No_Lk_Node.Next_Sibling.Is_Null -> ");
|
|
begin
|
|
Put (No_Lk_Node.Next_Sibling.Is_Null'Image);
|
|
New_Line;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
|
|
Put ("No_Lk_Node.Previous_Sibling.Is_Null -> ");
|
|
begin
|
|
Put (No_Lk_Node.Previous_Sibling.Is_Null'Image);
|
|
New_Line;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
|
|
N := U.Root.Child (2);
|
|
Put_Line ("Root.Child (2).Image -> " & N.Image);
|
|
|
|
declare
|
|
Prev : constant Lk_Node := N.Previous_Sibling;
|
|
Equal_1 : constant Boolean := Prev.Next_Sibling = N;
|
|
Equal_2 : constant Boolean := Prev = N;
|
|
begin
|
|
Put_Line ("Root.Child (2).Previous_Sibling.Image -> " & Prev.Image);
|
|
Put_Line
|
|
("[...].Previous_Sibling = [...] -> " & Equal_1'Image);
|
|
Put_Line
|
|
("[...].Previous_Sibling = [...].Previous_Sibling.Next_Sibling -> "
|
|
& Equal_2'Image);
|
|
end;
|
|
Put_Line ("Root.Children:");
|
|
for C of U.Root.Children loop
|
|
Put_Line (" -> " & C.Image);
|
|
end loop;
|
|
New_Line;
|
|
|
|
N := U.Root.Child (2).Child (1);
|
|
for B in Boolean'Range loop
|
|
Put_Line ("Parents (" & Image (N) & ", With_Self => " & B'Image & "):");
|
|
for P of N.Parents (With_Self => B) loop
|
|
Put_Line (" " & Image (P));
|
|
end loop;
|
|
end loop;
|
|
|
|
Put ("Parents (No_Lk_Node) = ");
|
|
declare
|
|
Length : Natural;
|
|
begin
|
|
Length := No_Lk_Node.Parents'Length;
|
|
Put_Line (Length'Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Is_Ghost (" & Image (U.Root) & ") = " & U.Root.Is_Ghost'Image);
|
|
Put_Line ("Is_Ghost (" & Image (N) & ") = " & N.Is_Ghost'Image);
|
|
Put ("Is_Ghost (No_Lk_Node) = ");
|
|
declare
|
|
B : Boolean;
|
|
begin
|
|
B := No_Lk_Node.Is_Ghost;
|
|
Put_Line (B'Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Root.Text -> " & Image (U.Root.Text, With_Quotes => True));
|
|
Put ("No_Lk_Node.Text -> ");
|
|
declare
|
|
Dummy : Integer;
|
|
begin
|
|
Dummy := No_Lk_Node.Text'Length;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Root.Sloc_Range -> " & Image (U.Root.Sloc_Range));
|
|
Put ("No_Lk_Node.Sloc_Range -> ");
|
|
declare
|
|
Dummy : Source_Location_Range;
|
|
begin
|
|
Dummy := No_Lk_Node.Sloc_Range;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
N := U.Root.Child (1);
|
|
Put_Line ("First_Child.Compare ((1, 1)) -> " & N.Compare ((1, 1))'Image);
|
|
Put_Line ("First_Child.Compare ((4, 1)) -> " & N.Compare ((4, 1))'Image);
|
|
Put ("No_Lk_Node.Compare ((1, 1)) -> ");
|
|
begin
|
|
Put (No_Lk_Node.Compare ((1, 1))'Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line
|
|
("No_Lk_Node.Lookup (1, 1) -> " & Image (No_Lk_Node.Lookup ((1, 1))));
|
|
Put_Line ("Root.Lookup (2, 7) -> " & Image (U.Root.Lookup ((2, 7))));
|
|
New_Line;
|
|
|
|
Put_Line ("Root.Is_Incomplete -> " & U.Root.Is_Incomplete'Image);
|
|
Put ("No_Lk_Node.Is_Incomplete -> ");
|
|
declare
|
|
Dummy : Boolean;
|
|
begin
|
|
Dummy := No_Lk_Node.Is_Incomplete;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Root.Print (without slocs)");
|
|
U.Root.Print (Show_Slocs => False, Line_Prefix => "... ");
|
|
Put_Line ("Root.Print (with slocs)");
|
|
U.Root.Print (Show_Slocs => True, Line_Prefix => "... ");
|
|
Put ("No_Lk_Node.Print -> ");
|
|
begin
|
|
No_Lk_Node.Print;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Check the equality operator for nodes");
|
|
declare
|
|
-- To check that the expected equality operator is called (i.e. the
|
|
-- Langkit defined one instead of the builtin one), create a stale node
|
|
-- reference and make the vector call it: we expect a precondition
|
|
-- failure, as the equality operator is supposed to raise an error when
|
|
-- called on stale nodes.
|
|
|
|
package Node_Vectors is new Ada.Containers.Vectors (Positive, Lk_Node);
|
|
V : Node_Vectors.Vector;
|
|
begin
|
|
V.Append (U.Root);
|
|
Reparse_Modified;
|
|
declare
|
|
Dummy : Boolean;
|
|
begin
|
|
Dummy := V.Contains (U.Root);
|
|
raise Program_Error with "Stale_Reference_Error expected";
|
|
exception
|
|
when Exc : Stale_Reference_Error =>
|
|
Put_Line ("Got a Stale_Reference_Error exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
Reparse_Original;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing various token operations:");
|
|
Put_Line ("No_Lk_Token.Is_Null -> " & No_Lk_Token.Is_Null'Image);
|
|
Put_Line ("First_Token.Is_Null -> " & U.First_Token.Is_Null'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("Checking the Token->Unit backlink...");
|
|
if U.First_Token.Unit /= U then
|
|
raise Program_Error with "wrong token->unit backlink";
|
|
end if;
|
|
Put ("No_Lk_Token.Unit -> ");
|
|
begin
|
|
if No_Lk_Token.Unit /= U then
|
|
raise Program_Error;
|
|
end if;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Token_Count ->" & U.Token_Count'Image);
|
|
Put_Line ("Trivia_Count ->" & U.Trivia_Count'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("First_Token.Kind -> "
|
|
& Image (Format_Name (Token_Kind_Name (U.First_Token.Kind),
|
|
Camel_With_Underscores)));
|
|
Put_Line ("Last_Token.Kind -> "
|
|
& Image (Format_Name (Token_Kind_Name (U.Last_Token.Kind),
|
|
Camel_With_Underscores)));
|
|
Put ("No_Lk_Token.Kind -> ");
|
|
declare
|
|
Dummy : Token_Kind_Ref;
|
|
begin
|
|
Dummy := No_Lk_Token.Kind;
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Comment_Tok := U.Last_Token.Previous.Previous;
|
|
|
|
Put_Line ("No_Lk_Token.Image -> " & No_Lk_Token.Image);
|
|
Put_Line ("First_Token.Image -> " & U.First_Token.Image);
|
|
Put_Line ("Last_Token.Image -> " & U.Last_Token.Image);
|
|
Put_Line ("Comment_Tok.Image -> " & Comment_Tok.Image);
|
|
Put_Line ("Last_Token.Previous.Image -> " & U.Last_Token.Previous.Image);
|
|
New_Line;
|
|
|
|
Put_Line ("First_Token.Text -> "
|
|
& Image (U.First_Token.Text, With_Quotes => True));
|
|
Put_Line ("Last_Token.Text -> "
|
|
& Image (U.Last_Token.Text, With_Quotes => True));
|
|
Put ("No_Lk_Token.Text -> ");
|
|
begin
|
|
Put_Line (Image (No_Lk_Token.Text, With_Quotes => True));
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("No_Lk_Token.Next -> " & No_Lk_Token.Next.Image);
|
|
Put_Line ("First_Token.Next -> " & U.First_Token.Next.Image);
|
|
Put_Line ("Last_Token.Next -> " & U.Last_Token.Next.Image);
|
|
New_Line;
|
|
|
|
Put_Line ("No_Lk_Token.Previous -> " & No_Lk_Token.Previous.Image);
|
|
Put_Line ("First_Token.Previous -> " & U.First_Token.Previous.Image);
|
|
Put_Line ("Last_Token.Previous -> " & U.Last_Token.Previous.Image);
|
|
New_Line;
|
|
|
|
Put_Line ("No_Token.Is_Trivia -> " & No_Lk_Token.Is_Trivia'Image);
|
|
Put_Line ("First_Token.Is_Trivia -> " & U.First_Token.Is_Trivia'Image);
|
|
Put_Line ("Last_Token.Is_Trivia -> " & U.Last_Token.Is_Trivia'Image);
|
|
Put_Line ("Last_Token.Previous.Is_Trivia -> "
|
|
& U.Last_Token.Previous.Is_Trivia'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("First_Token.Index ->" & U.First_Token.Index'Image);
|
|
Put_Line ("Last_Token.Index ->" & U.Last_Token.Index'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("No_Token.Is_Comment -> " & No_Lk_Token.Is_Comment'Image);
|
|
Put_Line ("First_Token.Is_Comment -> " & U.First_Token.Is_Comment'Image);
|
|
Put_Line ("Last_Token.Is_Comment -> " & U.Last_Token.Is_Comment'Image);
|
|
Put_Line ("Comment_Tok.Is_Comment -> " & Comment_Tok.Is_Comment'Image);
|
|
New_Line;
|
|
|
|
Put_Line ("Lookup_Token ((1, 1)).Image -> "
|
|
& U.Lookup_Token ((1, 1)).Image);
|
|
Put_Line ("Lookup_Token ((2, 1)).Image -> "
|
|
& U.Lookup_Token ((2, 1)).Image);
|
|
Put ("No_Lk_Unit.Lookup_Token ((1, 1)) -> ");
|
|
begin
|
|
Put_Line (No_Lk_Unit.Lookup_Token ((1, 1)).Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing comparison operators for various cases:");
|
|
declare
|
|
FT : constant Lk_Token := U.First_Token;
|
|
LT : constant Lk_Token := U.Last_Token;
|
|
|
|
U2 : constant Lk_Unit := Ctx.Get_From_File ("example2.txt");
|
|
|
|
procedure Check (Label : String; Left, Right : Lk_Token);
|
|
|
|
-----------
|
|
-- Check --
|
|
-----------
|
|
|
|
procedure Check (Label : String; Left, Right : Lk_Token) is
|
|
Result : Boolean;
|
|
begin
|
|
Put (Label & " -> ");
|
|
Result := Left < Right;
|
|
Put_Line (Result'Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
when Exc : Stale_Reference_Error =>
|
|
Put_Line ("Got a Stale_Reference_Error exception: "
|
|
& Exception_Message (Exc));
|
|
end Check;
|
|
begin
|
|
Check ("First_Token < Last_Token:", FT, LT);
|
|
Check ("First_Token < No_Lk_Token:", FT, No_Lk_Token);
|
|
Check ("No_Lk_Token < Last_Token:", No_Lk_Token, LT);
|
|
Check ("First_Token < Other_Unit", FT, U2.Last_Token);
|
|
|
|
Reparse_Modified;
|
|
Check ("First_Token < Stale", U.First_Token, LT);
|
|
Check ("Stale < Last_Token", FT, U.Last_Token);
|
|
Reparse_Original;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing consistency of all comparison operators:");
|
|
declare
|
|
type Results_Array is array (1 .. 4) of Boolean;
|
|
procedure Check (Label : String; L, R : Lk_Token);
|
|
|
|
-----------
|
|
-- Check --
|
|
-----------
|
|
|
|
procedure Check (Label : String; L, R : Lk_Token) is
|
|
begin
|
|
Put (Label);
|
|
for B of Results_Array'(L < R, L <= R, L > R, L >= R) loop
|
|
Put (" | ");
|
|
Put (if B then 'T' else 'F');
|
|
end loop;
|
|
New_Line;
|
|
end Check;
|
|
|
|
T1 : constant Lk_Token := U.First_Token;
|
|
T2 : constant Lk_Token := U.Last_Token;
|
|
begin
|
|
Put_Line (" | < | <= | > | >=");
|
|
Check ("T1 OP T1", T1, T1);
|
|
Check ("T1 OP T2", T1, T2);
|
|
Check ("T2 OP T1", T2, T1);
|
|
Check ("T2 OP T2", T2, T2);
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing text range for various cases:");
|
|
declare
|
|
FT : constant Lk_Token := U.First_Token;
|
|
LT : constant Lk_Token := U.Last_Token;
|
|
|
|
U2 : constant Lk_Unit := Ctx.Get_From_File ("example2.txt");
|
|
|
|
procedure Check (Label : String; Left, Right : Lk_Token);
|
|
|
|
-----------
|
|
-- Check --
|
|
-----------
|
|
|
|
procedure Check (Label : String; Left, Right : Lk_Token) is
|
|
begin
|
|
Put (Label & " -> ");
|
|
Put_Line (Image (Text (Left, Right), With_Quotes => True));
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
when Exc : Stale_Reference_Error =>
|
|
Put_Line ("Got a Stale_Reference_Error exception: "
|
|
& Exception_Message (Exc));
|
|
end Check;
|
|
begin
|
|
Check ("First_Token .. Last_Token:", FT, LT);
|
|
Check ("First_Token .. No_Lk_Token:", FT, No_Lk_Token);
|
|
Check ("No_Lk_Token .. Last_Token:", No_Lk_Token, LT);
|
|
Check ("First_Token .. Other_Unit", FT, U2.Last_Token);
|
|
|
|
Reparse_Modified;
|
|
Check ("First_Token .. Stale", U.First_Token, LT);
|
|
Check ("Stale .. Last_Token", FT, U.Last_Token);
|
|
Reparse_Original;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Testing token equivalence for various cases:");
|
|
declare
|
|
-- Create a new context to ensure that cross-context token comparison
|
|
-- works as expected.
|
|
|
|
U2 : constant Lk_Unit :=
|
|
Create_Context (Id).Get_From_File ("example2.txt");
|
|
|
|
U_Example_Tok : constant Lk_Token := U.First_Token;
|
|
U_Var_Tok : constant Lk_Token := U.First_Token.Next.Next.Next.Next;
|
|
U_Id_A_Tok : constant Lk_Token := U_Var_Tok.Next.Next;
|
|
U_Equal_Tok : constant Lk_Token := U_Id_A_Tok.Next.Next;
|
|
U_Lit_0_Tok : constant Lk_Token := U_Equal_Tok.Next.Next;
|
|
|
|
U2_Var_Tok : constant Lk_Token := U2.First_Token;
|
|
U2_Id_C_Tok : constant Lk_Token := U2_Var_Tok.Next.Next;
|
|
U2_Equal_Tok : constant Lk_Token := U2_Id_C_Tok.Next.Next;
|
|
U2_Lit_2_Tok : constant Lk_Token := U2_Equal_Tok.Next.Next;
|
|
U2_Id_A_Tok : constant Lk_Token :=
|
|
U2.Root.Child (5).Token_Start.Next.Next;
|
|
U2_Lit_0_Tok : constant Lk_Token := U2_Id_A_Tok.Next.Next.Next.Next;
|
|
|
|
procedure Check (Left, Right : Lk_Token);
|
|
|
|
-----------
|
|
-- Check --
|
|
-----------
|
|
|
|
procedure Check (Left, Right : Lk_Token) is
|
|
begin
|
|
Put (" ");
|
|
Put ("Is_Equivalent (" & Image (Left) & ", " & Image (Right)
|
|
& ") = ");
|
|
Put_Line (Left.Is_Equivalent (Right)'Image);
|
|
exception
|
|
when Exc : Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
when Exc : Stale_Reference_Error =>
|
|
Put_Line ("Got a Stale_Reference_Error exception: "
|
|
& Exception_Message (Exc));
|
|
end Check;
|
|
begin
|
|
Put_Line (" Null token references...");
|
|
Check (No_Lk_Token, U_Example_Tok);
|
|
Check (U_Example_Tok, No_Lk_Token);
|
|
New_Line;
|
|
|
|
Put_Line (" Different kinds...");
|
|
Check (U_Example_Tok, U_Var_Tok);
|
|
Check (U_Equal_Tok, U_Var_Tok);
|
|
New_Line;
|
|
|
|
Put_Line (" Same kind on literal-matched tokens...");
|
|
Check (U_Var_Tok, U2_Var_Tok);
|
|
Check (U_Equal_Tok, U2_Equal_Tok);
|
|
New_Line;
|
|
|
|
Put_Line (" Same kind on symbolized tokens...");
|
|
Check (U_Id_A_Tok, U2_Id_C_Tok);
|
|
Check (U_Id_A_Tok, U2_Id_A_Tok);
|
|
New_Line;
|
|
|
|
Put_Line (" Same kind on pattern-matched tokens...");
|
|
Check (U_Lit_0_Tok, U2_Lit_2_Tok);
|
|
Check (U_Lit_0_Tok, U2_Lit_0_Tok);
|
|
New_Line;
|
|
|
|
Put_Line (" Stale references...");
|
|
Reparse_Modified;
|
|
Check (U_Example_Tok, U2_Var_Tok);
|
|
Check (U2_Var_Tok, U_Example_Tok);
|
|
Reparse_Original;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Use of stale node reference:");
|
|
Reparse_Modified;
|
|
begin
|
|
Put_Line ("--> " & N.Image);
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Stale_Reference_Error =>
|
|
Put_Line ("Got a Stale_Reference_Error exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
Reparse_Original;
|
|
New_Line;
|
|
|
|
Put_Line ("Check generic/specific context type converters");
|
|
declare
|
|
Gen_Ctx : Lk_Context := Create_Context (Id);
|
|
Spe_Ctx : Libfoolang.Analysis.Analysis_Context :=
|
|
From_Generic_Context (Gen_Ctx);
|
|
|
|
Dummy_Unit : Libfoolang.Analysis.Analysis_Unit;
|
|
begin
|
|
-- Create an analysis unit while the context can only be referenced
|
|
-- through language-specific types.
|
|
|
|
Gen_Ctx := No_Lk_Context;
|
|
Dummy_Unit := Spe_Ctx.Get_From_Buffer
|
|
(Filename => "foo.txt", Buffer => "example bar");
|
|
Dummy_Unit := Libfoolang.Analysis.No_Analysis_Unit;
|
|
|
|
-- Now switch back to the generic type and make sure the context is
|
|
-- functional.
|
|
|
|
Gen_Ctx := To_Generic_Context (Spe_Ctx);
|
|
Spe_Ctx := Libfoolang.Analysis.No_Analysis_Context;
|
|
Put_Line (Gen_Ctx.Get_From_File ("foo.txt").Root.Image);
|
|
|
|
-- Check conversions for null contexts
|
|
|
|
Gen_Ctx := To_Generic_Context (Libfoolang.Analysis.No_Analysis_Context);
|
|
Spe_Ctx := From_Generic_Context (No_Lk_Context);
|
|
if Gen_Ctx /= No_Lk_Context then
|
|
raise Program_Error;
|
|
elsif Spe_Ctx /= Libfoolang.Analysis.No_Analysis_Context then
|
|
raise Program_Error;
|
|
end if;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Check generic/specific unit type converters");
|
|
declare
|
|
Gen_Ctx : Lk_Context := Create_Context (Id);
|
|
Gen_Unit : Lk_Unit := Gen_Ctx.Get_From_File ("example.txt");
|
|
Spe_Unit : Libfoolang.Analysis.Analysis_Unit :=
|
|
From_Generic_Unit (Gen_Unit);
|
|
begin
|
|
-- Create an analysis unit while the context can only be referenced
|
|
-- through language-specific types.
|
|
|
|
Gen_Unit := No_Lk_Unit;
|
|
Gen_Ctx := No_Lk_Context;
|
|
|
|
-- At this point, the context/units, created through public APIs, are
|
|
-- live only through the language-specific unit type in Spe_Unit. Now
|
|
-- switch back to the generic type and make sure both are functional.
|
|
|
|
Gen_Unit := To_Generic_Unit (Spe_Unit);
|
|
Gen_Ctx := Gen_Unit.Context;
|
|
Put_Line (Gen_Ctx.Get_From_File ("example.txt").Root.Image);
|
|
|
|
-- Check conversions for null units
|
|
|
|
Gen_Unit := To_Generic_Unit (Libfoolang.Analysis.No_Analysis_Unit);
|
|
Spe_Unit := From_Generic_Unit (No_Lk_Unit);
|
|
if Gen_Unit /= No_Lk_Unit then
|
|
raise Program_Error;
|
|
elsif Spe_Unit /= Libfoolang.Analysis.No_Analysis_Unit then
|
|
raise Program_Error;
|
|
end if;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Check generic/specific node type converters");
|
|
declare
|
|
Gen_Ctx : constant Lk_Context := Create_Context (Id);
|
|
Gen_Unit : Lk_Unit := Gen_Ctx.Get_From_File ("example.txt");
|
|
Gen_Node : Lk_Node := Gen_Unit.Root;
|
|
Spe_Node : Libfoolang.Analysis.Foo_Node :=
|
|
From_Generic_Node (Gen_Node);
|
|
begin
|
|
Put_Line ("Root from specific: " & Spe_Node.Image);
|
|
Gen_Node := To_Generic_Node (Spe_Node);
|
|
Gen_Unit := Gen_Node.Unit;
|
|
Put_Line ("Root from generic: " & Gen_Unit.Root.Image);
|
|
|
|
-- Check conversions for null nodes
|
|
|
|
Gen_Node := To_Generic_Node (Libfoolang.Analysis.No_Foo_Node);
|
|
Spe_Node := From_Generic_Node (No_Lk_Node);
|
|
if Gen_Node /= No_Lk_Node then
|
|
raise Program_Error;
|
|
elsif Spe_Node /= Libfoolang.Analysis.No_Foo_Node then
|
|
raise Program_Error;
|
|
end if;
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Check generic/specific grammar rule converters");
|
|
declare
|
|
use Libfoolang.Common;
|
|
|
|
procedure Check (Rule : Grammar_Rule);
|
|
-- Check the specific/generic conversion back and forth for Rule
|
|
|
|
-----------
|
|
-- Check --
|
|
-----------
|
|
|
|
procedure Check (Rule : Grammar_Rule) is
|
|
R : constant Grammar_Rule_Ref := To_Generic_Grammar_Rule (Rule);
|
|
begin
|
|
Put_Line
|
|
(Rule'Image & " -> "
|
|
& Image (Format_Name (Grammar_Rule_Name (R),
|
|
Camel_With_Underscores)));
|
|
if From_Generic_Grammar_Rule (R) /= Rule then
|
|
raise Program_Error;
|
|
end if;
|
|
end Check;
|
|
|
|
begin
|
|
for Rule in Grammar_Rule loop
|
|
Check (Rule);
|
|
end loop;
|
|
end;
|
|
|
|
Put ("Check error case... ");
|
|
declare
|
|
use Libfoolang.Common;
|
|
|
|
Dummy : Grammar_Rule;
|
|
begin
|
|
Dummy := From_Generic_Grammar_Rule (No_Grammar_Rule_Ref);
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Langkit_Support.Errors.Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Check that equality takes metadata into account");
|
|
declare
|
|
N2 : Lk_Node;
|
|
begin
|
|
U := Ctx.Get_From_File ("example.txt");
|
|
N := U.Root.Child (1);
|
|
|
|
N2 := As_Node
|
|
(Eval_Member
|
|
(From_Node (Id, N),
|
|
Member_Refs.Example_P_With_Md,
|
|
(From_Bool (Id, False), From_Bool (Id, False))));
|
|
|
|
Put_Line ("N = N2 (same metadata): "
|
|
& Boolean'Image (N = N2));
|
|
|
|
N2 := As_Node
|
|
(Eval_Member
|
|
(From_Node (Id, N),
|
|
Member_Refs.Example_P_With_Md,
|
|
(From_Bool (Id, False), From_Bool (Id, True))));
|
|
|
|
Put_Line ("N = N2 (/= metadata, field not used in eq): "
|
|
& Boolean'Image (N = N2));
|
|
|
|
N2 := As_Node
|
|
(Eval_Member
|
|
(From_Node (Id, N),
|
|
Member_Refs.Example_P_With_Md,
|
|
(From_Bool (Id, True), From_Bool (Id, False))));
|
|
|
|
Put_Line ("N = N2 (/= metadata, field used in eq): "
|
|
& Boolean'Image (N = N2));
|
|
end;
|
|
New_Line;
|
|
|
|
Put_Line ("Root.Children_And_Trivia:");
|
|
for C of U.Root.Children_And_Trivia loop
|
|
if C.Is_Node then
|
|
Put_Line (" Node: " & C.Node.Image);
|
|
else
|
|
Put_Line (" Token: " & C.Token.Image);
|
|
end if;
|
|
end loop;
|
|
|
|
Put ("No_Lk_Node.Children_And_Trivia: ");
|
|
declare
|
|
Dummy : Node_Or_Token_Sequence;
|
|
begin
|
|
Dummy := No_Lk_Node.Children_And_Trivia;
|
|
raise Program_Error;
|
|
exception
|
|
when Exc : Langkit_Support.Errors.Precondition_Failure =>
|
|
Put_Line ("Got a Precondition_Failure exception: "
|
|
& Exception_Message (Exc));
|
|
end;
|
|
|
|
end Analysis;
|