aboutsummaryrefslogtreecommitdiffstats
path: root/psl/psl-build.adb
diff options
context:
space:
mode:
Diffstat (limited to 'psl/psl-build.adb')
-rw-r--r--psl/psl-build.adb1009
1 files changed, 0 insertions, 1009 deletions
diff --git a/psl/psl-build.adb b/psl/psl-build.adb
deleted file mode 100644
index c3e47baa6..000000000
--- a/psl/psl-build.adb
+++ /dev/null
@@ -1,1009 +0,0 @@
-with GNAT.Table;
-with Ada.Text_IO; use Ada.Text_IO;
-with Types; use Types;
-with PSL.Errors; use PSL.Errors;
-with PSL.CSE; use PSL.CSE;
-with PSL.QM;
-with PSL.Disp_NFAs; use PSL.Disp_NFAs;
-with PSL.Optimize; use PSL.Optimize;
-with PSL.NFAs.Utils;
-with PSL.Prints;
-with PSL.NFAs; use PSL.NFAs;
-
-package body PSL.Build is
- function Build_SERE_FA (N : Node) return NFA;
-
-
- package Intersection is
- function Build_Inter (L, R : NFA; Match_Len : Boolean) return NFA;
- end Intersection;
-
- package body Intersection is
-
- type Stack_Entry_Id is new Natural;
- No_Stack_Entry : constant Stack_Entry_Id := 0;
- type Stack_Entry is record
- L, R : NFA_State;
- Res : NFA_State;
- Next_Unhandled : Stack_Entry_Id;
- end record;
-
- package Stackt is new GNAT.Table
- (Table_Component_Type => Stack_Entry,
- Table_Index_Type => Stack_Entry_Id,
- Table_Low_Bound => 1,
- Table_Initial => 128,
- Table_Increment => 100);
-
- First_Unhandled : Stack_Entry_Id;
-
- procedure Init_Stack is
- begin
- Stackt.Init;
- First_Unhandled := No_Stack_Entry;
- end Init_Stack;
-
- function Not_Empty return Boolean is
- begin
- return First_Unhandled /= No_Stack_Entry;
- end Not_Empty;
-
- procedure Pop_State (L, R : out NFA_State) is
- begin
- L := Stackt.Table (First_Unhandled).L;
- R := Stackt.Table (First_Unhandled).R;
- First_Unhandled := Stackt.Table (First_Unhandled).Next_Unhandled;
- end Pop_State;
-
- function Get_State (N : NFA; L, R : NFA_State) return NFA_State
- is
- Res : NFA_State;
- begin
- for I in Stackt.First .. Stackt.Last loop
- if Stackt.Table (I).L = L
- and then Stackt.Table (I).R = R
- then
- return Stackt.Table (I).Res;
- end if;
- end loop;
- Res := Add_State (N);
- Stackt.Append ((L => L, R => R, Res => Res,
- Next_Unhandled => First_Unhandled));
- First_Unhandled := Stackt.Last;
- return Res;
- end Get_State;
-
- function Build_Inter (L, R : NFA; Match_Len : Boolean) return NFA
- is
- Start_L, Start_R : NFA_State;
- Final_L, Final_R : NFA_State;
- S_L, S_R : NFA_State;
- E_L, E_R : NFA_Edge;
- Res : NFA;
- Start : NFA_State;
- Extra_L, Extra_R : NFA_Edge;
- begin
- Start_L := Get_Start_State (L);
- Start_R := Get_Start_State (R);
- Final_R := Get_Final_State (R);
- Final_L := Get_Final_State (L);
-
- if False then
- Disp_Body (L);
- Disp_Body (R);
- Put ("//start state: ");
- Disp_State (Start_L);
- Put (",");
- Disp_State (Start_R);
- New_Line;
- end if;
-
- if Match_Len then
- Extra_L := No_Edge;
- Extra_R := No_Edge;
- else
- Extra_L := Add_Edge (Final_L, Final_L, True_Node);
- Extra_R := Add_Edge (Final_R, Final_R, True_Node);
- end if;
-
- Res := Create_NFA;
- Init_Stack;
- Start := Get_State (Res, Start_L, Start_R);
- Set_Start_State (Res, Start);
-
- while Not_Empty loop
- Pop_State (S_L, S_R);
-
- if False then
- Put ("//poped state: ");
- Disp_State (S_L);
- Put (",");
- Disp_State (S_R);
- New_Line;
- end if;
-
- E_L := Get_First_Src_Edge (S_L);
- while E_L /= No_Edge loop
- E_R := Get_First_Src_Edge (S_R);
- while E_R /= No_Edge loop
- if not (E_L = Extra_L and E_R = Extra_R) then
- Add_Edge (Get_State (Res, S_L, S_R),
- Get_State (Res,
- Get_Edge_Dest (E_L),
- Get_Edge_Dest (E_R)),
- Build_Bool_And (Get_Edge_Expr (E_L),
- Get_Edge_Expr (E_R)));
- end if;
- E_R := Get_Next_Src_Edge (E_R);
- end loop;
- E_L := Get_Next_Src_Edge (E_L);
- end loop;
- end loop;
- Set_Final_State (Res, Get_State (Res, Final_L, Final_R));
- Remove_Unreachable_States (Res);
-
- if not Match_Len then
- Remove_Edge (Extra_L);
- Remove_Edge (Extra_R);
- end if;
-
- -- FIXME: free L and R.
- return Res;
- end Build_Inter;
- end Intersection;
-
- -- All edges from A are duplicated using B as a source.
- -- Handle epsilon-edges.
- procedure Duplicate_Src_Edges (N : NFA; A, B : NFA_State)
- is
- pragma Unreferenced (N);
- E : NFA_Edge;
- Expr : Node;
- Dest : NFA_State;
- begin
- pragma Assert (A /= B);
- E := Get_First_Src_Edge (A);
- while E /= No_Edge loop
- Expr := Get_Edge_Expr (E);
- Dest := Get_Edge_Dest (E);
- if Expr /= Null_Node then
- Add_Edge (B, Dest, Expr);
- end if;
- E := Get_Next_Src_Edge (E);
- end loop;
- end Duplicate_Src_Edges;
-
- -- All edges to A are duplicated using B as a destination.
- -- Handle epsilon-edges.
- procedure Duplicate_Dest_Edges (N : NFA; A, B : NFA_State)
- is
- pragma Unreferenced (N);
- E : NFA_Edge;
- Expr : Node;
- Src : NFA_State;
- begin
- pragma Assert (A /= B);
- E := Get_First_Dest_Edge (A);
- while E /= No_Edge loop
- Expr := Get_Edge_Expr (E);
- Src := Get_Edge_Src (E);
- if Expr /= Null_Node then
- Add_Edge (Src, B, Expr);
- end if;
- E := Get_Next_Dest_Edge (E);
- end loop;
- end Duplicate_Dest_Edges;
-
- procedure Remove_Epsilon_Edge (N : NFA; S, D : NFA_State) is
- begin
- if Get_First_Src_Edge (S) = No_Edge then
- -- No edge from S.
- -- Move edges to S to D.
- Redest_Edges (S, D);
- Remove_Unconnected_State (N, S);
- if Get_Start_State (N) = S then
- Set_Start_State (N, D);
- end if;
- elsif Get_First_Dest_Edge (D) = No_Edge then
- -- No edge to D.
- -- Move edges from D to S.
- Resource_Edges (D, S);
- Remove_Unconnected_State (N, D);
- if Get_Final_State (N) = D then
- Set_Final_State (N, S);
- end if;
- else
- Duplicate_Dest_Edges (N, S, D);
- Duplicate_Src_Edges (N, D, S);
- Remove_Identical_Src_Edges (S);
- end if;
- end Remove_Epsilon_Edge;
-
- procedure Remove_Epsilon (N : NFA;
- E : NFA_Edge) is
- S : constant NFA_State := Get_Edge_Src (E);
- D : constant NFA_State := Get_Edge_Dest (E);
- begin
- Remove_Edge (E);
-
- Remove_Epsilon_Edge (N, S, D);
- end Remove_Epsilon;
-
- function Build_Concat (L, R : NFA) return NFA
- is
- Start_L, Start_R : NFA_State;
- Final_L, Final_R : NFA_State;
- Eps_L, Eps_R : Boolean;
- E_L, E_R : NFA_Edge;
- begin
- Start_L := Get_Start_State (L);
- Start_R := Get_Start_State (R);
- Final_R := Get_Final_State (R);
- Final_L := Get_Final_State (L);
- Eps_L := Get_Epsilon_NFA (L);
- Eps_R := Get_Epsilon_NFA (R);
-
- Merge_NFA (L, R);
-
- Set_Start_State (L, Start_L);
- Set_Final_State (L, Final_R);
- Set_Epsilon_NFA (L, False);
-
- if Eps_L then
- E_L := Add_Edge (Start_L, Final_L, Null_Node);
- end if;
-
- if Eps_R then
- E_R := Add_Edge (Start_R, Final_R, Null_Node);
- end if;
-
- Remove_Epsilon_Edge (L, Final_L, Start_R);
-
- if Eps_L then
- Remove_Epsilon (L, E_L);
- end if;
- if Eps_R then
- Remove_Epsilon (L, E_R);
- end if;
-
- if (Start_L = Final_L or else Eps_L)
- and then (Start_R = Final_R or else Eps_R)
- then
- Set_Epsilon_NFA (L, True);
- end if;
-
- Remove_Identical_Src_Edges (Final_L);
- Remove_Identical_Dest_Edges (Start_R);
-
- return L;
- end Build_Concat;
-
- function Build_Or (L, R : NFA) return NFA
- is
- Start_L, Start_R : NFA_State;
- Final_L, Final_R : NFA_State;
- Eps : Boolean;
- Start, Final : NFA_State;
- E_S_L, E_S_R, E_L_F, E_R_F : NFA_Edge;
- begin
- Start_L := Get_Start_State (L);
- Start_R := Get_Start_State (R);
- Final_R := Get_Final_State (R);
- Final_L := Get_Final_State (L);
- Eps := Get_Epsilon_NFA (L) or Get_Epsilon_NFA (R);
-
- -- Optimize [*0] | R.
- if Start_L = Final_L
- and then Get_First_Src_Edge (Start_L) = No_Edge
- then
- if Start_R /= Final_R then
- Set_Epsilon_NFA (R, True);
- end if;
- -- FIXME
- -- delete_NFA (L);
- return R;
- end if;
-
- Merge_NFA (L, R);
-
- -- Use Thompson construction.
- Start := Add_State (L);
- Set_Start_State (L, Start);
- E_S_L := Add_Edge (Start, Start_L, Null_Node);
- E_S_R := Add_Edge (Start, Start_R, Null_Node);
-
- Final := Add_State (L);
- Set_Final_State (L, Final);
- E_L_F := Add_Edge (Final_L, Final, Null_Node);
- E_R_F := Add_Edge (Final_R, Final, Null_Node);
-
- Set_Epsilon_NFA (L, Eps);
-
- Remove_Epsilon (L, E_S_L);
- Remove_Epsilon (L, E_S_R);
- Remove_Epsilon (L, E_L_F);
- Remove_Epsilon (L, E_R_F);
-
- return L;
- end Build_Or;
-
- function Build_Fusion (L, R : NFA) return NFA
- is
- Start_R : NFA_State;
- Final_L, Final_R, S_L : NFA_State;
- E_L : NFA_Edge;
- E_R : NFA_Edge;
- N_L, Expr : Node;
- begin
- Start_R := Get_Start_State (R);
- Final_R := Get_Final_State (R);
- Final_L := Get_Final_State (L);
-
- Merge_NFA (L, R);
-
- E_L := Get_First_Dest_Edge (Final_L);
- while E_L /= No_Edge loop
- S_L := Get_Edge_Src (E_L);
- N_L := Get_Edge_Expr (E_L);
-
- E_R := Get_First_Src_Edge (Start_R);
- while E_R /= No_Edge loop
- Expr := Build_Bool_And (N_L, Get_Edge_Expr (E_R));
- Expr := PSL.QM.Reduce (Expr);
- if Expr /= False_Node then
- Add_Edge (S_L, Get_Edge_Dest (E_R), Expr);
- end if;
- E_R := Get_Next_Src_Edge (E_R);
- end loop;
- Remove_Identical_Src_Edges (S_L);
- E_L := Get_Next_Dest_Edge (E_L);
- end loop;
-
- Set_Final_State (L, Final_R);
-
- Set_Epsilon_NFA (L, False);
-
- if Get_First_Src_Edge (Final_L) = No_Edge then
- Remove_State (L, Final_L);
- end if;
- if Get_First_Dest_Edge (Start_R) = No_Edge then
- Remove_State (L, Start_R);
- end if;
-
- return L;
- end Build_Fusion;
-
- function Build_Star_Repeat (N : Node) return NFA is
- Res : NFA;
- Start, Final, S : NFA_State;
- Seq : Node;
- begin
- Seq := Get_Sequence (N);
- if Seq = Null_Node then
- -- Epsilon.
- Res := Create_NFA;
- S := Add_State (Res);
- Set_Start_State (Res, S);
- Set_Final_State (Res, S);
- return Res;
- end if;
- Res := Build_SERE_FA (Seq);
- Start := Get_Start_State (Res);
- Final := Get_Final_State (Res);
- Redest_Edges (Final, Start);
- Set_Final_State (Res, Start);
- Remove_Unconnected_State (Res, Final);
- Set_Epsilon_NFA (Res, False);
- return Res;
- end Build_Star_Repeat;
-
- function Build_Plus_Repeat (N : Node) return NFA is
- Res : NFA;
- Start, Final : NFA_State;
- T : NFA_Edge;
- begin
- Res := Build_SERE_FA (Get_Sequence (N));
- Start := Get_Start_State (Res);
- Final := Get_Final_State (Res);
- T := Get_First_Dest_Edge (Final);
- while T /= No_Edge loop
- Add_Edge (Get_Edge_Src (T), Start, Get_Edge_Expr (T));
- T := Get_Next_Src_Edge (T);
- end loop;
- return Res;
- end Build_Plus_Repeat;
-
- -- Association actual to formals, so that when a formal is referenced, the
- -- actual can be used instead.
- procedure Assoc_Instance (Decl : Node; Instance : Node)
- is
- Formal : Node;
- Actual : Node;
- begin
- -- Temporary associates actuals to formals.
- Formal := Get_Parameter_List (Decl);
- Actual := Get_Association_Chain (Instance);
- while Formal /= Null_Node loop
- if Actual = Null_Node then
- -- Not enough actual.
- raise Internal_Error;
- end if;
- if Get_Actual (Formal) /= Null_Node then
- -- Recursion
- raise Internal_Error;
- end if;
- Set_Actual (Formal, Get_Actual (Actual));
- Formal := Get_Chain (Formal);
- Actual := Get_Chain (Actual);
- end loop;
- if Actual /= Null_Node then
- -- Too many actual.
- raise Internal_Error;
- end if;
- end Assoc_Instance;
-
- procedure Unassoc_Instance (Decl : Node)
- is
- Formal : Node;
- begin
- -- Remove temporary association.
- Formal := Get_Parameter_List (Decl);
- while Formal /= Null_Node loop
- Set_Actual (Formal, Null_Node);
- Formal := Get_Chain (Formal);
- end loop;
- end Unassoc_Instance;
-
- function Build_SERE_FA (N : Node) return NFA
- is
- Res : NFA;
- S1, S2 : NFA_State;
- begin
- case Get_Kind (N) is
- when N_Booleans =>
- Res := Create_NFA;
- S1 := Add_State (Res);
- S2 := Add_State (Res);
- Set_Start_State (Res, S1);
- Set_Final_State (Res, S2);
- if N /= False_Node then
- Add_Edge (S1, S2, N);
- end if;
- return Res;
- when N_Braced_SERE =>
- return Build_SERE_FA (Get_SERE (N));
- when N_Concat_SERE =>
- return Build_Concat (Build_SERE_FA (Get_Left (N)),
- Build_SERE_FA (Get_Right (N)));
- when N_Fusion_SERE =>
- return Build_Fusion (Build_SERE_FA (Get_Left (N)),
- Build_SERE_FA (Get_Right (N)));
- when N_Match_And_Seq =>
- return Intersection.Build_Inter (Build_SERE_FA (Get_Left (N)),
- Build_SERE_FA (Get_Right (N)),
- True);
- when N_And_Seq =>
- return Intersection.Build_Inter (Build_SERE_FA (Get_Left (N)),
- Build_SERE_FA (Get_Right (N)),
- False);
- when N_Or_Prop
- | N_Or_Seq =>
- return Build_Or (Build_SERE_FA (Get_Left (N)),
- Build_SERE_FA (Get_Right (N)));
- when N_Star_Repeat_Seq =>
- return Build_Star_Repeat (N);
- when N_Plus_Repeat_Seq =>
- return Build_Plus_Repeat (N);
- when N_Sequence_Instance
- | N_Endpoint_Instance =>
- declare
- Decl : Node;
- begin
- Decl := Get_Declaration (N);
- Assoc_Instance (Decl, N);
- Res := Build_SERE_FA (Get_Sequence (Decl));
- Unassoc_Instance (Decl);
- return Res;
- end;
- when N_Boolean_Parameter
- | N_Sequence_Parameter =>
- declare
- Actual : constant Node := Get_Actual (N);
- begin
- if Actual = Null_Node then
- raise Internal_Error;
- end if;
- return Build_SERE_FA (Actual);
- end;
- when others =>
- Error_Kind ("build_sere_fa", N);
- end case;
- end Build_SERE_FA;
-
- function Count_Edges (S : NFA_State) return Natural
- is
- Res : Natural;
- E : NFA_Edge;
- begin
- Res := 0;
- E := Get_First_Src_Edge (S);
- while E /= No_Edge loop
- Res := Res + 1;
- E := Get_Next_Src_Edge (E);
- end loop;
- return Res;
- end Count_Edges;
-
- type Count_Vector is array (Natural range <>) of Natural;
-
- procedure Count_All_Edges (N : NFA; Res : out Count_Vector)
- is
- S : NFA_State;
- begin
- S := Get_First_State (N);
- while S /= No_State loop
- Res (Natural (Get_State_Label (S))) := Count_Edges (S);
- S := Get_Next_State (S);
- end loop;
- end Count_All_Edges;
-
- pragma Unreferenced (Count_All_Edges);
-
- package Determinize is
- -- Create a new NFA that reaches its final state only when N fails
- -- (ie when the final state is not reached).
- function Determinize (N : NFA) return NFA;
- end Determinize;
-
- package body Determinize is
- -- In all the comments N stands for the initial NFA (ie the NFA to
- -- determinize).
-
- use Prints;
-
- Flag_Trace : constant Boolean := False;
- Last_Label : Int32 := 0;
-
- -- The tree associates a set of states in N to *an* uniq set in the
- -- result NFA.
- --
- -- As the NFA is labelized, each node represent a state in N, and has
- -- two branches: one for state is present and one for state is absent.
- --
- -- The leaves contain the state in the result NFA.
- --
- -- The leaves are chained to create a stack of state to handle.
- --
- -- The root of the tree is node Start_Tree_Id and represent the start
- -- state of N.
- type Deter_Tree_Id is new Natural;
- No_Tree_Id : constant Deter_Tree_Id := 0;
- Start_Tree_Id : constant Deter_Tree_Id := 1;
-
- -- List of unhanded leaves.
- Deter_Head : Deter_Tree_Id;
-
- type Deter_Tree_Id_Bool_Array is array (Boolean) of Deter_Tree_Id;
-
- -- Node in the tree.
- type Deter_Tree_Entry is record
- Parent : Deter_Tree_Id;
-
- -- For non-leaf:
- Child : Deter_Tree_Id_Bool_Array;
-
- -- For leaf:
- Link : Deter_Tree_Id;
- State : NFA_State;
- -- + value ?
- end record;
-
- package Detert is new GNAT.Table
- (Table_Component_Type => Deter_Tree_Entry,
- Table_Index_Type => Deter_Tree_Id,
- Table_Low_Bound => 1,
- Table_Initial => 128,
- Table_Increment => 100);
-
- type Bool_Vector is array (Natural range <>) of Boolean;
- pragma Pack (Bool_Vector);
-
- -- Convert a set of states in N to a state in the result NFA.
- -- The set is represented by a vector of boolean. An element of the
- -- vector is true iff the corresponding state is present.
- function Add_Vector (V : Bool_Vector; N : NFA) return NFA_State
- is
- E : Deter_Tree_Id;
- Added : Boolean;
- Res : NFA_State;
- begin
- E := Start_Tree_Id;
- Added := False;
- for I in V'Range loop
- if Detert.Table (E).Child (V (I)) = No_Tree_Id then
- Detert.Append ((Child => (No_Tree_Id, No_Tree_Id),
- Parent => E,
- Link => No_Tree_Id,
- State => No_State));
- Detert.Table (E).Child (V (I)) := Detert.Last;
- E := Detert.Last;
- Added := True;
- else
- E := Detert.Table (E).Child (V (I));
- Added := False;
- end if;
- end loop;
- if Added then
- -- Create the new state.
- Res := Add_State (N);
- Detert.Table (E).State := Res;
-
- if Flag_Trace then
- Set_State_Label (Res, Last_Label);
- Put ("Result state" & Int32'Image (Last_Label) & " for");
- for I in V'Range loop
- if V (I) then
- Put (Natural'Image (I));
- end if;
- end loop;
- New_Line;
- Last_Label := Last_Label + 1;
- end if;
-
- -- Put it to the list of states to be handled.
- Detert.Table (E).Link := Deter_Head;
- Deter_Head := E;
-
- return Res;
- else
- return Detert.Table (E).State;
- end if;
- end Add_Vector;
-
- -- Return true iff the stack is empty (ie all the states have been
- -- handled).
- function Stack_Empty return Boolean is
- begin
- return Deter_Head = No_Tree_Id;
- end Stack_Empty;
-
- -- Get an element from the stack.
- -- Extract the state in the result NFA.
- -- Rebuild the set of states in N (ie rebuild the vector of states).
- procedure Stack_Pop (V : out Bool_Vector; S : out NFA_State)
- is
- L, P : Deter_Tree_Id;
- begin
- L := Deter_Head;
- pragma Assert (L /= No_Tree_Id);
- S := Detert.Table (L).State;
- Deter_Head := Detert.Table (L).Link;
-
- for I in reverse V'Range loop
- pragma Assert (L /= Start_Tree_Id);
- P := Detert.Table (L).Parent;
- if L = Detert.Table (P).Child (True) then
- V (I) := True;
- elsif L = Detert.Table (P).Child (False) then
- V (I) := False;
- else
- raise Program_Error;
- end if;
- L := P;
- end loop;
- pragma Assert (L = Start_Tree_Id);
- end Stack_Pop;
-
- type State_Vector is array (Natural range <>) of Natural;
- type Expr_Vector is array (Natural range <>) of Node;
-
- procedure Build_Arcs (N : NFA;
- State : NFA_State;
- States : State_Vector;
- Exprs : Expr_Vector;
- Expr : Node;
- V : Bool_Vector)
- is
- begin
- if Expr = False_Node then
- return;
- end if;
-
- if States'Length = 0 then
- declare
- Reduced_Expr : constant Node := PSL.QM.Reduce (Expr);
- --Reduced_Expr : constant Node := Expr;
- S : NFA_State;
- begin
- if Reduced_Expr = False_Node then
- return;
- end if;
- S := Add_Vector (V, N);
- Add_Edge (State, S, Reduced_Expr);
- if Flag_Trace then
- Put (" Add edge");
- Put (Int32'Image (Get_State_Label (State)));
- Put (" to");
- Put (Int32'Image (Get_State_Label (S)));
- Put (", expr=");
- Dump_Expr (Expr);
- Put (", reduced=");
- Dump_Expr (Reduced_Expr);
- New_Line;
- end if;
- end;
- else
- declare
- N_States : State_Vector renames
- States (States'First + 1 .. States'Last);
- N_V : Bool_Vector (V'Range) := V;
- S : constant Natural := States (States'First);
- E : constant Node := Exprs (S);
- begin
- N_V (S) := True;
- if Expr = Null_Node then
- Build_Arcs (N, State, N_States, Exprs, E, N_V);
- Build_Arcs (N, State, N_States, Exprs,
- Build_Bool_Not (E), V);
- else
- Build_Arcs (N, State, N_States, Exprs,
- Build_Bool_And (E, Expr), N_V);
- Build_Arcs (N, State, N_States, Exprs,
- Build_Bool_And (Build_Bool_Not (E), Expr), V);
- end if;
- end;
- end if;
- end Build_Arcs;
-
- function Determinize_1 (N : NFA; Nbr_States : Natural) return NFA
- is
- Final : Natural;
- V : Bool_Vector (0 .. Nbr_States - 1);
- Exprs : Expr_Vector (0 .. Nbr_States - 1);
- S : NFA_State;
- E : NFA_Edge;
- D : Natural;
- Edge_Expr : Node;
- Expr : Node;
- Nbr_Dest : Natural;
- States : State_Vector (0 .. Nbr_States - 1);
- Res : NFA;
- State : NFA_State;
- begin
- Final := Natural (Get_State_Label (Get_Final_State (N)));
-
- -- FIXME: handle epsilon or final = start -> create an empty NFA.
-
- -- Initialize the tree.
- Res := Create_NFA;
- Detert.Init;
- Detert.Append ((Child => (No_Tree_Id, No_Tree_Id),
- Parent => No_Tree_Id,
- Link => No_Tree_Id,
- State => No_State));
- pragma Assert (Detert.Last = Start_Tree_Id);
- Deter_Head := No_Tree_Id;
-
- -- Put the initial state in the tree and in the stack.
- -- FIXME: ok, we know that its label is 0.
- V := (0 => True, others => False);
- State := Add_Vector (V, Res);
- Set_Start_State (Res, State);
-
- -- The failure state. As there is nothing to do with this
- -- state, remove it from the stack.
- V := (others => False);
- State := Add_Vector (V, Res);
- Set_Final_State (Res, State);
- Stack_Pop (V, State);
-
- -- Iterate on states in the result NFA that haven't yet been handled.
- while not Stack_Empty loop
- Stack_Pop (V, State);
-
- if Flag_Trace then
- Put_Line ("Handle result state"
- & Int32'Image (Get_State_Label (State)));
- end if;
-
- -- Build edges vector.
- Exprs := (others => Null_Node);
- Expr := Null_Node;
-
- S := Get_First_State (N);
- Nbr_Dest := 0;
- while S /= No_State loop
- if V (Natural (Get_State_Label (S))) then
- E := Get_First_Src_Edge (S);
- while E /= No_Edge loop
- D := Natural (Get_State_Label (Get_Edge_Dest (E)));
- Edge_Expr := Get_Edge_Expr (E);
-
- if False and Flag_Trace then
- Put_Line (" edge" & Int32'Image (Get_State_Label (S))
- & " to" & Natural'Image (D));
- end if;
-
- if D = Final then
- Edge_Expr := Build_Bool_Not (Edge_Expr);
- if Expr = Null_Node then
- Expr := Edge_Expr;
- else
- Expr := Build_Bool_And (Expr, Edge_Expr);
- end if;
- else
- if Exprs (D) = Null_Node then
- Exprs (D) := Edge_Expr;
- States (Nbr_Dest) := D;
- Nbr_Dest := Nbr_Dest + 1;
- else
- Exprs (D) := Build_Bool_Or (Exprs (D),
- Edge_Expr);
- end if;
- end if;
- E := Get_Next_Src_Edge (E);
- end loop;
- end if;
- S := Get_Next_State (S);
- end loop;
-
- if Flag_Trace then
- Put (" Final: expr=");
- Print_Expr (Expr);
- New_Line;
- for I in 0 .. Nbr_Dest - 1 loop
- Put (" Dest");
- Put (Natural'Image (States (I)));
- Put (" expr=");
- Print_Expr (Exprs (States (I)));
- New_Line;
- end loop;
- end if;
-
- -- Build arcs.
- if not (Nbr_Dest = 0 and Expr = Null_Node) then
- Build_Arcs (Res, State,
- States (0 .. Nbr_Dest - 1), Exprs, Expr,
- Bool_Vector'(0 .. Nbr_States - 1 => False));
- end if;
- end loop;
-
- --Remove_Unreachable_States (Res);
- return Res;
- end Determinize_1;
-
- function Determinize (N : NFA) return NFA
- is
- Nbr_States : Natural;
- begin
- Labelize_States (N, Nbr_States);
-
- if Flag_Trace then
- Put_Line ("NFA to determinize:");
- Disp_NFA (N);
- Last_Label := 0;
- end if;
-
- return Determinize_1 (N, Nbr_States);
- end Determinize;
- end Determinize;
-
- function Build_Initial_Rep (N : NFA) return NFA
- is
- S : constant NFA_State := Get_Start_State (N);
- begin
- Add_Edge (S, S, True_Node);
- return N;
- end Build_Initial_Rep;
-
- procedure Build_Strong (N : NFA)
- is
- S : NFA_State;
- Final : constant NFA_State := Get_Final_State (N);
- begin
- S := Get_First_State (N);
- while S /= No_State loop
- -- FIXME.
- if S /= Final then
- Add_Edge (S, Final, EOS_Node);
- end if;
- S := Get_Next_State (S);
- end loop;
- end Build_Strong;
-
- procedure Build_Abort (N : NFA; Expr : Node)
- is
- S : NFA_State;
- E : NFA_Edge;
- Not_Expr : Node;
- begin
- Not_Expr := Build_Bool_Not (Expr);
- S := Get_First_State (N);
- while S /= No_State loop
- E := Get_First_Src_Edge (S);
- while E /= No_Edge loop
- Set_Edge_Expr (E, Build_Bool_And (Not_Expr, Get_Edge_Expr (E)));
- E := Get_Next_Src_Edge (E);
- end loop;
- S := Get_Next_State (S);
- end loop;
- end Build_Abort;
-
- function Build_Property_FA (N : Node) return NFA
- is
- L, R : NFA;
- begin
- case Get_Kind (N) is
- when N_Sequences
- | N_Booleans =>
- -- Build A(S) or A(B)
- R := Build_SERE_FA (N);
- return Determinize.Determinize (R);
- when N_Strong =>
- R := Build_Property_FA (Get_Property (N));
- Build_Strong (R);
- return R;
- when N_Imp_Seq =>
- -- R |=> P --> {R; TRUE} |-> P
- L := Build_SERE_FA (Get_Sequence (N));
- R := Build_Property_FA (Get_Property (N));
- return Build_Concat (L, R);
- when N_Overlap_Imp_Seq =>
- -- S |-> P is defined as Ac(S) : A(P)
- L := Build_SERE_FA (Get_Sequence (N));
- R := Build_Property_FA (Get_Property (N));
- return Build_Fusion (L, R);
- when N_Log_Imp_Prop =>
- -- B -> P --> {B} |-> P --> Ac(B) : A(P)
- L := Build_SERE_FA (Get_Left (N));
- R := Build_Property_FA (Get_Right (N));
- return Build_Fusion (L, R);
- when N_And_Prop =>
- -- P1 && P2 --> A(P1) | A(P2)
- L := Build_Property_FA (Get_Left (N));
- R := Build_Property_FA (Get_Right (N));
- return Build_Or (L, R);
- when N_Never =>
- R := Build_SERE_FA (Get_Property (N));
- return Build_Initial_Rep (R);
- when N_Always =>
- R := Build_Property_FA (Get_Property (N));
- return Build_Initial_Rep (R);
- when N_Abort =>
- R := Build_Property_FA (Get_Property (N));
- Build_Abort (R, Get_Boolean (N));
- return R;
- when N_Property_Instance =>
- declare
- Decl : Node;
- begin
- Decl := Get_Declaration (N);
- Assoc_Instance (Decl, N);
- R := Build_Property_FA (Get_Property (Decl));
- Unassoc_Instance (Decl);
- return R;
- end;
- when others =>
- Error_Kind ("build_property_fa", N);
- end case;
- end Build_Property_FA;
-
- function Build_FA (N : Node) return NFA
- is
- use PSL.NFAs.Utils;
- Res : NFA;
- begin
- Res := Build_Property_FA (N);
- if Optimize_Final then
- pragma Debug (Check_NFA (Res));
-
- Remove_Unreachable_States (Res);
- Remove_Simple_Prefix (Res);
- Merge_Identical_States (Res);
- Merge_Edges (Res);
- end if;
- -- Clear the QM table.
- PSL.QM.Reset;
- return Res;
- end Build_FA;
-end PSL.Build;