Nodes of different colours represent the following:
Solid arrows point from a parent (sub)module to the submodule which is descended from it. Dashed arrows point from a module being used to the module or program unit using it. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
character(len=*), | intent(in) | :: | InString | |||
integer, | intent(in) | :: | StackNum | |||
integer, | intent(out) | :: | ExpressionNum | |||
character(len=*), | intent(in) | :: | Line |
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
SUBROUTINE ParseExpression(InString, StackNum, ExpressionNum, Line)
! SUBROUTINE INFORMATION:
! AUTHOR Peter Graham Ellis
! DATE WRITTEN June 2006
! MODIFIED Brent Griffith, May 2009
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! Parsing string into a series of tokens
! METHODOLOGY EMPLOYED:
!
! USE STATEMENTS:
USE InputProcessor, ONLY: MakeUpperCase, ProcessNumber, SameString
USE DataInterfaces, ONLY: ShowFatalError, ShowSevereError, ShowContinueError
USE DataSystemVariables, ONLY: DeveloperFlag
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE PARAMETER DEFINITIONS:
INTEGER, PARAMETER :: MaxDoLoopCounts = 500
CHARACTER(len=*), PARAMETER :: fmta='(A)'
! SUBROUTINE ARGUMENT DEFINITIONS:
CHARACTER(len=*), INTENT(IN) :: InString ! String of expression text written in the Runtime Language
INTEGER, INTENT(IN) :: StackNum ! Parent StackNum??
INTEGER, INTENT(OUT) :: ExpressionNum ! index of expression in structure
CHARACTER(len=*), INTENT(IN) :: Line ! Actual line from string
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
! CHARACTER(len=120), DIMENSION(MaxErrors) :: Error ! Errors should be stored with the stack
INTEGER :: NumErrors !
INTEGER :: Pos
INTEGER :: LastPos
INTEGER :: NumTokens
CHARACTER(len=MaxNameLength) :: StringToken ! MaxNameLength won't do here
CHARACTER(len=MaxNameLength+10) :: String
TYPE(TokenType), DIMENSION(:), ALLOCATABLE,SAVE :: Token
TYPE(TokenType), DIMENSION(:), ALLOCATABLE :: TempToken
CHARACTER :: NextChar
LOGICAL :: PeriodFound
LOGICAL :: MinusFound
LOGICAL :: PlusFound
LOGICAL :: ErrorFlag
LOGICAL :: OperatorProcessing
INTEGER :: CountDoLooping
LOGICAL, SAVE :: firsttime=.true.
INTEGER :: i
LOGICAL :: LastED ! last character in a numeric was an E or D
! FLOW:
CountDoLooping = 0
NumErrors = 0
! Error = 'No errors.'
! Break the string into tokens
if (firsttime) then
ALLOCATE(Token(1))
firsttime=.false.
endif
NumTokens = 0
String=InString
! Following is a workaround to parse unitary operators as first value in the expression.
! i.e. Set X = -1
! this creates Set X = 0-1
! and seems to work.
IF (String(1:1) == '-') THEN
String='0'//trim(String)
ELSEIF (String(1:1) == '+') THEN
String='0'//trim(String)
ENDIF
LastPos = LEN_TRIM(String)
Pos = 1
DO WHILE (Pos <= LastPos)
CountDoLooping = CountDoLooping + 1
IF (CountDoLooping > MaxDoLoopCounts) THEN
CALL ShowSevereError('EMS ParseExpression: Entity='//trim(ErlStack(StackNum)%Name))
CALL ShowContinueError('...Line='//trim(Line))
CALL ShowContinueError('...Failed to process String="'//trim(String)//'".')
CALL ShowFatalError('...program terminates due to preceding condition.')
ENDIF
NextChar = String(Pos:Pos)
IF (SCAN(NextChar, ' ') /= 0) THEN
Pos = Pos + 1
CYCLE
END IF
! Extend the token array
! code replaced with a bit safer code below.
! ALLOCATE(TempToken(NumTokens))
! TempToken = Token
! DEALLOCATE(Token)
! ALLOCATE(Token(NumTokens + 1))
! Token(1:NumTokens) = TempToken(1:NumTokens)
! DEALLOCATE(TempToken)
! Extend the token array
if (NumTokens > 0) then !noel -- add to prevent deallocate of 0 -- but not sure if needed
ALLOCATE(TempToken(NumTokens))
!noel
!TempToken = Token
do i=1,NumTokens
TempToken(i) = Token(i)
enddo
DEALLOCATE(Token)
ALLOCATE(Token(NumTokens + 1))
!noel
!Token(1:NumTokens) = TempToken(1:NumTokens)
do i=1,NumTokens
Token(i) = TempToken(i)
enddo
DEALLOCATE(TempToken)
endif
! Get the next token
NumTokens = NumTokens + 1
StringToken = ''
PeriodFound = .FALSE.
MinusFound=.false.
PlusFound=.false.
OperatorProcessing=.false. ! true when an operator is found until terminated by non-operator
ErrorFlag = .FALSE.
LastED=.false.
IF (SCAN(NextChar, '0123456789.') /= 0) THEN
! Parse a number literal token
Pos = Pos + 1
StringToken = TRIM(StringToken)//NextChar
IF (SCAN(NextChar, '.') /= 0) PeriodFound = .TRUE.
DO WHILE (LEN_TRIM(String) > 0)
NextChar = String(Pos:Pos)
IF (SCAN(NextChar, '0123456789.eEdD') /= 0) THEN
Pos = Pos + 1
IF (SCAN(NextChar, '.') /= 0) THEN
IF (PeriodFound) THEN
! ERROR: two periods appearing in a number literal!
CALL ShowSevereError('EMS Parse Expression, for "'//trim(ErlStack(StackNum)%Name)//'".')
CALL ShowContinueError('...Line="'//trim(Line)//'".')
CALL ShowContinueError('...Bad String="'//trim(String)//'".')
CALL ShowContinueError('...Two decimal points detected in String.')
NumErrors=NumErrors+1
ErrorFlag=.true.
EXIT
ELSE
PeriodFound = .TRUE.
END IF
END IF
IF (SCAN(NextChar, 'eEdD') /= 0) THEN
StringToken = TRIM(StringToken)//NextChar
IF (LastED) THEN
CALL ShowSevereError('EMS Parse Expression, for "'//trim(ErlStack(StackNum)%Name)//'".')
CALL ShowContinueError('...Line="'//trim(Line)//'".')
CALL ShowContinueError('...Bad String="'//trim(String)//'".')
CALL ShowContinueError('...Two D/E in numeric String.')
NumErrors=NumErrors+1
ErrorFlag=.true.
! error
EXIT
ELSE
LastED=.true.
ENDIF
ELSE
StringToken = TRIM(StringToken)//NextChar
END IF
ELSE IF (SCAN(NextChar, '+-') /= 0) THEN ! +/- following an ED is okay.
IF (LastED) THEN
StringToken = TRIM(StringToken)//NextChar
Pos = Pos + 1
LastED=.false.
ELSE
EXIT
ENDIF
ELSE IF (SCAN(NextChar, ' +-*/^=<>)') /= 0) THEN ! Any binary operator is okay
EXIT ! End of token
ELSE
! Error: strange sequence of characters: return TokenString//NextChar e.g., 234.44a or 234.44%
StringToken = TRIM(StringToken)//NextChar
EXIT
END IF
END DO
! Save the number token
IF (.not. ErrorFlag) THEN
Token(NumTokens)%Type = TokenNumber
Token(NumTokens)%String = StringToken
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'Number="'//trim(StringToken)//'"'
Token(NumTokens)%Number = ProcessNumber(StringToken, ErrorFlag)
IF (DeveloperFlag .and. ErrorFlag) write(OutputFileDebug,fmta) 'Numeric error flagged'
IF (MinusFound) Token(NumTokens)%Number = -Token(NumTokens)%Number
IF (ErrorFlag) THEN
! Error: something wrong with this number!
CALL ShowSevereError('EMS Parse Expression, for "'//trim(ErlStack(StackNum)%Name)//'".')
CALL ShowContinueError('...Line="'//trim(Line)//'".')
CALL ShowContinueError('...Bad String="'//trim(String)//'".')
CALL ShowContinueError('Invalid numeric="'//trim(StringToken)//'".')
NumErrors=NumErrors+1
END IF
ENDIF
ELSE IF (SCAN(NextChar, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') /= 0) THEN
! Parse an undetermined string token (could be a variable, subroutine, or named operator)
Pos = Pos + 1
StringToken = TRIM(StringToken)//NextChar
OperatorProcessing=.false.
DO WHILE (LEN_TRIM(String) > 0)
NextChar = String(Pos:Pos)
IF (SCAN(NextChar, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789') /= 0) THEN
Pos = Pos + 1
StringToken = TRIM(StringToken)//NextChar
ELSE IF (SCAN(NextChar, ' +-*/^=<>()') /= 0) THEN
EXIT ! End of token
ELSE
! Error: bad syntax: return TokenString//NextChar e.g., var1$ or b%
EXIT
END IF
END DO
! Save the variable token
Token(NumTokens)%Type = TokenVariable
Token(NumTokens)%String = StringToken
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'Variable="'//trim(StringToken)//'"'
Token(NumTokens)%Variable = NewEMSVariable(StringToken, StackNum)
ELSE IF (SCAN(NextChar, '+-*/^=<>@|&') /= 0) THEN
! Parse an operator token
StringToken = NextChar
Token(NumTokens)%Type = TokenOperator
! First check for two character operators: == <> <= >=
IF (String(Pos:Pos + 1) == '==') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatorEqual
Token(NumTokens)%String = String(Pos:Pos + 1)
Pos = Pos + 1
ELSE IF (String(Pos:Pos + 1) == '<>') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatorNotEqual
Token(NumTokens)%String = String(Pos:Pos + 1)
Pos = Pos + 1
ELSE IF (String(Pos:Pos + 1) == '<=') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatorLessOrEqual
Token(NumTokens)%String = String(Pos:Pos + 1)
Pos = Pos + 1
ELSE IF (String(Pos:Pos + 1) == '>=') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatorGreaterOrEqual
Token(NumTokens)%String = String(Pos:Pos + 1)
Pos = Pos + 1
ELSE IF (String(Pos:Pos +1) == '||') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatiorLogicalOR
Token(NumTokens)%String = String(Pos:Pos +1)
Pos = Pos + 1
ELSE IF (String(Pos:Pos +1) == '&&') THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+1))//'"'
Token(NumTokens)%Operator = OperatorLogicalAND
Token(NumTokens)%String = String(Pos:Pos +1)
Pos = Pos + 1
! next check for builtin functions signaled by "@"
ELSE IF (String(Pos:Pos) == '@') THEN
IF (SameString(String(Pos:Pos + 5) , '@Round')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+5))//'"'
Token(NumTokens)%Operator = FuncRound
Token(NumTokens)%String = String(Pos:Pos + 5)
Pos = Pos + 5
ELSEIF (SameString(String(Pos:Pos + 3) , '@Mod')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncMod
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 3) , '@Sin')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncSin
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 3) , '@Cos')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncCos
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 6) , '@ArcCos')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+6))//'"'
Token(NumTokens)%Operator = FuncArcCos
Token(NumTokens)%String = String(Pos:Pos + 6)
Pos = Pos + 6
ELSEIF (SameString(String(Pos:Pos + 6) , '@ArcSin')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+6))//'"'
Token(NumTokens)%Operator = FuncArcSin
Token(NumTokens)%String = String(Pos:Pos + 6)
Pos = Pos + 6
ELSEIF (SameString(String(Pos:Pos + 8) , '@DegToRad')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncDegToRad
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 8) , '@RadToDeg')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncRadToDeg
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 3) , '@Exp')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncExp
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 2) , '@Ln')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+2))//'"'
Token(NumTokens)%Operator = FuncLn
Token(NumTokens)%String = String(Pos:Pos + 2)
Pos = Pos + 2
ELSEIF (SameString(String(Pos:Pos + 3) , '@Max')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncMax
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 3) , '@Min')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncMin
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 3) , '@Abs')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+3))//'"'
Token(NumTokens)%Operator = FuncABS
Token(NumTokens)%String = String(Pos:Pos + 3)
Pos = Pos + 3
ELSEIF (SameString(String(Pos:Pos + 13 ) , '@RANDOMUNIFORM')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+13))//'"'
Token(NumTokens)%Operator = FuncRandU
Token(NumTokens)%String = String(Pos:Pos + 13)
Pos = Pos + 13
ELSEIF (SameString(String(Pos:Pos + 12 ) , '@RANDOMNORMAL')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+12))//'"'
Token(NumTokens)%Operator = FuncRandG
Token(NumTokens)%String = String(Pos:Pos + 12)
Pos = Pos + 12
ELSEIF (SameString(String(Pos:Pos + 10 ) , '@SEEDRANDOM')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncRandSeed
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 14) , '@RhoAirFnPbTdbW')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+14))//'"'
Token(NumTokens)%Operator = FuncRhoAirFnPbTdbW
Token(NumTokens)%String = String(Pos:Pos + 14)
Pos = Pos + 14
ELSEIF (SameString(String(Pos:Pos + 11) , '@CpAirFnWTdb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncCpAirFnWTdb
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 12) , '@HfgAirFnWTdb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+12))//'"'
Token(NumTokens)%Operator = FuncHfgAirFnWTdb
Token(NumTokens)%String = String(Pos:Pos + 12)
Pos = Pos + 12
ELSEIF (SameString(String(Pos:Pos + 11) , '@HgAirFnWTdb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncHgAirFnWTdb
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 13) , '@TdpFnTdbTwbPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+13))//'"'
Token(NumTokens)%Operator = FuncTdpFnTdbTwbPb
Token(NumTokens)%String = String(Pos:Pos + 13)
Pos = Pos + 13
ELSEIF (SameString(String(Pos:Pos + 8) , '@TdpFnWPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncTdpFnWPb
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 7) , '@HFnTdbW')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+7))//'"'
Token(NumTokens)%Operator = FuncHFnTdbW
Token(NumTokens)%String = String(Pos:Pos + 7)
Pos = Pos + 7
ELSEIF (SameString(String(Pos:Pos + 10) , '@HFnTdbRhPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncHFnTdbRhPb
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 7) , '@TdbFnHW')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+7))//'"'
Token(NumTokens)%Operator = FuncTdbFnHW
Token(NumTokens)%String = String(Pos:Pos + 7)
Pos = Pos + 7
ELSEIF (SameString(String(Pos:Pos + 11) , '@RhovFnTdbRh')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncRhovFnTdbRh
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 17) , '@RhovFnTdbRhLBnd0C')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+17))//'"'
Token(NumTokens)%Operator = FuncRhovFnTdbRhLBnd0C
Token(NumTokens)%String = String(Pos:Pos + 17)
Pos = Pos + 17
ELSEIF (SameString(String(Pos:Pos + 12) , '@RhovFnTdbWPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+12))//'"'
Token(NumTokens)%Operator = FuncRhovFnTdbWPb
Token(NumTokens)%String = String(Pos:Pos + 12)
Pos = Pos + 12
ELSEIF (SameString(String(Pos:Pos + 11) , '@RhFnTdbRhov')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncRhFnTdbRhov
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 17) , '@RhFnTdbRhovLBnd0C')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+17))//'"'
Token(NumTokens)%Operator = FuncRhFnTdbRhovLBnd0C
Token(NumTokens)%String = String(Pos:Pos + 17)
Pos = Pos + 17
ELSEIF (SameString(String(Pos:Pos + 10) , '@RhFnTdbWPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncRhFnTdbWPb
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 11) , '@TwbFnTdbWPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncTwbFnTdbWPb
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 9) , '@VFnTdbWPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+9))//'"'
Token(NumTokens)%Operator = FuncVFnTdbWPb
Token(NumTokens)%String = String(Pos:Pos + 9)
Pos = Pos + 9
ELSEIF (SameString(String(Pos:Pos + 8) , '@WFnTdpPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncWFnTdpPb
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 7) , '@WFnTdbH')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+7))//'"'
Token(NumTokens)%Operator = FuncWFnTdbH
Token(NumTokens)%String = String(Pos:Pos + 7)
Pos = Pos + 7
ELSEIF (SameString(String(Pos:Pos + 11) , '@WFnTdbTwbPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncWFnTdbTwbPb
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 10) , '@WFnTdbRhPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncWFnTdbRhPb
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 10) , '@PsatFnTemp')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncPsatFnTemp
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 9) , '@TsatFnHPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+9))//'"'
Token(NumTokens)%Operator = FuncTsatFnHPb
Token(NumTokens)%String = String(Pos:Pos + 9)
Pos = Pos + 9
ELSEIF (SameString(String(Pos:Pos + 8) , '@TsatFnPb')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncTsatFnPb
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 4) , '@CpCW')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+4))//'"'
Token(NumTokens)%Operator = FuncCpCW
Token(NumTokens)%String = String(Pos:Pos + 4)
Pos = Pos + 4
ELSEIF (SameString(String(Pos:Pos + 4) , '@CpHW')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+4))//'"'
Token(NumTokens)%Operator = FuncCpHW
Token(NumTokens)%String = String(Pos:Pos + 4)
Pos = Pos + 4
ELSEIF (SameString(String(Pos:Pos + 6) , '@RhoH2O')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+6))//'"'
Token(NumTokens)%Operator = FuncRhoH2O
Token(NumTokens)%String = String(Pos:Pos + 6)
Pos = Pos + 6
ELSEIF (SameString(String(Pos:Pos + 11) , '@FATALHALTEP')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+11))//'"'
Token(NumTokens)%Operator = FuncFatalHaltEp
Token(NumTokens)%String = String(Pos:Pos + 11)
Pos = Pos + 11
ELSEIF (SameString(String(Pos:Pos + 12) , '@SEVEREWARNEP')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+12))//'"'
Token(NumTokens)%Operator = FuncSevereWarnEp
Token(NumTokens)%String = String(Pos:Pos + 12)
Pos = Pos + 12
ELSEIF (SameString(String(Pos:Pos + 6) , '@WARNEP')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+6))//'"'
Token(NumTokens)%Operator = FuncWarnEp
Token(NumTokens)%String = String(Pos:Pos + 6)
Pos = Pos + 6
ELSEIF (SameString(String(Pos:Pos + 10) , '@TRENDVALUE')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncTrendValue
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSEIF (SameString(String(Pos:Pos + 12) , '@TRENDAVERAGE')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+12))//'"'
Token(NumTokens)%Operator = FuncTrendAverage
Token(NumTokens)%String = String(Pos:Pos + 12)
Pos = Pos + 12
ELSEIF (SameString(String(Pos:Pos + 8) , '@TRENDMAX')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncTrendMax
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 8) , '@TRENDMIN')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncTrendMin
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 14) , '@TRENDDIRECTION')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+14))//'"'
Token(NumTokens)%Operator = FuncTrendDirection
Token(NumTokens)%String = String(Pos:Pos + 14)
Pos = Pos + 14
ELSEIF (SameString(String(Pos:Pos + 8) , '@TRENDSUM')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+8))//'"'
Token(NumTokens)%Operator = FuncTrendSum
Token(NumTokens)%String = String(Pos:Pos + 8)
Pos = Pos + 8
ELSEIF (SameString(String(Pos:Pos + 10) , '@CURVEVALUE')) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'FUNCTION "'//trim(String(Pos:Pos+10))//'"'
Token(NumTokens)%Operator = FuncCurveValue
Token(NumTokens)%String = String(Pos:Pos + 10)
Pos = Pos + 10
ELSE ! throw error
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'ERROR "'//trim(String)//'"'
CALL ShowFatalError('EMS Runtime Language: did not find valid input for built-in function ='//Trim(String))
ENDIF
ELSE
! Check for remaining single character operators
Token(NumTokens)%String = StringToken
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'OPERATOR "'//trim(StringToken)//'"'
SELECT CASE (StringToken)
CASE ('+')
IF (.not. OperatorProcessing) THEN
Token(NumTokens)%Operator = OperatorAdd
OperatorProcessing=.true.
ELSE
PlusFound=.true.
OperatorProcessing=.false.
ENDIF
CASE ('-')
IF (.not. OperatorProcessing) THEN
Token(NumTokens)%Operator = OperatorSubtract
OperatorProcessing=.true.
ELSE
MinusFound=.true.
OperatorProcessing=.false.
ENDIF
CASE ('*')
Token(NumTokens)%Operator = OperatorMultiply
OperatorProcessing=.true.
CASE ('/')
Token(NumTokens)%Operator = OperatorDivide
OperatorProcessing=.true.
CASE ('<')
Token(NumTokens)%Operator = OperatorLessThan
OperatorProcessing=.true.
CASE ('>')
Token(NumTokens)%Operator = OperatorGreaterThan
OperatorProcessing=.true.
CASE ('^')
Token(NumTokens)%Operator = OperatorRaiseToPower
OperatorProcessing=.true.
CASE DEFAULT
! Uh OH, this should never happen! throw error
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'ERROR "'//trim(StringToken)//'"'
CAll ShowFatalError('EMS, caught unexpected token = "'//Trim(StringToken)//'" ; while parsing string='//Trim(String))
END SELECT
END IF
Pos = Pos + 1
ELSE IF (SCAN(NextChar, '()') /= 0) THEN
! Parse a parenthesis token
Pos = Pos + 1
StringToken = NextChar
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'PAREN "'//trim(StringToken)//'"'
Token(NumTokens)%Type = TokenParenthesis
Token(NumTokens)%String = StringToken
IF (NextChar == '(') Token(NumTokens)%Parenthesis = ParenthesisLeft
IF (NextChar == ')') Token(NumTokens)%Parenthesis = ParenthesisRight
ELSE IF (SCAN(NextChar, '"') /= 0) THEN
! Parse a string literal token
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'LITERAL STRING'
Pos = Pos + 1
ELSE
! Error: bad start to the token
END IF
END DO
IF (NumErrors > 0) THEN
IF (DeveloperFlag) write(OutputFileDebug,fmta) 'ERROR OUT'
CALL ShowFatalError('EMS, previous errors cause termination.')
ENDIF
ExpressionNum = ProcessTokens(Token, NumTokens, StackNum, String)
RETURN
END SUBROUTINE ParseExpression