From f8cef7edffc705cc1c168620a6ba0e76a90f6366 Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Sun, 13 Jan 2019 20:19:48 +1100 Subject: Remaining lexer combinators working --- src/packrat-lexer-combinators.adb | 52 ++++++++++++++++++++++++++++++--------- test/ratnest-tests.adb | 25 ++++++++++++++++--- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/packrat-lexer-combinators.adb b/src/packrat-lexer-combinators.adb index 6405efb..1090398 100644 --- a/src/packrat-lexer-combinators.adb +++ b/src/packrat-lexer-combinators.adb @@ -65,26 +65,23 @@ package body Packrat.Lexer.Combinators is return Empty_Fail; end if; loop + exit when Position > Input'Last; Temp := Param (Input, Position); - exit when Temp.Status = Failure; - if Temp.Status = Needs_More then - Result.Status := Optional_More; - exit; - end if; + exit when Temp.Status = Failure or Temp.Status = Needs_More; Result := Result.Join (Temp); Counter := Counter + 1; Position := Start + Result.Length; - if Position > Input'Last then - Result.Status := Optional_More; - exit; - end if; end loop; if Counter < Minimum then - if Result.Status = Optional_More then + if Position > Input'Last or Temp.Status = Needs_More then Result.Status := Needs_More; else Result.Status := Failure; end if; + elsif Position > Input'Last or Temp.Status = Needs_More then + Result.Status := Optional_More; + else + Result.Status := Success; end if; return Result; end Many; @@ -93,9 +90,40 @@ package body Packrat.Lexer.Combinators is function Many_Until (Input : in Element_Array; Start : in Positive) - return Combinator_Result is + return Combinator_Result + is + Result : Combinator_Result := Create_Result (0, Success, Empty_Array); + Temp : Combinator_Result; + Position : Positive := Start; + Counter : Natural := 0; begin - return Empty_Fail; + if Start > Input'Last then + return Empty_Fail; + end if; + loop + exit when Position > Input'Last; + Temp := Param (Input, Position); + exit when Temp.Status = Failure or Temp.Status = Needs_More or Test (Input (Position)); + Result := Result.Join (Temp); + Counter := Counter + 1; + Position := Start + Result.Length; + end loop; + if Counter < Minimum then + if Position > Input'Last or Temp.Status = Needs_More then + Result.Status := Needs_More; + else + Result.Status := Failure; + end if; + elsif Position > Input'Last then + Result.Status := Needs_More; + elsif Temp.Status = Needs_More and Test (Input (Position)) then + Result.Status := Optional_More; + elsif Test (Input (Position)) then + Result.Status := Success; + else + Result.Status := Failure; + end if; + return Result; end Many_Until; diff --git a/test/ratnest-tests.adb b/test/ratnest-tests.adb index 0fac8cd..6f649d9 100644 --- a/test/ratnest-tests.adb +++ b/test/ratnest-tests.adb @@ -379,7 +379,17 @@ package body Ratnest.Tests is function Many_0 is new Strombo.Many (Match_A); function Many_4 is new Strombo.Many (Match_A, 4); - Test_Str : String := "aaabbaaaaabaa"; + function Match_B is new Strombo.Match ('b'); + function Match_C is new Strombo.Match ('c'); + function Seq_Abc is new Strombo.Sequence + ((Match_A'Unrestricted_Access, + Match_B'Unrestricted_Access, + Match_C'Unrestricted_Access)); + function Many_Seq_0 is new Strombo.Many (Seq_Abc); + function Many_Seq_4 is new Strombo.Many (Seq_Abc, 4); + + Test_Str : String := "aaabbaaaaabaa"; + Test_Str2 : String := "aababcabcab"; Result1 : Slexy.Combinator_Result := Slexy.Create_Result (3, Packrat.Success, "aaa"); @@ -392,11 +402,18 @@ package body Ratnest.Tests is Result5 : Slexy.Combinator_Result := Slexy.Empty_Fail; Result6 : Slexy.Combinator_Result := Slexy.Create_Result (2, Packrat.Needs_More, "aa"); + Result7 : Slexy.Combinator_Result := + Slexy.Create_Result (0, Packrat.Success, ""); + Result8 : Slexy.Combinator_Result := + Slexy.Create_Result (6, Packrat.Optional_More, "abcabc"); + Result9 : Slexy.Combinator_Result := + Slexy.Create_Result (6, Packrat.Needs_More, "abcabc"); begin if Many_0 (Test_Str, 1) /= Result1 or Many_4 (Test_Str, 1) /= Result4 or - Many_4 (Test_Str, 6) /= Result3 or Many_0 (Test_Str, 4) /= Result5 or + Many_4 (Test_Str, 6) /= Result3 or Many_0 (Test_Str, 4) /= Result7 or Many_0 (Test_Str, 12) /= Result2 or Many_4 (Test_Str, 12) /= Result6 or - Many_0 (Test_Str, Test_Str'Last + 5) /= Result5 + Many_0 (Test_Str, Test_Str'Last + 5) /= Result5 or + Many_Seq_0 (Test_Str2, 4) /= Result8 or Many_Seq_4 (Test_Str2, 4) /= Result9 then return Fail; end if; @@ -418,7 +435,7 @@ package body Ratnest.Tests is Result2 : Slexy.Combinator_Result := Slexy.Create_Result (3, Packrat.Success, "aaa"); Result3 : Slexy.Combinator_Result := - Slexy.Create_Result (3, Packrat.Optional_More, "aaa"); + Slexy.Create_Result (3, Packrat.Needs_More, "aaa"); Result4 : Slexy.Combinator_Result := Slexy.Empty_Fail; begin if Many_Until_0 (Test_Str, 1) /= Result1 or -- cgit