summaryrefslogtreecommitdiff
path: root/src/packrat-graphs.ads
diff options
context:
space:
mode:
Diffstat (limited to 'src/packrat-graphs.ads')
-rw-r--r--src/packrat-graphs.ads381
1 files changed, 285 insertions, 96 deletions
diff --git a/src/packrat-graphs.ads b/src/packrat-graphs.ads
index 0ef298e..cd5c364 100644
--- a/src/packrat-graphs.ads
+++ b/src/packrat-graphs.ads
@@ -4,28 +4,27 @@ with
Ada.Iterator_Interfaces;
+private with
+
+ Ada.Containers.Ordered_Maps,
+ Ada.Containers.Vectors;
+
generic
type Label_Enum is (<>);
type Element is private;
type Element_Array is array (Positive range <>) of Element;
- with package My_Interfaces is new Interfaces (Label_Enum, Element, Element_Array);
package Packrat.Graphs is
- type Node is new My_Interfaces.Node with private;
-
- type Node_Reference (Data : not null access Node'Class) is limited null record
- with Implicit_Dereference => Data;
-
-
- type Cursor is new My_Interfaces.Cursor with private;
+ type Node is private;
- type Iter_Cursor (Data : not null access Cursor) is private
+ type Node_Reference (Data : not null access Node) is limited null record
with Implicit_Dereference => Data;
+ type Cursor is private;
- type Parse_Graph is new My_Interfaces.Graph with private
+ type Graph is tagged private
with Default_Iterator => Iterate,
Iterator_Element => Node_Reference,
Variable_Indexing => Node_At;
@@ -33,9 +32,9 @@ package Packrat.Graphs is
- No_Position : constant My_Interfaces.Cursor'Class;
+ No_Position : constant Cursor;
- Empty_Graph : constant Parse_Graph;
+ Empty_Graph : constant Graph;
@@ -44,13 +43,23 @@ package Packrat.Graphs is
(New_Item : in Element_Array;
Start : in Positive;
Finish : in Natural)
- return Node;
+ return Node
+ with Pre =>
+ Finish + 1 >= Start,
+ Post =>
+ Is_Leaf (Leaf'Result);
function Branch
(Label : in Label_Enum;
Start : in Positive;
Finish : in Natural)
- return Node;
+ return Node
+ with Pre =>
+ Finish + 1 >= Start,
+ Post =>
+ Is_Branch (Branch'Result);
+
+
function Is_Leaf
@@ -62,13 +71,19 @@ package Packrat.Graphs is
return Boolean;
+
+
function Label
(This : in Node)
- return Label_Enum;
+ return Label_Enum
+ with Pre =>
+ Is_Branch (This);
function Elements
(This : in Node)
- return Element_Array;
+ return Element_Array
+ with Pre =>
+ Is_Leaf (This);
function Start
(This : in Node)
@@ -94,38 +109,57 @@ package Packrat.Graphs is
function Is_Node
(Position : in Cursor)
- return Boolean;
+ return Boolean
+ with Post =>
+ (if Is_Node'Result then not Is_Nothing (Position));
function Is_Root
(Position : in Cursor)
- return Boolean;
+ return Boolean
+ with Post =>
+ (if Is_Root'Result then
+ not Is_Nothing (Position) and
+ Is_Nothing (Parent (Position)) and
+ Depth (Position) = 0);
function Is_Branch
(Position : in Cursor)
- return Boolean;
+ return Boolean
+ with Post =>
+ (if Is_Branch'Result then not Is_Nothing (Position));
function Is_Leaf
(Position : in Cursor)
- return Boolean;
+ return Boolean
+ with Post =>
+ (if Is_Leaf'Result then not Is_Nothing (Position));
function Label
(Position : in Cursor)
- return Label_Enum;
+ return Label_Enum
+ with Pre =>
+ Is_Branch (Position);
function Elements
(Position : in Cursor)
- return Element_Array;
+ return Element_Array
+ with Pre =>
+ Is_Leaf (Position);
function Start
(Position : in Cursor)
- return Positive;
+ return Positive
+ with Pre =>
+ not Is_Nothing (Position);
function Finish
(Position : in Cursor)
- return Natural;
+ return Natural
+ with Pre =>
+ not Is_Nothing (Position);
function Choices
(Position : in Cursor)
@@ -141,7 +175,9 @@ package Packrat.Graphs is
function Child_Count
(Position : in Cursor;
Choice : in Positive)
- return Natural;
+ return Natural
+ with Pre =>
+ Choice <= Choices (Position);
function Child_Count
(Position : in Cursor)
@@ -154,38 +190,62 @@ package Packrat.Graphs is
function First_Child
(Position : in Cursor;
Choice : in Positive)
- return Cursor;
+ return Cursor
+ with Pre =>
+ Choice <= Choices (Position),
+ Post =>
+ Parent (First_Child'Result) = Position;
function Last_Child
(Position : in Cursor;
Choice : in Positive)
- return Cursor;
+ return Cursor
+ with Pre =>
+ Choice <= Choices (Position),
+ Post =>
+ Parent (Last_Child'Result) = Position;
function First_Child
(Position : in Cursor)
- return Cursor;
+ return Cursor
+ with Post =>
+ Parent (First_Child'Result) = Position;
function Last_Child
(Position : in Cursor)
- return Cursor;
+ return Cursor
+ with Post =>
+ Parent (Last_Child'Result) = Position;
function Next_Sibling
(Position : in Cursor)
- return Cursor;
+ return Cursor
+ with Post =>
+ Parent (Next_Sibling'Result) = Parent (Position);
function Prev_Sibling
(Position : in Cursor)
- return Cursor;
+ return Cursor
+ with Post =>
+ Parent (Prev_Sibling'Result) = Parent (Position);
procedure Delete_Children
(Position : in out Cursor;
- Choice : in Positive);
+ Choice : in Positive)
+ with Pre =>
+ Choice <= Choices (Position),
+ Post =>
+ Child_Count (Position, Choice) = 0;
procedure Delete_Children
- (Position : in out Cursor);
+ (Position : in out Cursor)
+ with Post =>
+ Child_Count (Position) = 0;
procedure Delete_All_Children
- (Position : in out Cursor);
+ (Position : in out Cursor)
+ with Post =>
+ All_Child_Count (Position) = 0;
@@ -201,103 +261,129 @@ package Packrat.Graphs is
function Find_In_Subgraph
(Position : in Cursor;
Item : in Element_Array)
- return Cursor;
+ return Cursor
+ with Post =>
+ Is_Nothing (Find_In_Subgraph'Result) or
+ Is_Leaf (Find_In_Subgraph'Result);
function Contains
- (Container : in Parse_Graph;
- Position : in My_Interfaces.Cursor'Class)
- return Boolean;
+ (Container : in Graph;
+ Position : in Cursor)
+ return Boolean
+ with Post =>
+ (if Contains'Result then not Is_Nothing (Position));
function Singleton
- (Input : in My_Interfaces.Node'Class)
- return Parse_Graph;
+ (Input : in Node)
+ return Graph
+ with Post =>
+ Singleton'Result.Node_Count = 1;
function Node_At
- (Container : in Parse_Graph;
- Position : in My_Interfaces.Cursor'Class)
+ (Container : in Graph;
+ Position : in Cursor)
return Node_Reference
with Pre =>
- Position.Is_Node;
+ Contains (Container, Position);
function Is_Empty
- (Container : in Parse_Graph)
- return Boolean;
+ (Container : in Graph)
+ return Boolean
+ with Post =>
+ (if Is_Empty'Result then Container.Node_Count = 0 else Container.Node_Count /= 0);
function Is_Ambiguous
- (Container : in Parse_Graph)
+ (Container : in Graph)
return Boolean;
function Node_Count
- (Container : in Parse_Graph)
+ (Container : in Graph)
return Natural;
function Root_Count
- (Container : in Parse_Graph)
- return Natural;
+ (Container : in Graph)
+ return Natural
+ with Post =>
+ (if Container.Is_Empty then Root_Count'Result = 0 else Root_Count'Result > 0);
function Root
- (Container : in Parse_Graph;
+ (Container : in Graph;
Index : in Positive)
- return My_Interfaces.Cursor'Class;
+ return Cursor
+ with Pre =>
+ Index <= Container.Root_Count;
procedure Append
- (Container : in out Parse_Graph;
- Addition : in Parse_Graph);
+ (Container : in out Graph;
+ Addition : in Graph)
+ with Pre =>
+ Container.Is_Empty or else Addition.Is_Empty or else
+ Finish (Container.Root (Container.Root_Count)) < Start (Addition.Root (1));
procedure Prepend
- (Container : in out Parse_Graph;
- Addition : in Parse_Graph);
+ (Container : in out Graph;
+ Addition : in Graph)
+ with Pre =>
+ Container.Is_Empty or else Addition.Is_Empty or else
+ Start (Container.Root (1)) > Finish (Addition.Root (Addition.Root_Count));
procedure Attach_Choice
- (Container : in out Parse_Graph;
- Position : in My_Interfaces.Cursor'Class;
- Addition : in Parse_Graph);
+ (Container : in out Graph;
+ Position : in Cursor;
+ Addition : in Graph)
+ with Pre =>
+ Container.Contains (Position) and Is_Branch (Position) and
+ (Addition.Is_Empty or else
+ (Start (Position) <= Start (Addition.Root (1)) and
+ Finish (Position) >= Finish (Addition.Root (Addition.Root_Count))));
procedure Clear
- (Container : in out Parse_Graph);
+ (Container : in out Graph)
+ with Post =>
+ Container.Is_Empty;
procedure Delete_Position
- (Container : in out Parse_Graph;
- Position : in out My_Interfaces.Cursor'Class);
+ (Container : in out Graph;
+ Position : in out Cursor)
+ with Pre'Class =>
+ Container.Contains (Position),
+ Post'Class =>
+ not Container.Contains (Position);
function Find
- (Container : in Parse_Graph;
+ (Container : in Graph;
Item : in Element_Array)
- return My_Interfaces.Cursor'Class;
-
-
-
-
- function Is_Valid_Node
- (Position : in Iter_Cursor)
- return Boolean;
+ return Cursor
+ with Post =>
+ Is_Leaf (Find'Result) or
+ Is_Nothing (Find'Result);
package Graph_Iterators is
- new Ada.Iterator_Interfaces (Iter_Cursor, Is_Valid_Node);
+ new Ada.Iterator_Interfaces (Cursor, Is_Node);
type Choosing_Function is access function
(Position : in Cursor)
@@ -307,16 +393,16 @@ package Packrat.Graphs is
function Iterate
- (This : in Parse_Graph)
+ (This : in Graph)
return Graph_Iterators.Reversible_Iterator'Class;
function Iterate_Subtree
- (This : in Parse_Graph;
- Position : in My_Interfaces.Cursor'Class)
+ (This : in Graph;
+ Position : in Cursor)
return Graph_Iterators.Reversible_Iterator'Class;
function Iterate_Choice
- (This : in Parse_Graph;
+ (This : in Graph;
Func : in Choosing_Function)
return Graph_Iterators.Forward_Iterator'Class;
@@ -326,63 +412,166 @@ package Packrat.Graphs is
private
- type Node is new My_Interfaces.Node with null record;
+ subtype Node_Index is Positive;
+ subtype Extended_Node_Index is Natural;
+
+ package Index_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Positive,
+ Element_Type => Node_Index);
+
+
+
+
+ type Choice_Down is record
+ From : Extended_Node_Index;
+ Choice : Natural;
+ end record;
+
+ function "<"
+ (Left, Right : in Choice_Down)
+ return Boolean;
+
+ package Choice_Down_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Positive,
+ Element_Type => Choice_Down);
+
+
+
+
+ package Choice_Maps is new Ada.Containers.Ordered_Maps
+ (Key_Type => Node_Index,
+ Element_Type => Natural);
+
+ package Edge_Down_Maps is new Ada.Containers.Ordered_Maps
+ (Key_Type => Choice_Down,
+ Element_Type => Index_Vectors.Vector,
+ "=" => Index_Vectors."=");
+
+ package Edge_Up_Maps is new Ada.Containers.Ordered_Maps
+ (Key_Type => Node_Index,
+ Element_Type => Index_Vectors.Vector,
+ "=" => Index_Vectors."=");
+
+
+
+
+ type Element_Array_Access is access Element_Array;
+
+ type Elem_Wrapper is new Ada.Finalization.Controlled with record
+ Data : Element_Array_Access;
+ end record;
+
+ overriding procedure Adjust
+ (This : in out Elem_Wrapper);
+
+ overriding procedure Finalize
+ (This : in out Elem_Wrapper);
+
+ function Wrap
+ (Data : in Element_Array)
+ return Elem_Wrapper;
+
+ Empty_Wrapper : constant Elem_Wrapper :=
+ (Ada.Finalization.Controlled with Data => null);
+
+ type Node_Kind is (Null_Node, Branch_Node, Leaf_Node);
+
+ type Node is record
+ Kind : Node_Kind;
+ Ident : Label_Enum;
+ Content : Elem_Wrapper;
+ Start : Positive;
+ Finish : Natural;
+ end record;
+
+ package Node_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Node_Index,
+ Element_Type => Node);
+
+
- type Cursor is new My_Interfaces.Cursor with null record;
- type Iter_Cursor (Data : not null access Cursor) is null record;
+ type Cursor is record
+ My_Graph : access Graph;
+ Index : Extended_Node_Index;
+ Track : Choice_Down_Vectors.Vector;
+ end record;
+
- type Parse_Graph is new My_Interfaces.Graph with null record;
+ type Graph is tagged record
+ Root_List : Index_Vectors.Vector;
+ Node_List : Node_Vectors.Vector;
+ Add_Place : Node_Index;
+ Choices : Choice_Maps.Map;
+ Down_Edges : Edge_Down_Maps.Map;
+ Up_Edges : Edge_Up_Maps.Map;
+ end record;
- No_Node : constant Node := (My_Interfaces.Node with null record);
- No_Position_Actual : constant Cursor := (My_Interfaces.Cursor with null record);
- No_Position : constant My_Interfaces.Cursor'Class := No_Position_Actual;
- Empty_Graph : constant Parse_Graph := (My_Interfaces.Graph with null record);
+ No_Node : constant Node :=
+ (Kind => Null_Node,
+ Ident => Label_Enum'First,
+ Content => Empty_Wrapper,
+ Start => 1,
+ Finish => 0);
+
+ No_Position : constant Cursor :=
+ (My_Graph => null,
+ Index => 0,
+ Track => Choice_Down_Vectors.Empty_Vector);
+
+ Empty_Graph : constant Graph :=
+ (Root_List => Index_Vectors.Empty_Vector,
+ Node_List => Node_Vectors.Empty_Vector,
+ Add_Place => 1,
+ Choices => Choice_Maps.Empty_Map,
+ Down_Edges => Edge_Down_Maps.Empty_Map,
+ Up_Edges => Edge_Up_Maps.Empty_Map);
type Forward_Iterator is new Graph_Iterators.Forward_Iterator with record
- My_Container : access Parse_Graph;
- My_Position : Cursor;
+ Position : Cursor;
end record;
overriding function First
(Object : in Forward_Iterator)
- return Iter_Cursor;
+ return Cursor;
overriding function Next
(Object : in Forward_Iterator;
- Place : in Iter_Cursor)
- return Iter_Cursor;
+ Place : in Cursor)
+ return Cursor;
+
+
+
type Reversible_Iterator is new Graph_Iterators.Reversible_Iterator with record
- My_Container : access Parse_Graph;
- My_Position : Cursor;
+ Position : Cursor;
end record;
overriding function First
(Object : in Reversible_Iterator)
- return Iter_Cursor;
+ return Cursor;
overriding function Next
(Object : in Reversible_Iterator;
- Place : in Iter_Cursor)
- return Iter_Cursor;
+ Place : in Cursor)
+ return Cursor;
overriding function Last
(Object : in Reversible_Iterator)
- return Iter_Cursor;
+ return Cursor;
overriding function Previous
(Object : in Reversible_Iterator;
- Place : in Iter_Cursor)
- return Iter_Cursor;
+ Place : in Cursor)
+ return Cursor;
end Packrat.Graphs;