summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJed Barber <jjbarber@y7mail.com>2020-12-03 22:39:00 +1100
committerJed Barber <jjbarber@y7mail.com>2020-12-03 22:39:00 +1100
commitcc1795dce90c4a498ddfed155c1f3a6f83a50f1d (patch)
tree0510e22bbd33640e9641acdc47a7d761b0ceb0e7
parent81ac04a3b7981403229bc6a8949ddcd0911adb80 (diff)
Parser constraint error bugs fixed
-rw-r--r--src/packrat-parsers.adb95
-rw-r--r--src/packrat-parsers.ads54
2 files changed, 77 insertions, 72 deletions
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)