Tokenize Subroutine

private subroutine Tokenize(parser, tokenized, errorMsg)

Arguments

TypeIntentOptionalAttributesName
class(EquationParser), intent(inout) :: parser
logical, intent(out) :: tokenized
character, intent(out), allocatable:: errorMsg

Contents

Source Code


Source Code

  subroutine Tokenize(parser,tokenized,errorMsg)
    class(EquationParser),intent(inout)    :: parser
    logical,intent(out)                    :: tokenized
    character(:),allocatable,intent(out)  :: errorMsg
    ! Local
    integer :: i,j,k,id
    integer,allocatable :: maxVarLen,varLen

    tokenized = .false.

    call parser%infix%Construct(Stack_Length)

    maxVarLen = 0
    do k = 1,parser%nIndepVars
      maxVarLen = max(maxVarLen,len(parser%indepVars(k)%value))
    enddo

    i = 1
    do while(parser%inFixFormula(i:i) /= ' ')
      varLen = maxVarLen
      if(IsFunction(j,parser%infixFormula(i:i+maxFunctionLength),id)) then

        parser%inFix%top_index = parser%inFix%top_index+1
        parser%inFix%tokens(parser%inFix%top_index)%tokenString = parser%inFixFormula(i:i+j-1)
        parser%inFix%tokens(parser%inFix%top_index)%tokenType = Function_Token
        parser%inFix%tokens(parser%inFix%top_index)%tokenIndex = id
        i = i+j

      elseif(IsVariable(varLen,parser%inFixFormula(i:i+varLen-1),parser%indepVars,parser%nIndepVars)) then
        parser%inFix%top_index = parser%inFix%top_index+1
        parser%inFix%tokens(parser%inFix%top_index)%tokenString = parser%inFixFormula(i:i+varLen-1)
        parser%inFix%tokens(parser%inFix%top_index)%tokenType = Variable_Token
        i = i+varLen

        ! Next item must be an operator, closing parentheses, or end of equation

        if(.not. IsOperator(parser%infixFormula(i:i)) .and. &
           parser%inFixFormula(i:i) /= ')' .and. parser%inFixFormula(i:i) /= ' ') then

          errorMsg = 'Missing operator or closing parentheses after token : '// &
                     trim(parser%inFix%tokens(parser%inFix%top_index)%tokenString)
          return

        endif

      elseif(IsNumber(parser%inFixFormula(i:i))) then

        parser%inFix%top_index = parser%inFix%top_index+1
        parser%inFix%tokens(parser%inFix%top_index)%tokenString = ''

        if(parser%inFixFormula(i:i) == 'p' .or. parser%inFixFormula(i:i) == 'P') then

          ! Conditional for using built in 'pi' definition
          parser%inFix%tokens(parser%inFix%top_index)%tokenString(1:2) = parser%inFixFormula(i:i+1)
          j = 2

        else

          j = 0
          do while(IsNumber(parser%inFixFormula(i+j:i+j)))

            parser%inFix%tokens(parser%inFix%top_index)%tokenString(j+1:j+1) = parser%inFixFormula(i+j:i+j)
            j = j+1

          enddo

        endif

        parser%inFix%tokens(parser%inFix%top_index)%tokenType = Number_Token

        i = i+j

        ! Next item must be an operator or a closing parentheses
        if(.not. IsOperator(parser%infixFormula(i:i)) .and. &
           parser%inFixFormula(i:i) /= ')' .and. parser%inFixFormula(i:i) /= ' ') then

          errorMsg = 'Missing operator or closing parentheses after token : '// &
                     trim(parser%inFix%tokens(parser%inFix%top_index)%tokenString)
          return

        endif

      elseif(IsSeparator(parser%inFixFormula(i:i))) then

        parser%inFix%top_index = parser%inFix%top_index+1
        parser%inFix%tokens(parser%inFix%top_index)%tokenString = parser%inFixFormula(i:i)

        if(parser%inFixFormula(i:i) == '(') then
          parser%inFix%tokens(parser%inFix%top_index)%tokenType = OpeningParentheses_Token
        elseif(parser%inFixFormula(i:i) == ')') then
          parser%inFix%tokens(parser%inFix%top_index)%tokenType = ClosingParentheses_Token
        else
          parser%inFix%tokens(parser%inFix%top_index)%tokenType = Operator_Token
        endif

        i = i+1
      else

        errorMsg = 'Invalid Token : '// &
                   trim(parser%inFixFormula(i:i))

        return

      endif
    enddo

    if(parser%inFix%tokens(1)%tokenType == Operator_Token) then
      if(trim(parser%inFix%tokens(1)%tokenString) == '+' .or. &
         trim(parser%inFix%tokens(1)%tokenString) == '-') then
        parser%inFix%tokens(1)%tokenType = Monadic_Token
      endif
    endif

    do i = 2,parser%inFix%top_index
      if(parser%inFix%tokens(i)%tokenType == Operator_Token .and. &
         parser%inFix%tokens(i-1)%tokenType == OpeningParentheses_Token) then
        parser%inFix%tokens(i)%tokenType = Monadic_Token
      endif
    enddo

    tokenized = .true.

  endsubroutine Tokenize