From 192172cfc44220975b34295d38c5213b08de5191 Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Thu, 10 Dec 2020 23:22:19 +1100 Subject: Some unit tests for Packrat.Parsers --- test/packrat-parsers-debug.adb | 122 +++++++ test/packrat-parsers-debug.ads | 76 +++++ test/rat_tests-parsers.adb | 736 +++++++++++++++++++++++++++++++++++++++++ test/rat_tests-parsers.ads | 85 +++++ test/test_main.adb | 21 +- 5 files changed, 1034 insertions(+), 6 deletions(-) create mode 100644 test/packrat-parsers-debug.adb create mode 100644 test/packrat-parsers-debug.ads create mode 100644 test/rat_tests-parsers.adb create mode 100644 test/rat_tests-parsers.ads diff --git a/test/packrat-parsers-debug.adb b/test/packrat-parsers-debug.adb new file mode 100644 index 0000000..744166a --- /dev/null +++ b/test/packrat-parsers-debug.adb @@ -0,0 +1,122 @@ + + +with + + Ada.Characters.Latin_1, + Ada.Strings.Unbounded; + + +package body Packrat.Parsers.Debug is + + + package Latin renames Ada.Characters.Latin_1; + package SU renames Ada.Strings.Unbounded; + + + + + + function Parts + (This : in Combinator_Result) + return Result_Part_Array + is + Arr : Result_Part_Array (1 .. Integer (This.Results.Length)); + Index : Positive := 1; + begin + for R of This.Results loop + Arr (Index) := Result_Part (R); + Index := Index + 1; + end loop; + return Arr; + end Parts; + + + function Curtails + (This : in Combinator_Result) + return Curtail_Map is + begin + return (This.Curtails with null record); + end Curtails; + + + function Status + (This : in Combinator_Result) + return Result_Status is + begin + return This.Status; + end Status; + + + + + + function Finish + (Part : in Result_Part) + return Traits.Tokens.Finish_Type is + begin + return Part.Finish; + end Finish; + + function Value + (Part : in Result_Part) + return Traits.Element_Array is + begin + if Part.Value.Is_Empty then + return Arr : Traits.Element_Array (1 .. 0); + else + return Part.Value.Element; + end if; + end Value; + + function Tokens + (Part : in Result_Part) + return Traits.Tokens.Finished_Token_Array is + begin + if Part.Tokens.Is_Empty then + return Arr : Traits.Tokens.Finished_Token_Array (1 .. 0); + else + return Part.Tokens.Element; + end if; + end Tokens; + + + + + + function Is_Empty + (Curt : in Curtail_Map) + return Boolean is + begin + return Packrat.Parsers.Curtail_Maps.Map (Curt).Is_Empty; + end Is_Empty; + + + + + + function Debug_String + (This : in Combinator_Result) + return String + is + Str : SU.Unbounded_String; + Index : Integer := 1; + begin + for Part of Parts (This) loop + SU.Append (Str, "Part" & Integer'Image (Index) & ":" & Latin.LF); + SU.Append (Str, Latin.HT & "Fin:" & + Traits.Tokens.Finish_Type'Image (Finish (Part)) & Latin.LF); + SU.Append (Str, Latin.HT & "Val:" & Integer'Image (Value (Part)'Length) & Latin.LF); + SU.Append (Str, Latin.HT & "Tok:" & Latin.LF); + for Tok of Tokens (Part) loop + SU.Append (Str, Latin.HT & Latin.HT & Traits.Tokens.Debug_String (Tok) & Latin.LF); + end loop; + Index := Index + 1; + end loop; + SU.Append (Str, Latin.HT & "Status: " & Result_Status'Image (Status (This)) & Latin.LF); + return -Str; + end Debug_String; + + +end Packrat.Parsers.Debug; + + diff --git a/test/packrat-parsers-debug.ads b/test/packrat-parsers-debug.ads new file mode 100644 index 0000000..7fd425b --- /dev/null +++ b/test/packrat-parsers-debug.ads @@ -0,0 +1,76 @@ + + +generic +package Packrat.Parsers.Debug is + + + type Result_Part is private; + type Result_Part_Array is array (Positive range <>) of Result_Part; + + type Curtail_Map is private; + + + + + Empty_Context : constant Parser_Context; + Empty_Fail : constant Combinator_Result; + + + + + function Parts + (This : in Combinator_Result) + return Result_Part_Array; + + function Curtails + (This : in Combinator_Result) + return Curtail_Map; + + function Status + (This : in Combinator_Result) + return Result_Status; + + + + + function Finish + (Part : in Result_Part) + return Traits.Tokens.Finish_Type; + + function Value + (Part : in Result_Part) + return Traits.Element_Array; + + function Tokens + (Part : in Result_Part) + return Traits.Tokens.Finished_Token_Array; + + + + + function Is_Empty + (Curt : in Curtail_Map) + return Boolean; + + + + + function Debug_String + (This : in Combinator_Result) + return String; + + +private + + + type Result_Part is new Combo_Result_Part; + type Curtail_Map is new Curtail_Maps.Map with null record; + + + Empty_Context : constant Parser_Context := Packrat.Parsers.Empty_Context; + Empty_Fail : constant Combinator_Result := Packrat.Parsers.Empty_Fail; + + +end Packrat.Parsers.Debug; + + diff --git a/test/rat_tests-parsers.adb b/test/rat_tests-parsers.adb new file mode 100644 index 0000000..9368d6d --- /dev/null +++ b/test/rat_tests-parsers.adb @@ -0,0 +1,736 @@ + + +with + + Ada.Text_IO, + Packrat.Utilities; + + +package body Rat_Tests.Parsers is + + + use type Packrat.Result_Status; + + + + + + function Alphanum_Switch + (Char : in Character) + return Character is + begin + case Char is + when 'a' .. 'z' => + return Character'Val (48 + (Character'Pos (Char) - 97) mod 10); + when 'A' .. 'Z' => + return Character'Val (48 + (Character'Pos (Char) - 65) mod 10); + when '0' .. '9' => + return Character'Val (49 + (Character'Pos (Char))); + when others => + return Char; + end case; + end Alphanum_Switch; + + + + + + function Count_Check + return Test_Result + is + Input : String := "aaaa12aa"; + Context1, Context2, Context3, Context4 : Pone.Parsers.Parser_Context := + One_Debug.Empty_Context; + function Match_A is new Pone.Parsers.Match ('a'); + function Three_A is new Pone.Parsers.Count (Match_A, 3); + Result1 : Pone.Parsers.Combinator_Result := Three_A (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Three_A (Input, Context2, 3); + Result3 : Pone.Parsers.Combinator_Result := Three_A (Input, Context3, 5); + Result4 : Pone.Parsers.Combinator_Result := Three_A (Input, Context4, 7); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Failure or + One_Debug.Status (Result4) /= Packrat.Needs_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + begin + if Result1_Parts'Length /= 1 or + One_Debug.Parts (Result2)'Length /= 0 or + One_Debug.Parts (Result3)'Length /= 0 or + One_Debug.Parts (Result4)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Value (Result1_Parts (1))'Length /= 3 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Count_Check; + + + function Many_Nomin_Check + return Test_Result + is + Input : String := "abcd123efghi"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Sat_Letter is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Letter); + function Many_Letter is new Pone.Parsers.Many (Sat_Letter, 0); + Result1 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context2, 5); + Result3 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context3, 8); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Optional_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 5 or + Result2_Parts'Length /= 1 or + Result3_Parts'Length /= 6 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 0 or + One_Debug.Finish (Result1_Parts (2)) /= 1 or + One_Debug.Finish (Result1_Parts (3)) /= 2 or + One_Debug.Finish (Result1_Parts (4)) /= 3 or + One_Debug.Finish (Result1_Parts (5)) /= 4 + then + return Fail; + end if; + if One_Debug.Value (Result1_Parts (1))'Length /= 0 or + One_Debug.Value (Result1_Parts (2))'Length /= 1 or + One_Debug.Value (Result1_Parts (3))'Length /= 2 or + One_Debug.Value (Result1_Parts (4))'Length /= 3 or + One_Debug.Value (Result1_Parts (5))'Length /= 4 + then + return Fail; + end if; + if (for some P of Result1_Parts => One_Debug.Tokens (P)'Length /= 0) then + return Fail; + end if; + if One_Debug.Finish (Result2_Parts (1)) /= 4 or + One_Debug.Value (Result2_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result3_Parts (1)) /= 7 or + One_Debug.Finish (Result3_Parts (2)) /= 8 or + One_Debug.Finish (Result3_Parts (3)) /= 9 or + One_Debug.Finish (Result3_Parts (4)) /= 10 or + One_Debug.Finish (Result3_Parts (5)) /= 11 or + One_Debug.Finish (Result3_Parts (6)) /= 12 + then + return Fail; + end if; + if One_Debug.Value (Result3_Parts (1))'Length /= 0 or + One_Debug.Value (Result3_Parts (2))'Length /= 1 or + One_Debug.Value (Result3_Parts (3))'Length /= 2 or + One_Debug.Value (Result3_Parts (4))'Length /= 3 or + One_Debug.Value (Result3_Parts (5))'Length /= 4 or + One_Debug.Value (Result3_Parts (6))'Length /= 5 + then + return Fail; + end if; + if (for some P of Result3_Parts => One_Debug.Tokens (P)'Length /= 0) then + return Fail; + end if; + end; + return Pass; + end Many_Nomin_Check; + + + function Many_Min_Check + return Test_Result + is + Input : String := "abcd123efghi"; + Context1, Context2, Context3, Context4 : Pone.Parsers.Parser_Context := + One_Debug.Empty_Context; + function Sat_Letter is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Letter); + function Many_Letter is new Pone.Parsers.Many (Sat_Letter, 3); + Result1 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context2, 5); + Result3 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context3, 8); + Result4 : Pone.Parsers.Combinator_Result := Many_Letter (Input, Context4, 11); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Optional_More or + One_Debug.Status (Result4) /= Packrat.Needs_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 2 or + One_Debug.Parts (Result2)'Length /= 0 or + Result3_Parts'Length /= 3 or + One_Debug.Parts (Result4)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Finish (Result1_Parts (2)) /= 4 + then + return Fail; + end if; + if One_Debug.Value (Result1_Parts (1))'Length /= 3 or + One_Debug.Value (Result1_Parts (2))'Length /= 4 + then + return Fail; + end if; + if One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result1_Parts (2))'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result3_Parts (1)) /= 10 or + One_Debug.Finish (Result3_Parts (2)) /= 11 or + One_Debug.Finish (Result3_Parts (3)) /= 12 + then + return Fail; + end if; + if One_Debug.Value (Result3_Parts (1))'Length /= 3 or + One_Debug.Value (Result3_Parts (2))'Length /= 4 or + One_Debug.Value (Result3_Parts (3))'Length /= 5 + then + return Fail; + end if; + if One_Debug.Tokens (Result3_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result3_Parts (2))'Length /= 0 or + One_Debug.Tokens (Result3_Parts (3))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Many_Min_Check; + + + function Many_Until_Nomin_Check + return Test_Result + is + Input : String := "abc12de;fghi"; + Context1, Context2, Context3, Context4 : Pone.Parsers.Parser_Context := + One_Debug.Empty_Context; + function Sat_Letter is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Letter); + function Sat_Digit is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Digit); + function Body_Is_Dry is new Pone.Parsers.Many_Until (Sat_Letter, Sat_Digit, 0); + Result1 : Pone.Parsers.Combinator_Result := Body_Is_Dry (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Body_Is_Dry (Input, Context2, 4); + Result3 : Pone.Parsers.Combinator_Result := Body_Is_Dry (Input, Context3, 6); + Result4 : Pone.Parsers.Combinator_Result := Body_Is_Dry (Input, Context4, 9); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Failure or + One_Debug.Status (Result4) /= Packrat.Needs_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + begin + if Result1_Parts'Length /= 1 or + Result2_Parts'Length /= 1 or + One_Debug.Parts (Result3)'Length /= 0 or + One_Debug.Parts (Result4)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Value (Result1_Parts (1))'Length /= 3 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result2_Parts (1)) /= 3 or + One_Debug.Value (Result2_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Many_Until_Nomin_Check; + + + function Many_Until_Min_Check + return Test_Result + is + Input : String := "abcde12fgh"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Sat_Letter is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Letter); + function Sat_Digit is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Digit); + function Your_Way is new Pone.Parsers.Many_Until (Sat_Letter, Sat_Digit, 3); + Result1 : Pone.Parsers.Combinator_Result := Your_Way (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Your_Way (Input, Context2, 4); + Result3 : Pone.Parsers.Combinator_Result := Your_Way (Input, Context3, 8); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Needs_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + begin + if Result1_Parts'Length /= 1 or + One_Debug.Parts (Result2)'Length /= 0 or + One_Debug.Parts (Result3)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 5 or + One_Debug.Value (Result1_Parts (1))'Length /= 5 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Many_Until_Min_Check; + + + function Satisfy_Check + return Test_Result + is + Input : String := "abc123def"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Satisfy_Letter is new Pone.Parsers.Satisfy (Packrat.Utilities.Is_Letter); + Result1 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context1, 2); + Result2 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context2, 6); + Result3 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context3, 10); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Failure + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 1 or + Result2_Parts'Length /= 0 or + Result3_Parts'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 2 or + One_Debug.Value (Result1_Parts (1))'Length /= 1 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Satisfy_Check; + + + function Satisfy_With_Check + return Test_Result + is + Input : String := "abc123def"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Satisfy_Letter is new Pone.Parsers.Satisfy_With + (Packrat.Utilities.Is_Letter, Alphanum_Switch); + Result1 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context1, 2); + Result2 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context2, 6); + Result3 : Pone.Parsers.Combinator_Result := Satisfy_Letter (Input, Context3, 10); + begin + if One_Debug.Status (Result1) /= Packrat.Failure or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Failure + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 0 or + Result2_Parts'Length /= 1 or + Result3_Parts'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result2_Parts (1)) /= 6 or + One_Debug.Value (Result2_Parts (1))'Length /= 1 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Satisfy_With_Check; + + + function Match_Check + return Test_Result + is + Input : String := "aaabbbccc"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Match_B is new Pone.Parsers.Match ('b'); + Result1 : Pone.Parsers.Combinator_Result := Match_B (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Match_B (Input, Context2, 5); + Result3 : Pone.Parsers.Combinator_Result := Match_B (Input, Context3, 200); + begin + if One_Debug.Status (Result1) /= Packrat.Failure or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Failure + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 0 or + Result2_Parts'Length /= 1 or + Result3_Parts'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result2_Parts (1)) /= 5 or + One_Debug.Value (Result2_Parts (1))'Length /= 1 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Match_Check; + + + function Match_With_Check + return Test_Result + is + Input : String := "aaa111b2"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Match_0 is new Pone.Parsers.Match_With ('0', Alphanum_Switch); + Result1 : Pone.Parsers.Combinator_Result := Match_0 (Input, Context1, 3); + Result2 : Pone.Parsers.Combinator_Result := Match_0 (Input, Context2, 4); + Result3 : Pone.Parsers.Combinator_Result := Match_0 (Input, Context3, 7); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Failure + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 1 or + Result2_Parts'Length /= 0 or + Result3_Parts'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Value (Result1_Parts (1))'Length /= 1 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Match_With_Check; + + + function Multimatch_Check + return Test_Result + is + Input : String := "abcdefghi"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Multi is new Pone.Parsers.Multimatch ("def"); + Result1 : Pone.Parsers.Combinator_Result := Multi (Input, Context1, 2); + Result2 : Pone.Parsers.Combinator_Result := Multi (Input, Context2, 4); + Result3 : Pone.Parsers.Combinator_Result := Multi (Input, Context3, 300); + begin + if One_Debug.Status (Result1) /= Packrat.Failure or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Failure + then + return Fail; + end if; + declare + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + begin + if One_Debug.Parts (Result1)'Length /= 0 or + Result2_Parts'Length /= 1 or + One_Debug.Parts (Result3)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result2_Parts (1)) /= 6 or + One_Debug.Value (Result2_Parts (1))'Length /= 3 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Multimatch_Check; + + + function Take_Check + return Test_Result + is + Input : String := "abcdefghi"; + Context1, Context2, Context3, Context4 : Pone.Parsers.Parser_Context := + One_Debug.Empty_Context; + function Take_2 is new Pone.Parsers.Take (2); + function Take_5 is new Pone.Parsers.Take (5); + Result1 : Pone.Parsers.Combinator_Result := Take_2 (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Take_5 (Input, Context2, 3); + Result3 : Pone.Parsers.Combinator_Result := Take_5 (Input, Context3, 7); + Result4 : Pone.Parsers.Combinator_Result := Take_2 (Input, Context4, 100); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Needs_More or + One_Debug.Status (Result4) /= Packrat.Failure + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + begin + if Result1_Parts'Length /= 1 or + Result2_Parts'Length /= 1 or + One_Debug.Parts (Result3)'Length /= 0 or + One_Debug.Parts (Result4)'Length /= 0 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 2 or + One_Debug.Value (Result1_Parts (1))'Length /= 2 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Finish (Result2_Parts (1)) /= 7 or + One_Debug.Value (Result2_Parts (1))'Length /= 5 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Take_Check; + + + function Take_While_Check + return Test_Result + is + Input : String := "abc123def"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Take_On_Me is new Pone.Parsers.Take_While (Packrat.Utilities.Is_Letter); + Result1 : Pone.Parsers.Combinator_Result := Take_On_Me (Input, Context1, 2); + Result2 : Pone.Parsers.Combinator_Result := Take_On_Me (Input, Context2, 4); + Result3 : Pone.Parsers.Combinator_Result := Take_On_Me (Input, Context3, 7); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Optional_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 1 or + One_Debug.Parts (Result2)'Length /= 0 or + Result3_Parts'Length /= 1 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Value (Result1_Parts (1))'Length /= 2 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Finish (Result3_Parts (1)) /= 9 or + One_Debug.Value (Result3_Parts (1))'Length /= 3 or + One_Debug.Tokens (Result3_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Take_While_Check; + + + function Take_Until_Check + return Test_Result + is + Input : String := "abc123def"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Take_Me_On is new Pone.Parsers.Take_Until (Packrat.Utilities.Is_Digit); + Result1 : Pone.Parsers.Combinator_Result := Take_Me_On (Input, Context1, 2); + Result2 : Pone.Parsers.Combinator_Result := Take_Me_On (Input, Context2, 6); + Result3 : Pone.Parsers.Combinator_Result := Take_Me_On (Input, Context3, 8); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Failure or + One_Debug.Status (Result3) /= Packrat.Optional_More + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 1 or + One_Debug.Parts (Result2)'Length /= 0 or + Result3_Parts'Length /= 1 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 3 or + One_Debug.Value (Result1_Parts (1))'Length /= 2 or + One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Finish (Result3_Parts (1)) /= 9 or + One_Debug.Value (Result3_Parts (1))'Length /= 2 or + One_Debug.Tokens (Result3_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Take_Until_Check; + + + function Empty_Check + return Test_Result + is + Input : String := "abcdef"; + Context1, Context2, Context3 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + Result1 : Pone.Parsers.Combinator_Result := Pone.Parsers.Empty (Input, Context1, 1); + Result2 : Pone.Parsers.Combinator_Result := Pone.Parsers.Empty (Input, Context2, 3); + Result3 : Pone.Parsers.Combinator_Result := Pone.Parsers.Empty (Input, Context3, 10); + begin + if One_Debug.Status (Result1) /= Packrat.Success or + One_Debug.Status (Result2) /= Packrat.Success or + One_Debug.Status (Result3) /= Packrat.Success + then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + Result2_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result2); + Result3_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result3); + begin + if Result1_Parts'Length /= 1 or + Result2_Parts'Length /= 1 or + Result3_Parts'Length /= 1 + then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 0 or + One_Debug.Finish (Result2_Parts (1)) /= 2 or + One_Debug.Finish (Result3_Parts (1)) /= 9 + then + return Fail; + end if; + if One_Debug.Value (Result1_Parts (1))'Length /= 0 or + One_Debug.Value (Result2_Parts (1))'Length /= 0 or + One_Debug.Value (Result3_Parts (1))'Length /= 0 + then + return Fail; + end if; + if One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result2_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result3_Parts (1))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Empty_Check; + + + function Not_Empty_Check + return Test_Result + is + Input : String := "aa"; + Context1 : Pone.Parsers.Parser_Context := One_Debug.Empty_Context; + function Match_A is new Pone.Parsers.Match ('a'); + function Many_A is new Pone.Parsers.Many (Match_A, 0); + function NE_Many_A is new Pone.Parsers.Not_Empty (Many_A); + Result1 : Pone.Parsers.Combinator_Result := NE_Many_A (Input, Context1, 1); + begin + if One_Debug.Status (Result1) /= Packrat.Optional_More then + return Fail; + end if; + declare + Result1_Parts : One_Debug.Result_Part_Array := One_Debug.Parts (Result1); + begin + if Result1_Parts'Length /= 2 then + return Fail; + end if; + if One_Debug.Finish (Result1_Parts (1)) /= 1 or + One_Debug.Finish (Result1_Parts (2)) /= 2 + then + return Fail; + end if; + if One_Debug.Value (Result1_Parts (1))'Length /= 1 or + One_Debug.Value (Result1_Parts (2))'Length /= 2 + then + return Fail; + end if; + if One_Debug.Tokens (Result1_Parts (1))'Length /= 0 or + One_Debug.Tokens (Result1_Parts (2))'Length /= 0 + then + return Fail; + end if; + end; + return Pass; + end Not_Empty_Check; + + + + + + function Default_Result_Check + return Test_Result + is + Default : Pone.Parsers.Combinator_Result; + begin + if One_Debug.Status (Default) /= Packrat.Failure or + One_Debug.Parts (Default)'Length /= 0 or + not One_Debug.Is_Empty (One_Debug.Curtails (Default)) + then + return Fail; + end if; + return Pass; + end Default_Result_Check; + + +end Rat_Tests.Parsers; + + diff --git a/test/rat_tests-parsers.ads b/test/rat_tests-parsers.ads new file mode 100644 index 0000000..a70f41e --- /dev/null +++ b/test/rat_tests-parsers.ads @@ -0,0 +1,85 @@ + + +with + + Unit_Tests; + +use + + Unit_Tests; + +private with + + Packrat.No_Lex, + Packrat.Parsers.Debug, + Packrat.Errors, + Packrat.Traits; + + +package Rat_Tests.Parsers is + + + function Count_Check return Test_Result; + function Many_Nomin_Check return Test_Result; + function Many_Min_Check return Test_Result; + + function Many_Until_Nomin_Check return Test_Result; + function Many_Until_Min_Check return Test_Result; + + function Satisfy_Check return Test_Result; + function Satisfy_With_Check return Test_Result; + function Match_Check return Test_Result; + function Match_With_Check return Test_Result; + function Multimatch_Check return Test_Result; + function Take_Check return Test_Result; + function Take_While_Check return Test_Result; + function Take_Until_Check return Test_Result; + + function Empty_Check return Test_Result; + function Not_Empty_Check return Test_Result; + + Combinator_Tests : Test_Array := + ((+"Count", Count_Check'Access), + (+"Many No Minimum", Many_Nomin_Check'Access), + (+"Many With Minimum", Many_Min_Check'Access), + (+"Many_Until No Minimum", Many_Until_Nomin_Check'Access), + (+"Many_Until With Minimum", Many_Until_Min_Check'Access), + (+"Satisfy", Satisfy_Check'Access), + (+"Satisfy_With", Satisfy_With_Check'Access), + (+"Match", Match_Check'Access), + (+"Match_With", Match_With_Check'Access), + (+"Multimatch", Multimatch_Check'Access), + (+"Take", Take_Check'Access), + (+"Take_While", Take_While_Check'Access), + (+"Take_Until", Take_Until_Check'Access), + (+"Empty", Empty_Check'Access), + (+"Not_Empty", Not_Empty_Check'Access)); + + + function Default_Result_Check return Test_Result; + + Other_Tests : Test_Array := + (1 => (+"Default Combinator Result", Default_Result_Check'Access)); + + +private + + + type Parser_Labels_One is (One, Two, Three, Four, Five, Six); + + package Pone is new Packrat.No_Lex + (Parser_Labels_One, Character, String); + + package One_Debug is new Pone.Parsers.Debug; + + + + + function Alphanum_Switch + (Char : in Character) + return Character; + + +end Rat_Tests.Parsers; + + diff --git a/test/test_main.adb b/test/test_main.adb index 1edf4e6..3fdab35 100644 --- a/test/test_main.adb +++ b/test/test_main.adb @@ -12,7 +12,8 @@ with Rat_Tests.Tokens, Rat_Tests.Lexers, Rat_Tests.Utilities, - Rat_Tests.Parse_Graphs; + Rat_Tests.Parse_Graphs, + Rat_Tests.Parsers; use @@ -45,6 +46,7 @@ procedure Test_Main is Err : Packrat.Errors.Error_Message := Packrat.Errors.Encode ("A", 1); Tok : My_Tokens.Token_Type := My_Tokens.Create (A, 1, "abc"); + Fin_Tok : My_Tokens.Finished_Token_Type := (Tok, 5); begin @@ -75,15 +77,15 @@ begin Put_Line ("Running tests for Packrat.Tokens..."); Run_Tests (Rat_Tests.Tokens.Tests, How_Verbose); New_Line; - Put_Line ("Displaying Token debug string output example:"); + Put_Line ("Displaying Token debug string output examples:"); Put (My_Tokens.Debug_String (Tok)); + Put (My_Tokens.Debug_String (Fin_Tok)); New_Line; - Put_Line ("Running tests for Packrat.Lexers combinators..."); + Put_Line ("Running tests for Packrat.Lexers..."); + Put_Line ("Testing lexer combinators..."); Run_Tests (Rat_Tests.Lexers.Combinator_Tests, How_Verbose); - New_Line; - - Put_Line ("Running tests for Packrat.Lexers lexing..."); + Put_Line ("Testing lexer scanners..."); Run_Tests (Rat_Tests.Lexers.Lexer_Tests, How_Verbose); New_Line; @@ -99,6 +101,13 @@ begin New_Line; Put_Line ("Displaying Parse_Graph debug string output example:"); Put (Rat_Tests.Parse_Graphs.Debug_String_Check); + New_Line; + + Put_Line ("Running tests for Packrat.Parsers..."); + Put_Line ("Testing parser combinators..."); + Run_Tests (Rat_Tests.Parsers.Combinator_Tests, How_Verbose); + Put_Line ("Testing other tests..."); + Run_Tests (Rat_Tests.Parsers.Other_Tests, How_Verbose); end Test_Main; -- cgit