summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJed Barber <jjbarber@y7mail.com>2020-12-03 00:08:05 +1100
committerJed Barber <jjbarber@y7mail.com>2020-12-03 00:08:05 +1100
commite07aa7be550b1ecf557e554f680380dff5eef4cd (patch)
tree79902f4b8598b2d8aa2a805993c9a18e56096556 /src
parent0a4e00c7dfa35265de2808c3c405f26b2115ec00 (diff)
Revised how root nodes are handled in parse graphs
Diffstat (limited to 'src')
-rw-r--r--src/packrat-parse_graphs.adb208
-rw-r--r--src/packrat-parse_graphs.ads73
2 files changed, 131 insertions, 150 deletions
diff --git a/src/packrat-parse_graphs.adb b/src/packrat-parse_graphs.adb
index ef425d7..b919cff 100644
--- a/src/packrat-parse_graphs.adb
+++ b/src/packrat-parse_graphs.adb
@@ -20,12 +20,11 @@ package body Packrat.Parse_Graphs is
return Boolean
is
use type Base.Graph;
- use type Finish_Vectors.Vector;
+ use type Finished_Token_Vectors.Vector;
use type Node_Label_Maps.Map;
begin
return Left.Internal_Graph = Right.Internal_Graph and
- Left.Root_Node = Right.Root_Node and
- Left.Root_Finishes = Right.Root_Finishes and
+ Left.Root_Elems = Right.Root_Elems and
Left.Label_Map = Right.Label_Map;
end "=";
@@ -91,12 +90,34 @@ package body Packrat.Parse_Graphs is
function "<"
+ (Left, Right : in Finished_Token_Vectors.Vector)
+ return Boolean
+ is
+ Left_Index : Positive := Left.First_Index;
+ Right_Index : Positive := Right.First_Index;
+ begin
+ while Left_Index <= Left.Last_Index and Right_Index <= Right.Last_Index loop
+ if Left.Element (Left_Index) < Right.Element (Right_Index) then
+ return True;
+ elsif Left.Element (Left_Index) /= Right.Element (Right_Index) then
+ return False;
+ end if;
+ Left_Index := Left_Index + 1;
+ Right_Index := Right_Index + 1;
+ end loop;
+ return Left.Length < Right.Length;
+ end "<";
+
+
+ function "<"
(Left, Right : in Token_Group)
- return Boolean is
+ return Boolean
+ is
+ use type Finished_Token_Vectors.Vector;
begin
if Traits.Tokens.Start (Left.Parent.Token) = Traits.Tokens.Start (Right.Parent.Token) then
if Finish (Left) = Finish (Right) then
- return Left.Elems.Element < Right.Elems.Element;
+ return Left.Elems < Right.Elems;
else
return Finish (Left) < Finish (Right);
end if;
@@ -115,8 +136,7 @@ package body Packrat.Parse_Graphs is
Source : in Parse_Graph) is
begin
Target.Internal_Graph.Assign (Source.Internal_Graph);
- Target.Root_Node := Source.Root_Node;
- Target.Root_Finishes.Assign (Source.Root_Finishes);
+ Target.Root_Elems.Assign (Source.Root_Elems);
Target.Label_Map.Assign (Source.Label_Map);
end Assign;
@@ -127,8 +147,7 @@ package body Packrat.Parse_Graphs is
begin
return G : Parse_Graph :=
(Internal_Graph => Source.Internal_Graph.Copy,
- Root_Node => Source.Root_Node,
- Root_Finishes => Source.Root_Finishes.Copy,
+ Root_Elems => Source.Root_Elems.Copy,
Label_Map => Source.Label_Map.Copy);
end Copy;
@@ -137,9 +156,7 @@ package body Packrat.Parse_Graphs is
(Target, Source : in out Parse_Graph) is
begin
Target.Internal_Graph.Move (Source.Internal_Graph);
- Target.Root_Node := Source.Root_Node;
- Source.Root_Node := Base.No_Node;
- Target.Root_Finishes.Move (Source.Root_Finishes);
+ Target.Root_Elems.Move (Source.Root_Elems);
Target.Label_Map.Move (Source.Label_Map);
end Move;
@@ -159,8 +176,7 @@ package body Packrat.Parse_Graphs is
(Container : in out Parse_Graph) is
begin
Container.Internal_Graph.Clear;
- Container.Root_Node := Base.No_Node;
- Container.Root_Finishes.Clear;
+ Container.Root_Elems.Clear;
Container.Label_Map.Clear;
end Clear;
@@ -175,10 +191,16 @@ package body Packrat.Parse_Graphs is
is
Result : Finish_Vectors.Vector;
Current : Finish_Type;
+ Node_Label : Traits.Tokens.Token;
begin
- if Node = Container.Root_Node then
- Result := Container.Root_Finishes;
- end if;
+ Node_Label := Container.Internal_Graph.Label (Node);
+ for Fin_Token of Container.Root_Elems loop
+ if Fin_Token.Token = Node_Label and then
+ not Result.Contains (Fin_Token.Finish)
+ then
+ Result.Append (Fin_Token.Finish);
+ end if;
+ end loop;
for Edge of Container.Internal_Graph.Inbound (Node) loop
Current := Container.Internal_Graph.Label (Edge).Subnode_Finish;
if not Result.Contains (Current) then
@@ -304,14 +326,12 @@ package body Packrat.Parse_Graphs is
if not Container.Contains (Position.Token) then
return False;
end if;
+ for F of Container.Root_Elements loop
+ if F = Position then
+ return True;
+ end if;
+ end loop;
Node := Container.Label_Map.Element (Position.Token);
- if Node = Container.Root_Node then
- for F of Container.Root_Finish_List loop
- if F = Position.Finish then
- return True;
- end if;
- end loop;
- end if;
return (for some Edge of Container.Internal_Graph.Inbound (Node) =>
Container.Internal_Graph.Label (Edge).Subnode_Finish = Position.Finish);
end Contains;
@@ -367,8 +387,7 @@ package body Packrat.Parse_Graphs is
(for some Fin_Token of Elements (Grouping) => Finder (Fin_Token)));
end Finder;
begin
- return (for some Finish of Container.Root_Finish_List =>
- Finder (Container.Root_Element (Finish)));
+ return (for some Fin_Token of Container.Root_Elements => Finder (Fin_Token));
end Reachable;
@@ -411,6 +430,14 @@ package body Packrat.Parse_Graphs is
end All_Reachable;
+ function Valid_Token
+ (Fin_Token : in Finished_Token)
+ return Boolean is
+ begin
+ return Fin_Token.Finish + 1 >= Traits.Tokens.Start (Fin_Token.Token);
+ end Valid_Token;
+
+
function Valid_Starts_Finishes
(Parent : in Finished_Token;
Subtokens : in Finished_Token_Array)
@@ -586,9 +613,11 @@ package body Packrat.Parse_Graphs is
if not Container.Contains (Token) then
return;
end if;
- if Container.Label_Map (Token) = Container.Root_Node then
- Container.Clear_Root;
- end if;
+ for I in reverse 1 .. Container.Root_Elems.Last_Index loop
+ if Container.Root_Elems.Element (I).Token = Token then
+ Container.Root_Elems.Delete (I);
+ end if;
+ end loop;
Container.Internal_Graph.Delete (Container.Label_Map (Token));
Container.Label_Map.Delete (Token);
end Prune;
@@ -603,14 +632,12 @@ package body Packrat.Parse_Graphs is
if not Container.Contains (Position.Token) then
return;
end if;
+ for I in reverse 1 .. Container.Root_Elems.Last_Index loop
+ if Container.Root_Elems.Element (I) = Position then
+ Container.Root_Elems.Delete (I);
+ end if;
+ end loop;
Node := Container.Label_Map.Element (Position.Token);
- if Node = Container.Root_Node then
- for I in reverse 1 .. Container.Root_Finishes.Last_Index loop
- if Container.Root_Finishes.Element (I) = Position.Finish then
- Container.Root_Finishes.Delete (I);
- end if;
- end loop;
- end if;
for Edge of Container.Internal_Graph.Inbound (Node) loop
if Container.Internal_Graph.Label (Edge).Subnode_Finish = Position.Finish then
Container.Internal_Graph.Delete (Edge);
@@ -702,61 +729,40 @@ package body Packrat.Parse_Graphs is
(Container : in Parse_Graph)
return Boolean is
begin
- return Container.Root_Node /= Base.No_Node;
+ return not Container.Root_Elems.Is_Empty;
end Has_Root;
procedure Set_Root
(Container : in out Parse_Graph;
- Token : in Traits.Tokens.Token;
- Finishes : in Finish_Array) is
+ Tokens : in Finished_Token_Array) is
begin
- Container.Root_Node := Container.Label_Map.Element (Token);
- Container.Root_Finishes.Clear;
- for F of Finishes loop
- if not Container.Root_Finishes.Contains (F) then
- Container.Root_Finishes.Append (F);
+ Container.Clear_Root;
+ for Fin_Token of Tokens loop
+ if not Container.Root_Elems.Contains (Fin_Token) then
+ Container.Root_Elems.Append (Fin_Token);
end if;
end loop;
- Finish_Sort.Sort (Container.Root_Finishes);
+ Finished_Token_Sort.Sort (Container.Root_Elems);
end Set_Root;
procedure Clear_Root
(Container : in out Parse_Graph) is
begin
- Container.Root_Node := Base.No_Node;
- Container.Root_Finishes.Clear;
+ Container.Root_Elems.Clear;
end Clear_Root;
- function Root_Token
+ function Root_Elements
(Container : in Parse_Graph)
- return Traits.Tokens.Token is
- begin
- return Container.Internal_Graph.Label (Container.Root_Node);
- end Root_Token;
-
-
- function Root_Finish_List
- (Container : in Parse_Graph)
- return Finish_Array
+ return Finished_Token_Array
is
- function V2A is new Vector_To_Array (Finish_Type, Finish_Array, Finish_Vectors);
- begin
- return V2A (Container.Root_Finishes);
- end Root_Finish_List;
-
-
- function Root_Element
- (Container : in Parse_Graph;
- Finish_At : in Finish_Type)
- return Finished_Token is
+ function V2A is new Vector_To_Array
+ (Finished_Token, Finished_Token_Array, Finished_Token_Vectors);
begin
- return Root : Finished_Token :=
- (Token => Container.Internal_Graph.Label (Container.Root_Node),
- Finish => Finish_At);
- end Root_Element;
+ return V2A (Container.Root_Elems);
+ end Root_Elements;
@@ -770,6 +776,11 @@ package body Packrat.Parse_Graphs is
function V2A is new Vector_To_Array (Finish_Type, Finish_Array, Finish_Vectors);
Result : Finish_Vectors.Vector;
begin
+ for Fin_Token of Container.Root_Elems loop
+ if Fin_Token.Token = Token and not Result.Contains (Fin_Token.Finish) then
+ Result.Append (Fin_Token.Finish);
+ end if;
+ end loop;
for Edge of Container.Internal_Graph.Outbound (Container.Label_Map.Element (Token)) loop
if not Result.Contains (Container.Internal_Graph.Label (Edge).Group_Finish) then
Result.Append (Container.Internal_Graph.Label (Edge).Group_Finish);
@@ -814,8 +825,6 @@ package body Packrat.Parse_Graphs is
return Token_Group_Array
is
function V2A is new Vector_To_Array
- (Finished_Token, Finished_Token_Array, Finished_Token_Vectors);
- function V2A is new Vector_To_Array
(Token_Group, Token_Group_Array, Token_Group_Vectors);
Groupings : Group_Finished_Token_Maps.Map;
Edge_Label : Edge_Label_Type;
@@ -840,7 +849,7 @@ package body Packrat.Parse_Graphs is
Finished_Token_Sort.Sort (Raw_Group);
Result.Append
((Parent => Position,
- Elems => Finished_Token_Array_Holders.To_Holder (V2A (Raw_Group))));
+ Elems => Raw_Group));
end loop;
Token_Group_Sort.Sort (Result);
return V2A (Result);
@@ -851,7 +860,7 @@ package body Packrat.Parse_Graphs is
(Grouping : in Token_Group)
return Positive is
begin
- return Grouping.Elems.Constant_Reference.Element'First;
+ return Grouping.Elems.First_Index;
end First_Index;
@@ -859,7 +868,7 @@ package body Packrat.Parse_Graphs is
(Grouping : in Token_Group)
return Positive is
begin
- return Grouping.Elems.Constant_Reference.Element'Last;
+ return Grouping.Elems.Last_Index;
end Last_Index;
@@ -867,8 +876,7 @@ package body Packrat.Parse_Graphs is
(Grouping : in Token_Group)
return Ada.Containers.Count_Type is
begin
- return Ada.Containers.Count_Type
- (Grouping.Elems.Constant_Reference.Element'Length);
+ return Grouping.Elems.Length;
end Length;
@@ -877,15 +885,18 @@ package body Packrat.Parse_Graphs is
Index : in Positive)
return Finished_Token is
begin
- return Grouping.Elems.Constant_Reference.Element (Index);
+ return Grouping.Elems.Element (Index);
end Element;
function Elements
(Grouping : in Token_Group)
- return Finished_Token_Array is
+ return Finished_Token_Array
+ is
+ function V2A is new Vector_To_Array
+ (Finished_Token, Finished_Token_Array, Finished_Token_Vectors);
begin
- return Grouping.Elems.Element;
+ return V2A (Grouping.Elems);
end Elements;
@@ -913,27 +924,8 @@ package body Packrat.Parse_Graphs is
return Boolean
is
use type Ada.Containers.Count_Type;
- First_Group : Group_ID_Type;
- Seen_Group : Boolean := False;
- Check_Label : Edge_Label_Type;
begin
- if Container.Root_Finishes.Length = 0 then
- return False;
- elsif Container.Root_Finishes.Length > 1 then
- return True;
- end if;
- for Edge of Container.Internal_Graph.Outbound (Container.Root_Node) loop
- Check_Label := Container.Internal_Graph.Label (Edge);
- if Container.Root_Finishes.Contains (Check_Label.Group_Finish) then
- if not Seen_Group then
- Seen_Group := True;
- First_Group := Check_Label.Group_ID;
- elsif Check_Label.Group_ID /= First_Group then
- return True;
- end if;
- end if;
- end loop;
- return False;
+ return Container.Root_Elems.Length /= 1;
end Is_Root_Ambiguous;
@@ -1104,19 +1096,19 @@ package body Packrat.Parse_Graphs is
(Left, Right : in Parse_Graph)
return Boolean
is
+ use type Ada.Containers.Count_Type;
Offset : Integer :=
- Traits.Tokens.Start (Right.Root_Token) - Traits.Tokens.Start (Left.Root_Token);
- Left_Finishes : Finish_Array := Left.Root_Finish_List;
- Right_Finishes : Finish_Array := Right.Root_Finish_List;
+ Traits.Tokens.Start (Right.Root_Elems.Element (1).Token) -
+ Traits.Tokens.Start (Left.Root_Elems.Element (1).Token);
Mapping : Isomorph_Maps.Map;
begin
- if Left_Finishes'Length /= Right_Finishes'Length then
+ if Left.Root_Elems.Length /= Right.Root_Elems.Length then
return False;
end if;
- return (for all Index in Left_Finishes'Range =>
+ return (for all Index in 1 .. Left.Root_Elems.Last_Index =>
Token_Isomorph
- (Left, (Left.Root_Token, Left_Finishes (Index)),
- Right, (Right.Root_Token, Right_Finishes (Index)),
+ (Left, Left.Root_Elems (Index),
+ Right, Right.Root_Elems (Index),
Offset, Mapping));
end Isomorphic;
diff --git a/src/packrat-parse_graphs.ads b/src/packrat-parse_graphs.ads
index fc5861d..4d2d956 100644
--- a/src/packrat-parse_graphs.ads
+++ b/src/packrat-parse_graphs.ads
@@ -7,7 +7,6 @@ with
private with
- Ada.Containers.Indefinite_Holders,
Ada.Containers.Vectors,
Ada.Containers.Ordered_Maps,
Directed_Graphs;
@@ -131,6 +130,10 @@ package Packrat.Parse_Graphs is
return Boolean
with Pre => Container.Has_Root;
+ function Valid_Token
+ (Fin_Token : in Finished_Token)
+ return Boolean;
+
function Valid_Starts_Finishes
(Parent : in Finished_Token;
Subtokens : in Finished_Token_Array)
@@ -214,35 +217,19 @@ package Packrat.Parse_Graphs is
procedure Set_Root
(Container : in out Parse_Graph;
- Token : in Traits.Tokens.Token;
- Finishes : in Finish_Array)
- with Pre => Container.Contains (Token) and
- (for all F of Finishes => F >= Traits.Tokens.Start (Token) - 1),
+ Tokens : in Finished_Token_Array)
+ with Pre => (for all F of Tokens => Container.Contains (F.Token)),
Post => Container.Has_Root;
procedure Clear_Root
(Container : in out Parse_Graph)
with Post => not Container.Has_Root;
- function Root_Token
+ function Root_Elements
(Container : in Parse_Graph)
- return Traits.Tokens.Token
+ return Finished_Token_Array
with Pre => Container.Has_Root;
- function Root_Finish_List
- (Container : in Parse_Graph)
- return Finish_Array
- with Pre => Container.Has_Root,
- Post => Is_Sorted (Root_Finish_List'Result) and
- No_Duplicates (Root_Finish_List'Result);
-
- function Root_Element
- (Container : in Parse_Graph;
- Finish_At : in Finish_Type)
- return Finished_Token
- with Pre => Container.Has_Root and then
- (for some F of Container.Root_Finish_List => F = Finish_At);
-
@@ -408,6 +395,24 @@ private
+
+ package Finished_Token_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Positive,
+ Element_Type => Finished_Token);
+
+ function "<"
+ (Left, Right : in Finished_Token_Vectors.Vector)
+ return Boolean;
+
+ type Token_Group is record
+ Parent : Finished_Token;
+ Elems : Finished_Token_Vectors.Vector;
+ end record;
+
+
+
+
+
package Finish_Vectors is new Ada.Containers.Vectors
(Index_Type => Positive,
Element_Type => Finish_Type);
@@ -419,21 +424,9 @@ private
Element_Type => Node_ID_Type);
type Parse_Graph is tagged record
- Internal_Graph : Base.Graph := Base.Empty_Graph;
- Root_Node : Base.Extended_Node_ID_Type := Base.No_Node;
- Root_Finishes : Finish_Vectors.Vector := Finish_Vectors.Empty_Vector;
- Label_Map : Node_Label_Maps.Map := Node_Label_Maps.Empty_Map;
- end record;
-
-
-
-
- package Finished_Token_Array_Holders is new Ada.Containers.Indefinite_Holders
- (Element_Type => Finished_Token_Array);
-
- type Token_Group is record
- Parent : Finished_Token;
- Elems : Finished_Token_Array_Holders.Holder;
+ Internal_Graph : Base.Graph := Base.Empty_Graph;
+ Root_Elems : Finished_Token_Vectors.Vector := Finished_Token_Vectors.Empty_Vector;
+ Label_Map : Node_Label_Maps.Map := Node_Label_Maps.Empty_Map;
end record;
@@ -448,10 +441,6 @@ private
(Index_Type => Positive,
Element_Type => Group_ID_Type);
- package Finished_Token_Vectors is new Ada.Containers.Vectors
- (Index_Type => Positive,
- Element_Type => Finished_Token);
-
package Token_Group_Vectors is new Ada.Containers.Vectors
(Index_Type => Positive,
Element_Type => Token_Group);
@@ -476,6 +465,7 @@ private
+
package Isomorph_Maps is new Ada.Containers.Ordered_Maps
(Key_Type => Finished_Token,
Element_Type => Finished_Token_Vectors.Vector,
@@ -504,8 +494,7 @@ private
Empty_Graph : constant Parse_Graph :=
(Internal_Graph => Base.Empty_Graph,
- Root_Node => Base.No_Node,
- Root_Finishes => Finish_Vectors.Empty_Vector,
+ Root_Elems => Finished_Token_Vectors.Empty_Vector,
Label_Map => Node_Label_Maps.Empty_Map);