From 393870127fe767a0359182ccf80ee9fb48573f97 Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Thu, 3 Dec 2020 15:48:43 +1100 Subject: Main parse functions implemented --- src/packrat-parsers.adb | 140 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 19 deletions(-) (limited to 'src/packrat-parsers.adb') diff --git a/src/packrat-parsers.adb b/src/packrat-parsers.adb index 8533b96..946bfdd 100644 --- a/src/packrat-parsers.adb +++ b/src/packrat-parsers.adb @@ -2,6 +2,7 @@ with + Packrat.Errors, System; @@ -119,7 +120,13 @@ package body Packrat.Parsers is return Result; end if; end if; + if My_Key.Start < Context.Current_Position then + raise Constraint_Error; + end if; Result := Actual (Context); + if Result.Status = Needs_More or Result.Status = Optional_More then + Context.Needs_More.Insert (My_Key.Start); + end if; if Context.Memotable.Contains (My_Key) then Context.Memotable.Replace (My_Key, Result); else @@ -306,6 +313,21 @@ package body Packrat.Parsers is + function Slide + (Input : in Traits.Element_Array; + Position : in Positive) + return Traits.Element_Array + is + subtype Slider is Traits.Element_Array + (Position .. Position + Input'Length - 1); + begin + return Slider (Input); + end Slide; + + + + + function Root (Input : in Traits.Element_Array; Context : in out Parser_Context; @@ -316,7 +338,10 @@ package body Packrat.Parsers is Index : Positive := 1; Root_Elems : Graphs.Finished_Token_Array (1 .. Integer (Salt.Results.Length)); begin - if Salt.Status /= Success then + if Salt.Status = Failure then + raise Parser_Error with Packrat.Errors.Encode + (Traits.Label_Enum'Image (Label), Start); + elsif Salt.Status /= Success then return (Status => Salt.Status); end if; for R of Salt.Results loop @@ -337,25 +362,89 @@ package body Packrat.Parsers is + procedure Tidy_Context + (Input : in Traits.Element_Array; + Context : in out Parser_Context) + is + Delete_Keys : Combo_Key_Vectors.Vector; + begin + if Context.Result_So_Far.Has_Root then + raise Constraint_Error; + end if; + Context.Needs_More.Clear; + Context.Leftrectable.Clear; + if not Context.Used_Before then + Context.Used_Before := True; + Context.Global_Start := Input'First; + Context.Current_Position := Input'First; + end if; + for C in Context.Memotable.Iterate loop + if Memotables.Element (C).Status = Optional_More or + Memotables.Element (C).Status = Needs_More + then + Delete_Keys.Append (Memotables.Key (C)); + end if; + end loop; + for K of Delete_Keys loop + Context.Memotable.Delete (K); + end loop; + end Tidy_Context; + + procedure Parse (Input : in Traits.Element_Array; Context : in out Parser_Context; - Result : out Graphs.Parse_Graph) - is + Result : out Graphs.Parse_Graph) is begin - -- to-do - null; + Tidy_Context (Input, Context); + Context.Allow_Incomplete := (Input'Length /= 0); + declare + use type Traits.Element_Array; + Real_Input : Traits.Element_Array := + (if Context.Pass_Forward.Is_Empty + then Slide (Input, Context.Current_Position) + else Context.Pass_Forward.Element & Input); + begin + if Root_Component (Real_Input, Context, Context.Global_Start).Status = Failure then + raise Parser_Error; + end if; + if Input'Length = 0 then + Result := Context.Result_So_Far; + Result.Delete_Unreachable; + return; + end if; + if not Context.Needs_More.Is_Empty then + Context.Current_Position := Context.Needs_More.First_Element; + Context.Pass_Forward.Replace_Element + (Real_Input (Context.Current_Position .. Real_Input'Last)); + else + Context.Current_Position := Real_Input'Last + 1; + Context.Pass_Forward.Clear; + end if; + end; end Parse; function Parse_Only (Input : in Traits.Element_Array; Context : in out Parser_Context) - return Graphs.Parse_Graph - is + return Graphs.Parse_Graph is begin - -- to-do - return Graphs.Empty_Graph; + Tidy_Context (Input, Context); + Context.Allow_Incomplete := False; + declare + use type Traits.Element_Array; + Real_Input : Traits.Element_Array := + (if Context.Pass_Forward.Is_Empty + then Slide (Input, Context.Current_Position) + else Context.Pass_Forward.Element & Input); + begin + if Root_Component (Real_Input, Context, Context.Global_Start).Status /= Success then + raise Parser_Error; + end if; + Context.Result_So_Far.Delete_Unreachable; + return Context.Result_So_Far; + end; end Parse_Only; @@ -364,9 +453,18 @@ package body Packrat.Parsers is Context : in out Parser_Context) return Graphs.Parse_Graph is + procedure My_Parse is new Parse (Root_Component); + Result : Graphs.Parse_Graph; begin - -- to-do - return Graphs.Empty_Graph; + loop + declare + Next_Input : Traits.Element_Array := Input.all; + begin + My_Parse (Next_Input, Context, Result); + exit when Next_Input'Length = 0; + end; + end loop; + return Result; end Parse_With; @@ -387,17 +485,20 @@ package body Packrat.Parsers is Current : Graphs.Finished_Token; Processed : Result_Sets.Set; begin - if Salt.Status /= Success then - return Salt; + if Salt.Status = Failure then + raise Parser_Error with Packrat.Errors.Encode + (Traits.Label_Enum'Image (Label), Start); end if; for R of Salt.Results loop Current := (Token => Traits.Tokens.Create (Label, Start, R.Value.Element), Finish => R.Finish); - if R.Tokens.Element'Length > 0 then - Context.Result_So_Far.Connect (Current, R.Tokens.Element); - else - Context.Result_So_Far.Include (Current.Token); + if Salt.Status = Success then + if R.Tokens.Element'Length > 0 then + Context.Result_So_Far.Connect (Current, R.Tokens.Element); + else + Context.Result_So_Far.Include (Current.Token); + end if; end if; Processed.Insert ((Finish => R.Finish, @@ -426,8 +527,9 @@ package body Packrat.Parsers is Salt : Combinator_Result := Combo (Input, Context, Start); Processed : Result_Sets.Set; begin - if Salt.Status /= Success then - return Salt; + if Salt.Status = Failure then + raise Parser_Error with Packrat.Errors.Encode + (Traits.Label_Enum'Image (Label), Start); end if; for R of Salt.Results loop Processed.Insert -- cgit