From cc1795dce90c4a498ddfed155c1f3a6f83a50f1d Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Thu, 3 Dec 2020 22:39:00 +1100 Subject: Parser constraint error bugs fixed --- src/packrat-parsers.adb | 95 +++++++++++++++++++++++++++++++++---------------- src/packrat-parsers.ads | 54 +++++++--------------------- 2 files changed, 77 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/packrat-parsers.adb b/src/packrat-parsers.adb index 6672dc3..f639195 100644 --- a/src/packrat-parsers.adb +++ b/src/packrat-parsers.adb @@ -72,6 +72,33 @@ package body Packrat.Parsers is + function Element + (Hold : in Elem_Holds.Holder) + return Traits.Element_Array is + begin + if Hold.Is_Empty then + return Value : Traits.Element_Array (1 .. 0); + else + return Hold.Element; + end if; + end Element; + + + function Element + (Hold : in Tok_Holds.Holder) + return Graphs.Finished_Token_Array is + begin + if Hold.Is_Empty then + return Value : Graphs.Finished_Token_Array (1 .. 0); + else + return Hold.Element; + end if; + end Element; + + + + + function To_Key (Start : in Positive; Func : access function @@ -125,7 +152,7 @@ package body Packrat.Parsers is end if; Result := Actual (Context); if Result.Status = Needs_More or Result.Status = Optional_More then - Context.Needs_More.Insert (My_Key.Start); + Context.Needs_More.Include (My_Key.Start); end if; if Context.Memotable.Contains (My_Key) then Context.Memotable.Replace (My_Key, Result); @@ -281,10 +308,10 @@ package body Packrat.Parsers is Temp := Next (Input, Context, R.Finish + 1); Adjust.Clear; for N of Temp.Results loop - Adjust.Insert + Adjust.Include ((Finish => N.Finish, - Value => Elem_Holds.To_Holder (R.Value.Element & N.Value.Element), - Tokens => Tok_Holds.To_Holder (R.Tokens.Element & N.Tokens.Element))); + Value => Elem_Holds.To_Holder (Element (R.Value) & Element (N.Value)), + Tokens => Tok_Holds.To_Holder (Element (R.Tokens) & Element (N.Tokens)))); end loop; Temp.Results := Adjust; Merge (Salt, Temp); @@ -366,7 +393,9 @@ package body Packrat.Parsers is Index : Positive := 1; begin for R of Root_Result.Results loop - Length := Length + Integer (R.Tokens.Element'Length); + if not R.Tokens.Is_Empty then + Length := Length + Integer (Element (R.Tokens)'Length); + end if; end loop; if Length = 0 then return Graphs.Empty_Graph; @@ -375,7 +404,7 @@ package body Packrat.Parsers is Root_Elems : Graphs.Finished_Token_Array (1 .. Length); begin for R of Root_Result.Results loop - for T of R.Tokens.Element loop + for T of Element (R.Tokens) loop Root_Elems (Index) := T; Index := Index + 1; end loop; @@ -399,12 +428,12 @@ package body Packrat.Parsers is Real_Input : Traits.Element_Array := (if Context.Pass_Forward.Is_Empty then Slide (Input, Context.Current_Position) - else Context.Pass_Forward.Element & Input); + else Element (Context.Pass_Forward) & Input); Root_Result : Combinator_Result := Root (Real_Input, Context, Context.Global_Start); begin if Root_Result.Status = Failure then - raise Parser_Error; + raise Parser_Error with -Context.Error_String; end if; if Input'Length = 0 then Result := Finish_Root (Root_Result, Context); @@ -434,12 +463,12 @@ package body Packrat.Parsers is Real_Input : Traits.Element_Array := (if Context.Pass_Forward.Is_Empty then Slide (Input, Context.Current_Position) - else Context.Pass_Forward.Element & Input); + else Element (Context.Pass_Forward) & Input); Root_Result : Combinator_Result := Root (Real_Input, Context, Context.Global_Start); begin if Root_Result.Status /= Success then - raise Parser_Error; + raise Parser_Error with -Context.Error_String; end if; return Finish_Root (Root_Result, Context); end; @@ -484,21 +513,24 @@ package body Packrat.Parsers is Processed : Result_Sets.Set; begin if Salt.Status = Failure then - raise Parser_Error with Packrat.Errors.Encode - (Traits.Label_Enum'Image (Label), Start); + Ada.Strings.Unbounded.Append + (Context.Error_String, + Packrat.Errors.Encode (Traits.Label_Enum'Image (Label), Start)); + else + Context.Error_String := +""; end if; for R of Salt.Results loop Current := - (Token => Traits.Tokens.Create (Label, Start, R.Value.Element), + (Token => Traits.Tokens.Create (Label, Start, Element (R.Value)), Finish => R.Finish); if Salt.Status = Success then - if R.Tokens.Element'Length > 0 then - Context.Result_So_Far.Connect (Current, R.Tokens.Element); + if not R.Tokens.Is_Empty then + Context.Result_So_Far.Connect (Current, Element (R.Tokens)); else Context.Result_So_Far.Include (Current.Token); end if; end if; - Processed.Insert + Processed.Include ((Finish => R.Finish, Value => Elem_Holds.Empty_Holder, Tokens => Tok_Holds.To_Holder ((1 => Current)))); @@ -526,11 +558,14 @@ package body Packrat.Parsers is Processed : Result_Sets.Set; begin if Salt.Status = Failure then - raise Parser_Error with Packrat.Errors.Encode - (Traits.Label_Enum'Image (Label), Start); + Ada.Strings.Unbounded.Append + (Context.Error_String, + Packrat.Errors.Encode (Traits.Label_Enum'Image (Label), Start)); + else + Context.Error_String := +""; end if; for R of Salt.Results loop - Processed.Insert + Processed.Include ((Finish => R.Finish, Value => Elem_Holds.Empty_Holder, Tokens => Tok_Holds.Empty_Holder)); @@ -725,7 +760,7 @@ package body Packrat.Parsers is Adjust.Clear; for R of Temp.Results loop if R.Finish = Input'Last or else not Test (Input (R.Finish + 1)) then - Adjust.Insert (R); + Adjust.Include (R); end if; end loop; Temp.Results.Assign (Adjust); @@ -787,7 +822,7 @@ package body Packrat.Parsers is if Start <= Input'Last and then Test (Input (Start)) then Part.Finish := Start; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := Success; end if; return Salt; @@ -814,7 +849,7 @@ package body Packrat.Parsers is if Start <= Input'Last and then Test (Change (Input (Start))) then Part.Finish := Start; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := Success; end if; return Salt; @@ -842,7 +877,7 @@ package body Packrat.Parsers is if Start <= Input'Last and then Input (Start) = Item then Part.Finish := Start; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := Success; end if; return Salt; @@ -870,7 +905,7 @@ package body Packrat.Parsers is if Start <= Input'Last and then Change (Input (Start)) = Item then Part.Finish := Start; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := Success; end if; return Salt; @@ -916,7 +951,7 @@ package body Packrat.Parsers is return Salt : Combinator_Result do Part.Finish := Start + My_Offset; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start + My_Offset)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := (if My_Offset < Items'Length - 1 then Needs_More else Success); end return; end Actual; @@ -953,7 +988,7 @@ package body Packrat.Parsers is return Salt : Combinator_Result do Part.Finish := Start + My_Offset; Part.Value := Elem_Holds.To_Holder (Input (Start .. Start + My_Offset)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := (if My_Offset < Number - 1 then Needs_More else Success); end return; end Actual; @@ -986,7 +1021,7 @@ package body Packrat.Parsers is return Salt : Combinator_Result do Part.Finish := My_Finish; Part.Value := Elem_Holds.To_Holder (Input (Start .. My_Finish)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := (if My_Finish = Input'Last and Context.Allow_Incomplete then Optional_More else Success); end return; @@ -1020,7 +1055,7 @@ package body Packrat.Parsers is return Salt : Combinator_Result do Part.Finish := My_Finish; Part.Value := Elem_Holds.To_Holder (Input (Start .. My_Finish)); - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := (if My_Finish = Input'Last and Context.Allow_Incomplete then Optional_More else Success); end return; @@ -1044,7 +1079,7 @@ package body Packrat.Parsers is Salt : Combinator_Result; begin Part.Finish := Start - 1; - Salt.Results.Insert (Part); + Salt.Results.Include (Part); Salt.Status := Success; return Salt; end Empty; @@ -1061,7 +1096,7 @@ package body Packrat.Parsers is begin for R of Salt.Results loop if R.Finish >= Start then - Adjust.Insert (R); + Adjust.Include (R); end if; end loop; Salt.Results.Assign (Adjust); diff --git a/src/packrat-parsers.ads b/src/packrat-parsers.ads index 93ad258..99dbee7 100644 --- a/src/packrat-parsers.ads +++ b/src/packrat-parsers.ads @@ -7,6 +7,7 @@ with private with + Ada.Strings.Unbounded, Ada.Containers.Vectors, Ada.Containers.Ordered_Maps, Ada.Containers.Ordered_Sets, @@ -21,28 +22,6 @@ generic package Packrat.Parsers is - -- Memoize only adds to the Parse_Graph result when it is successful - -- so the Parser_Context will need to keep track of unsuccessful combinator - -- at given positions - - -- If all combinators are memoized in a memotable then no need to keep track of call stack - -- To do that, use start point and function access as the key? - - -- If a combinator at a position is already in the memotable, return result - -- Else run combinator, add/update result in memotable, then return result - -- As a side effect of this, the entry in the memotable will be updated several times - -- while left recursion unwinds - - -- Combinators need to return value strings as well as the finish sets - - -- Two functions, Symbolize and Ignore?, to create a node in the graph and to discard - -- the current return value string - - -- Some way to join tokens-of-tokens into just tokens - - - - type Parser_Context is private; Empty_Context : constant Parser_Context; @@ -315,17 +294,6 @@ private -- does the lexer handle input that doesn't start from 1 at the beginning? - -- results need to record what combinators were curtailed, if any, with leftrec count - - -- choice combinators can be curtailed by multiple combinators at once - - -- results need to deal with tokens to put in the graph somehow - - - -- Curtail when leftrec count exceeds number of remaining tokens plus 1 - -- for a given combinator/position - - package Elem_Holds is new Ada.Containers.Indefinite_Holders (Element_Type => Traits.Element_Array, "=" => Traits."="); @@ -342,6 +310,14 @@ private (Left, Right : in Tok_Holds.Holder) return Boolean; + function Element + (Hold : in Elem_Holds.Holder) + return Traits.Element_Array; + + function Element + (Hold : in Tok_Holds.Holder) + return Graphs.Finished_Token_Array; + @@ -399,15 +375,6 @@ private - -- If there's anything in the Curtails, then Results should be empty - -- and vice versa... union? - - -- need to add a record of the total length of input available when - -- result was computed, to allow for knowing when to recompute - -- optional_more/need_more results - - -- actually no, just not putting optional/needmore results in the - -- memotable will work fine, but how to figure out how much to pass forward? type Combinator_Result is record Results : Result_Sets.Set := Result_Sets.Empty_Set; Curtails : Curtail_Maps.Map := Curtail_Maps.Empty_Map; @@ -443,6 +410,7 @@ private Current_Position : Positive := 1; Needs_More : Needs_Sets.Set; Pass_Forward : Elem_Holds.Holder; + Error_String : Ada.Strings.Unbounded.Unbounded_String; Memotable : Memotables.Map; Leftrectable : Leftrectables.Map; Allow_Incomplete : Boolean := True; @@ -455,6 +423,7 @@ private Current_Position => 1, Needs_More => Needs_Sets.Empty_Set, Pass_Forward => Elem_Holds.Empty_Holder, + Error_String => +"", Memotable => Memotables.Empty_Map, Leftrectable => Leftrectables.Empty_Map, Allow_Incomplete => True); @@ -547,6 +516,7 @@ private + -- Should this be factored out into the main Packrat package? function Slide (Input : in Traits.Element_Array; Position : in Positive) -- cgit