module Make_LD_Table_m

  use DFA_Defs, only: DFA_t, Not ! DFA table type, Edge label modifier

  implicit NONE

!---------------------------- RCS Module Info ------------------------------
  character (len=*), private, parameter :: ModuleName= &
       "$RCSfile: Make_LD_Table_m.f90,v $"
  private :: not_used_here 
!---------------------------------------------------------------------------

contains

  subroutine Make_LD_Table ( T, Work )
    type(DFA_t(*,*,*,*,*,*)) :: T ! Parameters are N_Vertices, N_Edges,
                                  ! Last_Action, Last_Class,
                                  ! Len_Action, Len_Class
    integer, intent(out), allocatable :: Work(:,:)

    integer :: Extra      ! Edge label modifier bits
    integer :: Nots(0:t%last_class) ! Edges labeled "not A"
    integer :: V, E       ! Vertex, edge indices

    allocate ( work(0:t%last_class,1:t%n_vertices), source=0 )

    ! Positive values are 10 * new state + edge modifier bits.
    ! Edge modifier bits: 1 => Delete current character
    !                     2 => Delete previous character
    ! Negative values are -10 * vertex action, or -10 * vertex action - 1
    ! to indicate that the last-read character is not part of the token
    ! and should be kept for the next cycle.

    ! Fill the work array actions. Fill the entire column. Transitions
    ! are filled into necessary rows of each column later.
    do v = 1, t%n_vertices
      if ( t%actions(v) > 0 ) then
        work(:,v) = -10 * t%actions(v)
        if ( t%edges(v) - t%edges(v-1) > 1 ) work(:,v) = work(:,v) - 1 ! Keep char
      end if
    end do

    ! Fill the work array transitions.
    ! Although not logically correct, "not A or not B" is treated as
    ! "not (A or B)" because this is more useful and the only workable
    ! treatment. That cannot be written in the input because the Not operator
    ! "~" can only precede a single object, not an expression.

    do v = 1, t%n_vertices

      ! Fill the "Nots". They all have the same destination. They do not
      ! have any other modifiers.
      extra = 0
      nots = 0
      do e = t%edges(v-1)+1, t%edges(v)
        if ( iand(t%modify(e),not) /= 0 ) then
          extra = t%to(e)
          nots(t%label(e)) = extra
        end if
      end do
      if ( extra /= 0 ) then
        where ( nots == 0 )
          work(:,v) = 10*extra
        end where
      end if

      do e = t%edges(v-1)+1, t%edges(v)
        extra = t%modify(e)
        if ( iand(extra,not) == 0 ) then ! All characters except this one
          work(t%label(e),v) = 10*t%to(e) + extra
        end if
      end do ! e
    end do ! v

  end subroutine Make_LD_Table

!--------------------------- end bloc --------------------------------------
  logical function not_used_here()
  character (len=*), parameter :: IdParm = &
       "$Id: Make_LD_Table_m.f90,v 1.1 2022/01/24 22:13:02 vsnyder Exp $"
  character (len=len(idParm)) :: Id = idParm
    not_used_here = (id(1:1) == ModuleName(1:1))
    print *, Id ! .mod files sometimes change if PRINT is added
  end function not_used_here
!---------------------------------------------------------------------------

end module Make_LD_Table_m

! $Log: Make_LD_Table_m.f90,v $
! Revision 1.1  2022/01/24 22:13:02  vsnyder
! Initial commit
!
