' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

'REM $Include: 'sxript.bi'

'PRINT
'FOR k = 1 TO SxriptLogoSize
'    PRINT SxriptLogoText$(k)
'NEXT
'PRINT
'PRINT " *** Welcome to Sxript *** "
'PRINT "       (QB45 Build)        "
'PRINT

'DO
'    LINE INPUT ":"; a$
'    b$ = SxriptEval$(a$)
'    PRINT ":"; b$: PRINT
'LOOP

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION GetDecimalPos (TheStringIn AS STRING)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
TheString = TheStringIn
TheReturn = INSTR(TheString, ".")
IF (TheReturn < 1) THEN
    TheReturn = -1
END IF
GetDecimalPos = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InsertCharacter$ (TheStringIn AS STRING, TheCharIn AS STRING, TheDigitIn AS INTEGER, NumTimesIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheChar AS STRING
DIM TheDigit AS INTEGER
DIM NumTimes AS INTEGER
DIM a AS STRING
DIM b AS STRING
DIM c AS STRING
DIM k AS INTEGER
TheString = TheStringIn
TheChar = TheCharIn
TheDigit = TheDigitIn
NumTimes = NumTimesIn
a = LEFT$(TheString, TheDigit - 1)
b = ""
FOR k = 1 TO NumTimes
    b = b + TheChar
NEXT
c = RIGHT$(TheString, LEN(TheString) - TheDigit + 1)
TheReturn = a + b + c
InsertCharacter$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReadManyCharacter$ (TheStringIn AS STRING, StartDigitIn AS INTEGER, FinishDigitIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM StartDigit AS INTEGER
DIM FinishDigit AS INTEGER
TheString = TheStringIn
StartDigit = StartDigitIn
FinishDigit = FinishDigitIn
TheReturn = ""
IF ((StartDigit > 0) AND ((FinishDigit - StartDigit) >= 0)) THEN
    TheReturn = MID$(TheString, StartDigit, (FinishDigit - StartDigit) + 1)
END IF
ReadManyCharacter$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReadOneCharacter$ (TheStringIn AS STRING, TheDigitIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheDigit AS INTEGER
TheString = TheStringIn
TheDigit = TheDigitIn
TheReturn = ""
IF (TheDigit > 0) THEN
    TheReturn = MID$(TheString, TheDigit, 1)
END IF
ReadOneCharacter$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveCharacter$ (TheStringIn AS STRING, TheDigitIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheDigit AS INTEGER
DIM a AS STRING
DIM b AS STRING
TheString = TheStringIn
TheDigit = TheDigitIn
a = LEFT$(TheString, TheDigit - 1)
b = RIGHT$(TheString, LEN(TheString) - TheDigit)
TheReturn = a + b
RemoveCharacter$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveDecimal$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM n AS INTEGER
TheString = TheStringIn
TheReturn = TheString
n = GetDecimalPos(TheString)
IF (n <> -1) THEN
    IF (n = LEN(TheString)) THEN
        TheReturn = LEFT$(TheString, LEN(TheString) - 1)
    ELSE
        TheReturn = LEFT$(TheString, n - 1) + RIGHT$(TheString, (LEN(TheString) - n))
    END IF
END IF
RemoveDecimal$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveSign$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn
IF ((LEFT$(TheString, 1) = "+") OR (LEFT$(TheString, 1) = "-")) THEN
    TheReturn = RemoveCharacter$(TheString, 1)
ELSE
    TheReturn = TheString
END IF
RemoveSign$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveZerosLeft$ (TheStringIn AS STRING, TheStartingDigitIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheStartingDigit AS INTEGER
DIM n AS INTEGER
DIM i AS INTEGER
DIM c AS STRING
TheString = TheStringIn
TheStartingDigit = TheStartingDigitIn
n = 0
FOR i = TheStartingDigit TO LEN(TheString)
    c = ReadOneCharacter$(TheString, i)
    IF (c = "0") THEN
        n = n + 1
    ELSE
        EXIT FOR
    END IF
NEXT
TheReturn = LEFT$(TheString, TheStartingDigit - 1) + RIGHT$(TheString, LEN(TheString) - TheStartingDigit - n + 1)
RemoveZerosLeft$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveZerosRight$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM n AS INTEGER
DIM i AS INTEGER
DIM c AS STRING
TheString = TheStringIn
n = 0
FOR i = LEN(TheString) TO 1 STEP -1
    c = ReadOneCharacter$(TheString, i)
    IF (c = "0") THEN
        n = n + 1
    ELSE
        EXIT FOR
    END IF
NEXT
TheReturn = LEFT$(TheString, LEN(TheString) - n)
RemoveZerosRight$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReverseSign$ (TheStringIn AS STRING)
DIM Temp AS STRING
DIM TheString AS STRING
TheString = TheStringIn
Temp = ""
IF (LEFT$(TheString, 1) = "+") THEN
    Temp = RemoveCharacter$(TheString, 1)
    Temp = "-" + Temp
END IF
IF (LEFT$(TheString, 1) = "-") THEN
    Temp = RemoveCharacter$(TheString, 1)
    Temp = "+" + Temp
END IF
IF (Temp = "") THEN
    Temp = "-" + TheString
END IF
ReverseSign$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION SelectLargerInteger$ (Num1In AS STRING, Num2In AS STRING)
' Select the larger of two integers. The arguments must have no sign and no decimal.
DIM Num1 AS STRING
DIM Num2 AS STRING
DIM Temp AS STRING
DIM LenDiff AS INTEGER
DIM TempDiff AS INTEGER
DIM k AS INTEGER
Num1 = Num1In
Num2 = Num2In
Temp = ""
LenDiff = LEN(Num1) - LEN(Num2)
IF (LenDiff > 0) THEN
    Temp = "first"
END IF
IF (LenDiff < 0) THEN
    Temp = "second"
END IF
IF (LenDiff = 0) THEN
    FOR k = 1 TO LEN(Num1)
        TempDiff = VAL(ReadOneCharacter$(Num1, k)) - VAL(ReadOneCharacter$(Num2, k))
        IF (TempDiff <> 0) THEN
            IF (TempDiff > 0) THEN
                Temp = "first"
                EXIT FOR
            ELSE
                Temp = "second"
                EXIT FOR
            END IF
        END IF
    NEXT
END IF
IF (Temp = "") THEN
    Temp = "neither"
END IF
SelectLargerInteger$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RepairFormat$ (TheStringIn AS STRING)
' Repair the format of a number.
DIM Temp AS STRING
DIM NewSign AS STRING
DIM n AS INTEGER
DIM c AS STRING
DIM i AS INTEGER

Temp = TheStringIn

' Remove and store the sign if there is one.
NewSign = ""
IF (LEFT$(Temp, 1) = "+") THEN
    NewSign = "+"
    Temp = RemoveSign$(Temp)
END IF
IF (LEFT$(Temp, 1) = "-") THEN
    NewSign = "-"
    Temp = RemoveSign$(Temp)
END IF
IF (NewSign = "") THEN
    NewSign = "+"
END IF

' If the string has no decimal, place one at the end of the string.
IF (GetDecimalPos(Temp) = -1) THEN
    ' This can be made faster.
    Temp = InsertCharacter$(Temp, ".", LEN(Temp) + 1, 1)
END IF

' Remove unnecessary zeros on the left.
n = 0
FOR i = 1 TO LEN(Temp)
    c = ReadOneCharacter$(Temp, i)
    IF (c = "0") THEN
        n = n + 1
    ELSE
        EXIT FOR
    END IF
NEXT
Temp = RIGHT$(Temp, LEN(Temp) - n)

' Remove unnecessary zeros on the right.
n = 0
FOR i = LEN(Temp) TO 1 STEP -1
    c = ReadOneCharacter$(Temp, i)
    IF (c = "0") THEN
        n = n + 1
    ELSE
        EXIT FOR
    END IF
NEXT
Temp = LEFT$(Temp, LEN(Temp) - n)

' If last character is a decimal then add a zero to the right.
IF (RIGHT$(Temp, 1) = ".") THEN
    Temp = Temp + "0"
END IF

' If leading character is a decimal then insert a zero to the left.
IF (LEFT$(Temp, 1) = ".") THEN
    Temp = "0" + Temp
END IF

' Attach the sign on the left.
Temp = NewSign + Temp

IF (Temp = "-0.0") THEN
    Temp = "+0.0"
END IF

RepairFormat$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalAdd$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
DIM fac1 AS DOUBLE
DIM fac2 AS DOUBLE
DIM LenDiff AS INTEGER
DIM TempSwap AS STRING
DIM Temp1 AS STRING
DIM Temp2 AS STRING
DIM Oper AS STRING
DIM NewSign AS STRING
DIM ChunkSize AS INTEGER
DIM TheSum AS STRING
DIM Remainder AS INTEGER
DIM SubFactor AS INTEGER
DIM psum AS INTEGER
DIM PartialSum AS STRING
DIM TempDiff AS INTEGER
DIM TotalDecimalPlaces AS INTEGER
DIM k AS INTEGER
DIM j AS INTEGER
Num1 = Num1In
Num2 = Num2In

' Add zeros to the right of the decimal of the shorter partial string.
LenDiff = (LEN(Num1) - GetDecimalPos(Num1)) - (LEN(Num2) - GetDecimalPos(Num2))
IF (LenDiff > 0) THEN
    Num2 = InsertCharacter$(Num2, "0", LEN(Num2) + 1, LenDiff)
ELSE
    Num1 = InsertCharacter$(Num1, "0", LEN(Num1) + 1, -LenDiff)
END IF

' Force Num1 to be the number with the greatest magnitude.
LenDiff = LEN(Num1) - LEN(Num2)
IF (LenDiff < 0) THEN
    TempSwap = Num1
    Num1 = Num2
    Num2 = TempSwap
END IF
IF (LenDiff = 0) THEN
    Temp1 = RemoveDecimal$(Num1)
    Temp2 = RemoveDecimal$(Num2)
    Temp1 = RemoveSign$(Temp1)
    Temp2 = RemoveSign$(Temp2)
    FOR k = 1 TO LEN(Temp1)
        TempDiff = VAL(ReadOneCharacter$(Temp1, k)) - VAL(ReadOneCharacter$(Temp2, k))
        IF (TempDiff <> 0) THEN
            IF (TempDiff > 0) THEN
                EXIT FOR
            ELSE
                TempSwap = Num1
                Num1 = Num2
                Num2 = TempSwap
                EXIT FOR
            END IF
        END IF
    NEXT
END IF

'Add zeros to the left of Num2 to normalize lengths.
Num2 = InsertCharacter$(Num2, "0", 2, LEN(Num1) - LEN(Num2))

' Determine the sign of the result.
IF ((LEFT$(Num1, 1) = "+") AND (LEFT$(Num2, 1) = "+")) THEN
    Oper = "add"
    NewSign = "+"
END IF
IF ((LEFT$(Num1, 1) = "-") AND (LEFT$(Num2, 1) = "-")) THEN
    Oper = "add"
    NewSign = "-"
END IF
IF ((LEFT$(Num1, 1) = "+") AND (LEFT$(Num2, 1) = "-")) THEN
    Oper = "subtract"
    NewSign = "+"
END IF
IF ((LEFT$(Num1, 1) = "-") AND (LEFT$(Num2, 1) = "+")) THEN
    Oper = "subtract"
    NewSign = "-"
END IF

' Remove the leading sign from each string.
Num1 = RemoveSign$(Num1)
Num2 = RemoveSign$(Num2)

' Remove the decimal from each number after storing the total number of
' decimal places in a new variable (to be restored after the operation).
TotalDecimalPlaces = (LEN(Num1) - GetDecimalPos(Num1))
IF (TotalDecimalPlaces > 0) THEN
    Num1 = RemoveDecimal$(Num1)
    Num2 = RemoveDecimal$(Num2)
END IF

' Initialize internal addition and subtraction loop.
ChunkSize = 4
TheSum = ""
Remainder = 0

' This formula is nice but a hardcoded value is faster.
'SubFactor = VAL(InsertCharacter$("1", "0", 2, ChunkSize))
SubFactor = 10000

'''
FOR k = 1 TO ChunkSize - (LEN(Num1) MOD ChunkSize)
    Num1 = "0" + Num1
    Num2 = "0" + Num2
NEXT
'''

'IF (LEN(Num1) < ChunkSize) THEN
'    FOR k = 1 TO ChunkSize - LEN(Num1)
'        Num1 = "0" + Num1
'        Num2 = "0" + Num2
'    NEXT
'END IF

'IF (LEN(Num1) > ChunkSize) THEN
'    FOR k = 1 TO ChunkSize - (LEN(Num1) MOD ChunkSize)
'        Num1 = "0" + Num1
'        Num2 = "0" + Num2
'    NEXT
'END IF

'IF (LEN(Num1) > ChunkSize) THEN
DO WHILE ((LEN(Num1) MOD ChunkSize) <> 0)
    Num1 = "0" + Num1
    Num2 = "0" + Num2
LOOP
'END IF

' Execute internal addition and subtraction loop.

IF (Oper = "add") THEN
    FOR k = LEN(Num1) TO 1 STEP -ChunkSize
        fac1 = VAL(ReadManyCharacter$(Num1, k - ChunkSize + 1, k))
        fac2 = VAL(ReadManyCharacter$(Num2, k - ChunkSize + 1, k))
        psum = fac1 + fac2 + Remainder
        PartialSum = LTRIM$(RTRIM$(STR$(psum)))
        'FOR j = 1 TO ChunkSize - LEN(PartialSum)
        '    PartialSum = "0" + PartialSum
        'NEXT
        DO WHILE (LEN(PartialSum) < ChunkSize)
            PartialSum = "0" + PartialSum
        LOOP
        IF (LEN(PartialSum) = ChunkSize + 1) THEN
            Remainder = 1
            PartialSum = RemoveCharacter$(PartialSum, 1)
        ELSE
            Remainder = 0
        END IF
        TheSum = LEFT$(LTRIM$(PartialSum), ChunkSize) + TheSum
    NEXT
END IF

IF (Oper = "subtract") THEN
    FOR k = LEN(Num1) TO 1 STEP -ChunkSize
        fac1 = VAL(ReadManyCharacter$(Num1, k - ChunkSize + 1, k))
        fac2 = VAL(ReadManyCharacter$(Num2, k - ChunkSize + 1, k))
        psum = fac1 - fac2 + SubFactor - Remainder
        PartialSum = LTRIM$(STR$(psum))
        'FOR j = 1 TO ChunkSize - LEN(PartialSum)
        '    PartialSum = "0" + PartialSum
        'NEXT
        DO WHILE (LEN(PartialSum) < ChunkSize)
            PartialSum = "0" + PartialSum
        LOOP
        IF (LEN(PartialSum) > ChunkSize) THEN
            PartialSum = RemoveCharacter$(PartialSum, 1)
            Remainder = 0
        ELSE
            Remainder = 1
        END IF
        TheSum = LEFT$(LTRIM$(PartialSum), ChunkSize) + TheSum
    NEXT
END IF

' Correct the string format.
TheSum = RemoveSign$(TheSum)

' Restore the decimal point.
TheSum = InsertCharacter$(TheSum, ".", LEN(TheSum) - TotalDecimalPlaces + 1, 1)

' If the result ends in a decimal then fix the format.
IF (RIGHT$(TheSum, 1) = ".") THEN
    TheSum = TheSum + "0"
END IF

' Remove unnecessary zeros.
TheSum = RemoveZerosLeft$(TheSum, 1)

' If the result begins in a decimal then fix the format.
IF (LEFT$(TheSum, 1) = ".") THEN
    TheSum = "0" + TheSum
END IF

' Assign the proper sign to the result.
TheSum = NewSign + TheSum

InternalAdd$ = TheSum
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalSub$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
Num1 = Num1In
Num2 = Num2In
InternalSub$ = InternalAdd$(Num1, ReverseSign$(Num2))
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalMul$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
DIM Temp AS STRING
DIM NewSign AS STRING
DIM Prod AS STRING
DIM TheProd AS STRING
DIM TempMult AS STRING
DIM CarryOver AS INTEGER
DIM PresentDigit AS INTEGER
DIM TotalDecimalPlaces AS INTEGER
DIM WorkingDigit AS INTEGER
DIM tempswap AS STRING
DIM i AS INTEGER
DIM k AS INTEGER
DIM q AS INTEGER

Num1 = Num1In
Num2 = Num2In
Temp = ""

' Problem requires post-DOUBLE precision.
IF (Temp = "") THEN

    ' Remove unneessary zeros.
    Num1 = RemoveZerosRight$(Num1)
    Num2 = RemoveZerosRight$(Num2)

    ' Remove the decimal from each number after storing the total number of
    ' decimal places in a new variable (to be restored after the multiplication).
    TotalDecimalPlaces = (LEN(Num1) - GetDecimalPos(Num1)) + (LEN(Num2) - GetDecimalPos(Num2))
    Num1 = RemoveDecimal$(Num1)
    Num2 = RemoveDecimal$(Num2)

    ' Determine the sign of the result.
    IF ((LEFT$(Num1, 1) = "+") AND (LEFT$(Num2, 1) = "+")) THEN
        NewSign = "+"
    END IF
    IF ((LEFT$(Num1, 1) = "-") AND (LEFT$(Num2, 1) = "-")) THEN
        NewSign = "+"
    END IF
    IF ((LEFT$(Num1, 1) = "+") AND (LEFT$(Num2, 1) = "-")) THEN
        NewSign = "-"
    END IF
    IF ((LEFT$(Num1, 1) = "-") AND (LEFT$(Num2, 1) = "+")) THEN
        NewSign = "-"
    END IF

    ' Remove the leading sign from each string.
    Num1 = RemoveSign$(Num1)
    Num2 = RemoveSign$(Num2)

    ' Force Num1 to be the number with the greatest length.
    IF (LEN(Num2) > LEN(Num1)) THEN

        tempswap = Num1
        Num1 = Num2
        Num2 = tempswap
    END IF

    ' Add a zero to the left of each string.
    ' This is necessary when the length of the result surpasses that of the input.
    Num1 = "0" + Num1
    Num2 = "0" + Num2

    ' Initialize internal multiplication loop.
    TheProd = "+0.0"
    TempMult = ""
    CarryOver = 0

    ' Execute internal multiplication loop.
    FOR k = LEN(Num2) TO 1 STEP -1
        WorkingDigit = VAL(ReadOneCharacter$(Num2, k))
        TempMult = ""
        CarryOver = 0
        FOR i = LEN(Num1) TO 1 STEP -1
            PresentDigit = VAL(ReadOneCharacter$(Num1, i))
            Prod = STR$(PresentDigit * WorkingDigit + CarryOver)
            Prod = LTRIM$(RTRIM$(Prod))
            IF (LEN(Prod) = 1) THEN
                CarryOver = 0
                TempMult = Prod + TempMult
            END IF
            IF (LEN(Prod) = 2) THEN
                CarryOver = VAL(LEFT$(Prod, 1))
                TempMult = RIGHT$(Prod, 1) + TempMult
            END IF
        NEXT
        TempMult = RemoveZerosLeft$(TempMult, 1)

        IF (TempMult = "") THEN
            TempMult = "+0.0"
        ELSE
            TempMult = "+" + InsertCharacter$(TempMult, "0", LEN(TempMult) + 1, LEN(Num2) - k) + ".0"
        END IF
        TheProd = InternalAdd$(TheProd, TempMult)
    NEXT

    ' Correct the string format.
    TheProd = RemoveSign$(TheProd)
    TheProd = LEFT$(TheProd, LEN(TheProd) - 2)

    ' Restore the decimal point.
    IF (TotalDecimalPlaces > 0) THEN
        q = TotalDecimalPlaces - LEN(TheProd)
        IF (q >= 0) THEN
            TheProd = InsertCharacter$(TheProd, "0", 1, q)
            TheProd = "." + TheProd
        ELSE
            TheProd = InsertCharacter$(TheProd, ".", LEN(TheProd) - TotalDecimalPlaces + 1, 1)
        END IF
        TheProd = RemoveZerosRight$(TheProd)
        IF (RIGHT$(TheProd, 1) = ".") THEN
            TheProd = TheProd + "0"
        END IF
        IF (LEFT$(TheProd, 1) = ".") THEN
            TheProd = "0" + TheProd
        END IF
    ELSE
        TheProd = TheProd + ".0"
    END IF

    ' Assign the proper sign to the result.
    TheProd = NewSign + TheProd

    Temp = TheProd

END IF

InternalMul$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalInv$ (DenomIn AS STRING, NumDigitsIn AS INTEGER)
' The output of this function does not have fixed length. The output is made such that
' NumDigits only counts numerical character 0-9. The sign and decimal are ignored. The overall
' string length (zero between decimal and first sig-fig) is thus variable.
DIM Denom AS STRING
DIM NumDigits AS INTEGER
Denom = DenomIn
NumDigits = NumDigitsIn
DIM Temp AS STRING
DIM NewSign AS STRING
DIM Numerator AS STRING
DIM TempDiff AS STRING
DIM TempFactor AS STRING
DIM TheQuot AS STRING
DIM TotalDecimalPlaces AS INTEGER
DIM dpd AS INTEGER
DIM k AS INTEGER
DIM m AS INTEGER
DIM n AS INTEGER

Temp = ""

IF (RemoveSign$(Denom) = "0.0") THEN
    Temp = "ERROR: Division by zero detected in InternalInv."
END IF

IF (Temp = "") THEN

    ' Determine the sign of the result.
    IF (LEFT$(Denom, 1) = "+") THEN
        NewSign = "+"
    END IF
    IF (LEFT$(Denom, 1) = "-") THEN
        NewSign = "-"
    END IF

    'Remove the sign from the string.
    Denom = RemoveSign$(Denom)

    ' Remove leading zeros such that string is not of the format 00.000###
    ' but instead #.##
    m = 0
    DO WHILE (m > -1)
        IF ((LEFT$(Denom, 1) = ".") OR (LEFT$(Denom, 1) = "0")) THEN
            m = m + 1
            Denom = RemoveSign$(InternalMul$(Denom, "+10.0"))
        ELSE
            EXIT DO
        END IF
    LOOP

    ' Remove the decimal from the number after storing the total number of
    ' decimal places in a new variable (to be restored after the inversion).
    dpd = GetDecimalPos(Denom)
    TotalDecimalPlaces = LEN(Denom) - dpd
    Denom = RemoveDecimal$(Denom)

    ' Initialize internal inversion loop.
    Numerator = "+1.0"
    TheQuot = ""
    TempFactor = Numerator

    ' Execute internal inversion loop.
    FOR k = 1 TO NumDigits + TotalDecimalPlaces + dpd - 2
        ' ^ The "2" is compensation for the sign and decimal. ^
        n = 0
        DO WHILE (n > -1)
            'Check for a zero in the result.
            TempFactor = RemoveSign$(TempFactor)
            TempFactor = RemoveDecimal$(TempFactor)
            IF (SelectLargerInteger$(TempFactor, Denom) <> "first") THEN
                EXIT DO
            END IF

            TempDiff = InternalAdd$("+" + TempFactor + ".0", "-" + Denom + ".0")
            TempDiff = RemoveSign$(TempDiff)
            TempDiff = LEFT$(TempDiff, LEN(TempDiff) - 2)
            ' ^ Removes the ".0". ^
            n = n + 1
            TempFactor = TempDiff

            IF (SelectLargerInteger$(TempDiff, Denom) = "second") THEN
                EXIT DO
            END IF

        LOOP
        IF (k > 1) THEN
            TheQuot = TheQuot + LTRIM$(STR$(n))
        END IF
        TempFactor = TempFactor + "0"
    NEXT

    ' Insert the decimal into the string.
    TheQuot = InsertCharacter$(TheQuot, ".", TotalDecimalPlaces + m, 1)

    ' If string begins with a decimal then add a zero to the left.
    IF (LEFT$(TheQuot, 1) = ".") THEN
        TheQuot = "0" + TheQuot
    END IF

    ' Assign the proper sign to the result.
    TheQuot = NewSign + TheQuot

    Temp = TheQuot

END IF

InternalInv$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalDiv$ (NumerIn AS STRING, DenomIn AS STRING, NumDigitsIn AS INTEGER)
DIM Numer AS STRING
DIM Denom AS STRING
DIM NumDigits AS INTEGER
DIM Temp AS STRING
DIM Factor AS STRING
Numer = NumerIn
Denom = DenomIn
NumDigits = NumDigitsIn
Factor = InternalInv$(Denom, NumDigits)
IF (LEFT$(Factor, 5) <> "ERROR") THEN
    Temp = InternalMul$(Numer, Factor)
ELSE
    Temp = "ERROR: Division by zero passed to InternalDiv."
END IF
InternalDiv$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION STxAxTICAdd$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
Num1 = Num1In
Num2 = Num2In
Num1 = RepairFormat$(Num1)
Num2 = RepairFormat$(Num2)
STxAxTICAdd$ = InternalAdd$(Num1, Num2)
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION STxAxTICSub$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
Num1 = Num1In
Num2 = Num2In
Num1 = RepairFormat$(Num1)
Num2 = RepairFormat$(Num2)
STxAxTICSub$ = InternalAdd$(Num1, ReverseSign$(Num2))
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION STxAxTICMul$ (Num1In AS STRING, Num2In AS STRING)
DIM Num1 AS STRING
DIM Num2 AS STRING
Num1 = Num1In
Num2 = Num2In
Num1 = RepairFormat$(Num1)
Num2 = RepairFormat$(Num2)
STxAxTICMul$ = InternalMul$(Num1, Num2)
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION STxAxTICInv$ (DenomIn AS STRING, NumDigitsIn AS INTEGER)
DIM Denom AS STRING
DIM NumDigits AS INTEGER
Denom = RepairFormat$(DenomIn)
NumDigits = NumDigitsIn
STxAxTICInv$ = InternalInv$(Denom, NumDigits)
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION STxAxTICDiv$ (NumerIn AS STRING, DenomIn AS STRING, NumDigitsIn AS INTEGER)
DIM Numer AS STRING
DIM Denom AS STRING
DIM NumDigits AS INTEGER
DIM Temp AS STRING
DIM Factor AS STRING
Numer = RepairFormat$(NumerIn)
Denom = RepairFormat$(DenomIn)
NumDigits = NumDigitsIn
Factor = InternalInv$(Denom, NumDigits)
Temp = ""
IF (LEFT$(Factor, 5) <> "ERROR") THEN
    IF (Temp = "") THEN
        Temp = InternalMul$(Numer, Factor)
    END IF
ELSE
    Temp = "ERROR: Division by zero passed to STxAxTICDiv."
END IF
STxAxTICDiv$ = Temp
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION CountElements (TheStringIn AS STRING, TheSeparatorIn AS STRING)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM TheSeparator AS STRING
TheString = TheStringIn
TheSeparator = TheSeparatorIn
DIM c AS STRING
DIM k AS INTEGER
DIM BrackBal AS INTEGER
DIM QuoteBal AS INTEGER
BrackBal = 0
QuoteBal = 0
TheReturn = 1
FOR k = 1 TO LEN(TheString)
    c = MID$(TheString, k, 1)
    IF (c = "`") THEN
        QuoteBal = QuoteBal + 1
    END IF
    IF (c = "'") THEN
        QuoteBal = QuoteBal - 1
    END IF
    IF (QuoteBal = 0) THEN
        IF (INSTR("(<{[", c) > 0) THEN
            BrackBal = BrackBal + 1
        END IF
        IF (INSTR(")>}]", c) > 0) THEN
            BrackBal = BrackBal - 1
        END IF
        IF (BrackBal = 1) THEN
            IF (c = TheSeparator) THEN
                TheReturn = TheReturn + 1
            END IF
        END IF
    END IF
NEXT
CountElements = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION FindMatching (TheStringIn AS STRING, TheSymbolIn AS STRING, TheStartPosIn AS INTEGER)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM TheSymbol AS STRING
DIM TheStartPos AS INTEGER
TheString = TheStringIn
TheSymbol = TheSymbolIn
TheStartPos = TheStartPosIn
DIM c AS STRING
DIM d AS STRING
DIM k AS INTEGER
DIM ClosingSymbol AS STRING
DIM TheDirection AS INTEGER
DIM TheEndPos AS INTEGER
DIM BrackBal AS INTEGER
DIM QuoteBal AS INTEGER
ClosingSymbol = ""
TheDirection = 0
BrackBal = 0
QuoteBal = 0
TheEndPos = 0
TheReturn = -1
c = "`(<{["
d = "')>}]"

k = INSTR(c, TheSymbol)
IF (k > 0) THEN
    ClosingSymbol = MID$(d, k, 1)
    TheDirection = 1
    TheEndPos = LEN(TheString)
END IF

k = INSTR(d, TheSymbol)
IF (k > 0) THEN
    ClosingSymbol = MID$(c, k, 1)
    TheDirection = -1
    TheEndPos = 1
END IF

k = TheStartPos
DO WHILE (1 = 1)
    c = MID$(TheString, k, 1)
    IF (c = "`") THEN
        QuoteBal = QuoteBal + 1
    END IF
    IF (c = "'") THEN
        QuoteBal = QuoteBal - 1
    END IF
    IF (QuoteBal = 0) THEN
        IF (INSTR("(<{[", c) > 0) THEN
            BrackBal = BrackBal + 1
        END IF
        IF (INSTR(")>}]", c) > 0) THEN
            BrackBal = BrackBal - 1
        END IF
        IF (BrackBal = 0) THEN
            IF (c = ClosingSymbol) THEN
                TheReturn = k
                EXIT DO
            END IF
        END IF
    END IF
    IF (k = TheEndPos) THEN
        EXIT DO
    END IF
    k = k + TheDirection
    IF (k = TheStartPos) THEN
        EXIT DO
    END IF
LOOP
FindMatching = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION FindMostEmbedded (TheStringIn AS STRING)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM MainBal AS INTEGER
DIM QuoteBal AS INTEGER
DIM AltBal AS INTEGER
DIM MainCrit AS INTEGER
DIM LeftPos AS INTEGER
DIM k AS INTEGER
DIM c AS STRING
TheString = TheStringIn
TheReturn = 0
MainBal = 0
QuoteBal = 0
AltBal = 0
MainCrit = 0
LeftPos = -1
IF ((INSTR(TheString, "(") > 0) AND (INSTR(TheString, ")") > 0)) THEN
    FOR k = 1 TO LEN(TheString)
        c = MID$(TheString, k, 1)
        IF (c = "`") THEN
            QuoteBal = QuoteBal + 1
        END IF
        IF (c = "'") THEN
            QuoteBal = QuoteBal - 1
        END IF
        IF (QuoteBal = 0) THEN
            IF (INSTR("<{[", c) > 0) THEN
                AltBal = AltBal + 1
            END IF
            IF (INSTR(">}]", c) > 0) THEN
                AltBal = AltBal - 1
            END IF
            IF (AltBal = 0) THEN
                IF (c = "(") THEN
                    MainBal = MainBal + 1
                    IF (MainBal > MainCrit) THEN
                        MainCrit = MainBal
                        LeftPos = k
                    END IF
                END IF
                IF (c = ")") THEN
                    MainBal = MainBal - 1
                END IF
            END IF
        END IF
    NEXT
    TheReturn = LeftPos
ELSE
    TheReturn = -1
END IF
FindMostEmbedded = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION GetSeparatorPos (TheStringIn AS STRING, TheSeparatorTypeIn AS STRING, TheSeparatorNumIn AS INTEGER, TheStartPosIn AS INTEGER)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM TheSeparatorType AS STRING
DIM TheSeparatorNum AS INTEGER
DIM TheStartPos AS INTEGER
DIM c AS STRING
DIM k AS INTEGER
DIM BrackBal AS INTEGER
DIM QuoteBal AS INTEGER
DIM SepCounter AS INTEGER
DIM BrackConst AS INTEGER
TheString = TheStringIn
TheSeparatorType = TheSeparatorTypeIn
TheSeparatorNum = TheSeparatorNumIn
TheStartPos = TheStartPosIn
BrackBal = 0
QuoteBal = 0
SepCounter = 0
TheReturn = -1
IF (TheStartPos > 1) THEN
    BrackConst = 0
    TheSeparatorNum = 1
ELSE
    BrackConst = 1
END IF
IF (INSTR(TheString, TheSeparatorType) > 0) THEN
    FOR k = TheStartPos TO LEN(TheString)
        c = MID$(TheString, k, 1)
        IF (c = "`") THEN
            QuoteBal = QuoteBal + 1
        END IF
        IF (c = "'") THEN
            QuoteBal = QuoteBal - 1
        END IF
        IF (QuoteBal = 0) THEN
            IF (INSTR("(<{[", c) > 0) THEN
                BrackBal = BrackBal + 1
            END IF
            IF (INSTR(")>}]", c) > 0) THEN
                BrackBal = BrackBal - 1
            END IF
            IF (BrackBal = BrackConst) THEN
                IF (c = TheSeparatorType) THEN
                    SepCounter = SepCounter + 1
                    IF (SepCounter = TheSeparatorNum) THEN
                        TheReturn = k
                        EXIT FOR
                    END IF
                END IF
            END IF
        END IF
    NEXT
END IF
GetSeparatorPos = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ManageWhiteSpace$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM QuoteBal AS INTEGER
DIM k AS INTEGER
DIM c AS STRING
TheString = TheStringIn
TheReturn = ""
QuoteBal = 0
IF ((INSTR(TheString, " ") > 0) OR (INSTR(TheString, CHR$(9)) > 0) OR (INSTR(TheString, CHR$(10)) > 0) OR (INSTR(TheString, CHR$(13)) > 0)) THEN
    FOR k = 1 TO LEN(TheString)
        c = MID$(TheString, k, 1)
        IF (c = "`") THEN
            QuoteBal = QuoteBal + 1
        END IF
        IF (c = "'") THEN
            QuoteBal = QuoteBal - 1
        END IF
        IF (QuoteBal = 0) THEN
            IF ((c <> " ") AND (c <> CHR$(9)) AND (c <> CHR$(10)) AND (c <> CHR$(13))) THEN
                TheReturn = TheReturn + c
            END IF
        ELSE
            TheReturn = TheReturn + c
        END IF
    NEXT
ELSE
    TheReturn = TheString
END IF
ManageWhiteSpace$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION RemoveWrapping$ (TheStringIn AS STRING, TheWrapIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheWrap AS STRING
DIM TheWidth AS INTEGER
TheString = TheStringIn
TheWrap = TheWrapIn
TheReturn = TheString
TheWidth = LEN(TheWrap) / 2
IF (TheWrap <> "") THEN
    IF (LEFT$(TheString, TheWidth) = LEFT$(TheWrap, TheWidth)) THEN
        IF (RIGHT$(TheReturn, TheWidth) = RIGHT$(TheWrap, TheWidth)) THEN
            TheReturn = RIGHT$(TheReturn, LEN(TheReturn) - TheWidth)
            TheReturn = LEFT$(TheReturn, LEN(TheReturn) - TheWidth)
        END IF
    END IF
END IF
RemoveWrapping$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReplaceWord$ (TheStringIn AS STRING, TheWordIn AS STRING, TheReplacementIn AS STRING, CurlyDepthIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheWord AS STRING
DIM TheReplacement AS STRING
DIM CurlyDepth AS INTEGER
DIM QuoteBal AS INTEGER
DIM CurlyBal AS INTEGER
DIM k AS INTEGER
DIM c AS STRING
TheString = TheStringIn
TheWord = TheWordIn
TheReplacement = TheReplacementIn
CurlyDepth = CurlyDepthIn
TheReturn = TheString
IF (INSTR(TheReturn, TheWord) > 0) THEN
    QuoteBal = 0
    CurlyBal = 0
    FOR k = 1 TO LEN(TheReturn) - LEN(TheWord) + 1
        c = MID$(TheReturn, k, 1)
        IF (c = "`") THEN
            QuoteBal = QuoteBal + 1
        END IF
        IF (c = "'") THEN
            QuoteBal = QuoteBal - 1
        END IF
        IF (QuoteBal = 0) THEN
            IF (CurlyDepth > -1) THEN
                IF (c = "{") THEN
                    CurlyBal = CurlyBal + 1
                END IF
                IF (c = "}") THEN
                    CurlyBal = CurlyBal - 1
                END IF
            ELSE
                CurlyBal = CurlyDepth
            END IF
            IF (CurlyBal = CurlyDepth) THEN
                c = MID$(TheReturn, k, LEN(TheWord))
                IF (c = TheWord) THEN
                    TheReturn = LEFT$(TheReturn, k - 1) + TheReplacement + RIGHT$(TheReturn, LEN(TheReturn) - k - LEN(TheWord) + 1)
                    EXIT FOR
                END IF
            END IF
        END IF
    NEXT
END IF
IF ((INSTR(TheReturn, TheWord) > 0) AND (TheReturn <> TheString)) THEN
    TheReturn = ReplaceWord$(TheReturn, TheWord, TheReplacement, CurlyDepth)
END IF
ReplaceWord$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReplaceRaw$ (TheStringIn AS STRING, TheWordIn AS STRING, TheReplacementIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheWord AS STRING
DIM TheReplacement AS STRING
DIM k AS INTEGER
DIM c AS STRING
TheString = TheStringIn
TheWord = TheWordIn
TheReplacement = TheReplacementIn
TheReturn = TheString
IF (INSTR(TheReturn, TheWord) > 0) THEN
    FOR k = 1 TO LEN(TheReturn) - LEN(TheWord) + 1
        c = MID$(TheReturn, k, LEN(TheWord))
        IF (c = TheWord) THEN
            TheReturn = LEFT$(TheReturn, k - 1) + TheReplacement + RIGHT$(TheReturn, LEN(TheReturn) - k - LEN(TheWord) + 1)
            EXIT FOR
        END IF
    NEXT
END IF
IF ((INSTR(TheReturn, TheWord) > 0) AND (TheReturn <> TheString)) THEN
    TheReturn = ReplaceRaw$(TheReturn, TheWord, TheReplacement)
END IF
ReplaceRaw$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ScanForName (TheStringIn AS STRING, TheCritPosIn AS INTEGER, TheSwitchIn AS STRING)
' Returns the position of the beginning of a word or function name or number.
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM TheSwitch AS STRING
DIM TheCritPos AS INTEGER
DIM TheNaughtyList AS STRING
DIM c AS STRING
DIM k AS INTEGER
DIM j AS INTEGER
TheString = TheStringIn
TheSwitch = TheSwitchIn
TheCritPos = TheCritPosIn
TheNaughtyList = BrackList + OpList
TheReturn = -1
IF (TheSwitch = "left") THEN
    FOR k = TheCritPos - 1 TO 1 STEP -1
        c = MID$(TheString, k, 1)
        FOR j = 1 TO LEN(TheNaughtyList)
            IF (c = MID$(TheNaughtyList, j, 1)) THEN
                TheReturn = k + 1
                EXIT FOR
            END IF
        NEXT
        IF (TheReturn > -1) THEN
            EXIT FOR
        END IF
    NEXT
    IF (TheReturn = -1) THEN
        TheReturn = 1
    END IF
END IF
IF (TheSwitch = "right") THEN
    FOR k = TheCritPos + 1 TO LEN(TheString)
        c = MID$(TheString, k, 1)
        FOR j = 1 TO LEN(TheNaughtyList)
            IF (c = MID$(TheNaughtyList, j, 1)) THEN
                TheReturn = k - 1
            END IF
        NEXT
        IF (TheReturn > -1) THEN
            EXIT FOR
        END IF
    NEXT
    IF (TheReturn = -1) THEN
        TheReturn = LEN(TheString)
    END IF
END IF
ScanForName = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ScanForOperator (TheStringIn AS STRING, TheSymbolIn AS STRING)
DIM TheReturn AS INTEGER
DIM TheString AS STRING
DIM TheSymbol AS STRING
TheString = TheStringIn
TheSymbol = TheSymbolIn
DIM BrackBal AS INTEGER
DIM QuoteBal AS INTEGER
DIM k AS INTEGER
DIM c AS STRING
BrackBal = 0
QuoteBal = 0
TheReturn = -1
IF (INSTR(TheString, TheSymbol) > 0) THEN
    FOR k = LEN(TheString) TO 1 STEP -1
        c = MID$(TheString, k, 1)
        IF (c = "`") THEN
            QuoteBal = QuoteBal + 1
        END IF
        IF (c = "'") THEN
            QuoteBal = QuoteBal - 1
        END IF
        IF (QuoteBal = 0) THEN
            IF (INSTR("(<{[", c) > 0) THEN
                BrackBal = BrackBal + 1
            END IF
            IF (INSTR(")>}]", c) > 0) THEN
                BrackBal = BrackBal - 1
            END IF
            IF (BrackBal = 0) THEN
                c = "_yes"
                IF (MID$(TheString, k, LEN(TheSymbol)) = TheSymbol) THEN
                    ' Prevents leading "+" and "-" signs from causing false triggers.
                    IF ((TheSymbol = "+") OR (TheSymbol = "-")) THEN
                        IF (k = 1) THEN
                            c = "_no"
                        END IF
                    END IF
                    IF (k > 1) THEN
                        IF (INSTR(OpList, MID$(TheString, k - 1, 1)) > 0) THEN
                            c = "_no"
                        END IF
                    END IF
                    IF (c = "_yes") THEN
                        TheReturn = k
                        EXIT FOR
                    END IF
                END IF
            END IF
        END IF
    NEXT
END IF
ScanForOperator = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION TypeCheck$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn
IF (LEN(TheString) > 1) THEN
    TheString = LEFT$(TheString, 1)
END IF
TheReturn = ""
IF (TheReturn = "") THEN
    IF (INSTR("+-.0123456789", TheString) > 0) THEN
        TheReturn = "number"
    END IF
END IF
IF (TheReturn = "") THEN
    IF (INSTR("()", TheString) > 0) THEN
        TheReturn = "paren"
    END IF
    IF (INSTR("`'", TheString) > 0) THEN
        TheReturn = "quote"
    END IF
    IF (INSTR("<>", TheString) > 0) THEN
        TheReturn = "vector"
    END IF
    IF (INSTR("{}", TheString) > 0) THEN
        TheReturn = "occult"
    END IF
    IF (INSTR("[]", TheString) > 0) THEN
        TheReturn = "symbol"
    END IF
    IF (TheString = ",") THEN
        TheReturn = "separator"
    END IF
END IF
IF (TheReturn = "") THEN
    TheReturn = "word"
END IF
TypeCheck$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ManageOperators$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn
TheReturn = TheString
TheReturn = ReplaceWord$(TheReturn, "^^", "^", -1)
TheReturn = ReplaceWord$(TheReturn, "^+", "^", -1)
TheReturn = ReplaceWord$(TheReturn, "**", "*", -1)
TheReturn = ReplaceWord$(TheReturn, "*+", "*", -1)
TheReturn = ReplaceWord$(TheReturn, "/+", "/", -1)
TheReturn = ReplaceWord$(TheReturn, "++", "+", -1)
TheReturn = ReplaceWord$(TheReturn, "+-", "-", -1)
TheReturn = ReplaceWord$(TheReturn, "-+", "-", -1)
TheReturn = ReplaceWord$(TheReturn, "--", "+", -1)

' For QB64:
TheReturn = ReplaceWord$(TheReturn, "D+", "Dp", -1)
TheReturn = ReplaceWord$(TheReturn, "D-", "Dm", -1)
' For FreeBASIC:
TheReturn = ReplaceWord$(TheReturn, "e+", "Ep", -1)
TheReturn = ReplaceWord$(TheReturn, "e-", "Em", -1)
' For Wine:
TheReturn = ReplaceWord$(TheReturn, "DE", "00", -1)

IF (TheReturn <> TheString) THEN
    TheReturn = ManageOperators$(TheReturn)
END IF
ManageOperators$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION ReturnElement$ (TheStringIn AS STRING, TheArgNumberIn AS INTEGER)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TheArgNumber AS INTEGER
DIM n AS INTEGER
DIM m AS INTEGER
TheString = TheStringIn
TheArgNumber = TheArgNumberIn
TheReturn = "_null"
n = CountElements(TheString, ",")
' If seeking first argument:
IF (TheReturn = "_null") THEN
    IF (TheArgNumber = 1) THEN
        IF (n = 1) THEN
            TheReturn = RemoveWrapping$(TheString, "<>")
        END IF
        IF (n > 1) THEN
            TheReturn = TheString
            TheReturn = LEFT$(TheReturn, GetSeparatorPos(TheReturn, ",", 1, 1) - 1)
            TheReturn = RIGHT$(TheReturn, LEN(TheReturn) - 1)
        END IF
    END IF
END IF
' If seeking last argument:
IF (TheReturn = "_null") THEN
    IF (TheArgNumber = n) THEN
        TheReturn = TheString
        TheReturn = RIGHT$(TheReturn, LEN(TheReturn) - GetSeparatorPos(TheReturn, ",", n - 1, 1))
        TheReturn = LEFT$(TheReturn, LEN(TheReturn) - 1)
    END IF
END IF
' Must have three or more arguments:
IF (TheReturn = "_null") THEN
    TheReturn = TheString
    n = GetSeparatorPos(TheReturn, ",", TheArgNumber - 1, 1)
    m = GetSeparatorPos(TheReturn, ",", TheArgNumber, n + 1)
    TheReturn = MID$(TheReturn, n + 1, (m - n) - 1)
END IF
ReturnElement$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION VectorASMD$ (Vector1In AS STRING, Vector2In AS STRING, TheOperatorIn AS STRING)
DIM TheReturn AS STRING
DIM Vector1 AS STRING
DIM Vector2 AS STRING
DIM TheOperator AS STRING
DIM size AS INTEGER
DIM size2 AS INTEGER
DIM k AS INTEGER
Vector1 = Vector1In
Vector2 = Vector2In
TheOperator = TheOperatorIn
size = CountElements(Vector1, ",")
size2 = CountElements(Vector2, ",")
IF (size <> size2) THEN
    TheReturn = "ERROR:`Unequal dimensions sent to VectorASMD.'"
ELSE
    TheReturn = "<"
    FOR k = 1 TO size
        TheReturn = TheReturn + "(" + ReturnElement$(Vector1, k) + " " + TheOperator + " " + ReturnElement$(Vector2, k) + ")"
        IF (k < size) THEN
            TheReturn = TheReturn + ","
        END IF
    NEXT
    TheReturn = TheReturn + ">"
END IF
VectorASMD$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION InternalEval$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn

TheString = ManageWhiteSpace$(TheString)

TheReturn = ""
DO WHILE (TheString <> TheReturn)
    TheReturn = TheString
    TheString = EvalStep$(TheString)
LOOP
TheReturn = TheString

InternalEval$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION StructureEval$ (TheVectorIn AS STRING, TheLeftBrackIn AS STRING, TheRightBrackIn AS STRING)
DIM TheReturn AS STRING
DIM TheVector AS STRING
DIM TheLeftBrack AS STRING
DIM TheRightBrack AS STRING
DIM c AS STRING
DIM c1 AS STRING
DIM c2 AS STRING
DIM d AS STRING
DIM k AS INTEGER
TheVector = TheVectorIn
TheLeftBrack = TheLeftBrackIn
TheRightBrack = TheRightBrackIn
d = ""
k = FindMatching(TheVector, TheLeftBrack, 1)
c1 = LEFT$(TheVector, k)
c1 = RemoveWrapping$(c1, TheLeftBrack + TheRightBrack)
c2 = RIGHT$(TheVector, LEN(TheVector) - k)
DO WHILE (1 = 1)
    k = GetSeparatorPos(TheLeftBrack + c1 + TheRightBrack, ",", 1, 1) - 1
    IF (k > -1) THEN
        c = LEFT$(c1, k - 1)
        c = InternalEval$(c)
        d = d + c + ","
        c1 = RIGHT$(c1, LEN(c1) - k)
    ELSE
        c = c1
        c = InternalEval$(c)
        d = d + c
        EXIT DO
    END IF
LOOP
d = TheLeftBrack + d + TheRightBrack
TheReturn = d + InternalEval$(c2)
StructureEval$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION PlotASCII$ (TheFuncIn AS STRING, LowLimitIn AS DOUBLE, HighLimitIn AS DOUBLE, StepSizeIn AS DOUBLE)
DIM TheReturn AS STRING
DIM TheFunc AS STRING
DIM LowLimit AS DOUBLE
DIM HighLimit AS DOUBLE
DIM StepSize AS DOUBLE
TheFunc = TheFuncIn
LowLimit = LowLimitIn
HighLimit = HighLimitIn
StepSize = StepSizeIn
DIM WindowHeight AS INTEGER
DIM WindowWidth AS INTEGER
DIM j AS DOUBLE
DIM k AS INTEGER
DIM n AS INTEGER
DIM NumPoints AS INTEGER
DIM tmp AS STRING
DIM ymin AS DOUBLE
DIM ymax AS DOUBLE
DIM xave AS DOUBLE
DIM yave AS DOUBLE
DIM xzoom AS DOUBLE
DIM yzoom AS DOUBLE
DIM xtext AS INTEGER
DIM ytext AS INTEGER
DIM x AS DOUBLE
DIM y AS DOUBLE

NumPoints = 1 + (HighLimit - LowLimit) / (StepSize)
DIM PointArrayX(NumPoints) AS DOUBLE
DIM PointArrayY(NumPoints) AS DOUBLE

WindowWidth = 45
WindowHeight = 18

DIM AsciiPlane(WindowWidth, WindowHeight) AS STRING

' CPP: STARTSKIP
'\\for (k = 1; k <= WindowWidth; k += 1) {
'\\    AsciiPlane[k] = new Array(WindowHeight);
'\\}
' CPP: ENDSKIP

FOR k = 1 TO WindowHeight
    FOR n = 1 TO WindowWidth
        AsciiPlane(n, k) = "_"
    NEXT
NEXT

ymin = 999999
ymax = -999999
k = 0
FOR j = LowLimit TO HighLimit STEP StepSize
    tmp = TheFunc + "(" + LTRIM$(RTRIM$(STR$(j))) + ")"
    tmp = InternalEval$(tmp)
    y = VAL(tmp)
    IF (y > ymax) THEN
        ymax = y
    END IF
    IF (y < ymin) THEN
        ymin = y
    END IF
    k = k + 1
    PointArrayX(k) = j
    PointArrayY(k) = y
NEXT

yave = (1 / 2) * (ymax + ymin)
xave = (1 / 2) * (HighLimit + LowLimit)
yzoom = (0.85 + 0.15) * ABS((WindowHeight) / (ymax - ymin))
xzoom = (0.85 + 0.15) * ABS((WindowWidth) / (HighLimit - LowLimit))
FOR k = 1 TO NumPoints
    x = PointArrayX(k)
    y = PointArrayY(k)
    x = (x - xave) * xzoom
    y = (y - yave) * yzoom
    xtext = INT(x + WindowWidth / 2)
    ytext = INT(WindowHeight / 2 - y)
    tmp = "*"
    IF (xtext < 1) THEN
        tmp = "<"
        xtext = 1
    END IF
    IF (xtext > WindowWidth) THEN
        tmp = ">"
        xtext = WindowWidth
    END IF
    IF (ytext < 1) THEN
        tmp = "^"
        ytext = 1
    END IF
    IF (ytext > WindowHeight) THEN
        tmp = "."
        ytext = WindowHeight
    END IF
    AsciiPlane(xtext, ytext) = tmp
NEXT

FOR k = 1 TO FunctionUserListSize
    IF (TheFunc = FunctionUserList(k, 1)) THEN
        TheFunc = FunctionUserList(k, 2)
    END IF
NEXT

TheReturn = "`"
TheReturn = TheReturn + CHR$(10)
TheReturn = TheReturn + "Plotting:  " + TheFunc + "  (step " + LTRIM$(RTRIM$(STR$(StepSize))) + ")"
TheReturn = TheReturn + CHR$(10)
FOR k = 1 TO WindowHeight
    tmp = ""
    FOR n = 1 TO WindowWidth
        TheReturn = TheReturn + AsciiPlane(n, k)
    NEXT
    TheReturn = TheReturn + STR$(ymax - ((k - 1) / WindowHeight) * (ymax - ymin) * (WindowHeight / (WindowHeight - 1)))
    IF (k < WindowHeight) THEN
        TheReturn = TheReturn + CHR$(10)
    END IF
NEXT
tmp = ""
tmp = tmp + LTRIM$(RTRIM$(STR$(LowLimit))) + " "
DO WHILE (LEN(tmp) < WindowWidth / 2 - 2)
    tmp = tmp + "|"
LOOP
tmp = tmp + " " + LTRIM$(RTRIM$(STR$(xave))) + " "
DO WHILE (LEN(tmp) < WindowWidth - 2)
    tmp = tmp + "|"
LOOP
tmp = tmp + " " + LTRIM$(RTRIM$(STR$(HighLimit)))
TheReturn = TheReturn + CHR$(10)
TheReturn = TheReturn + tmp
TheReturn = TheReturn + CHR$(10)
TheReturn = TheReturn + "'"
PlotASCII$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION StructureApplyFunc$ (TheVectorIn AS STRING, TheFunctionIn AS STRING, TheBracketsIn AS STRING)
DIM TheReturn AS STRING
DIM TheVector AS STRING
DIM TheFunction AS STRING
DIM TheBrackets AS STRING
DIM size AS INTEGER
TheVector = TheVectorIn
TheFunction = TheFunctionIn
TheBrackets = TheBracketsIn
DIM k AS INTEGER
TheReturn = LEFT$(TheBrackets, 1)
size = CountElements(TheVector, ",")
FOR k = 1 TO size
    TheReturn = TheReturn + TheFunction + "(" + ReturnElement$(TheVector, k) + ")"
    IF (k < size) THEN
        TheReturn = TheReturn + ","
    END IF
NEXT
TheReturn = TheReturn + RIGHT$(TheBrackets, 1)
StructureApplyFunc$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION FormatForTerminal$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn

TheString = ReplaceRaw$(TheString, "';`", "'")

TheString = ReplaceWord$(TheString, ";_", " ", -1)
TheString = ReplaceWord$(TheString, ";t", CHR$(9), -1)
TheString = ReplaceWord$(TheString, ";n", CHR$(10), -1)
TheString = ReplaceWord$(TheString, ";m", CHR$(13), -1)
TheString = ReplaceWord$(TheString, ";p", "(", -1)
TheString = ReplaceWord$(TheString, ";q", ")", -1)
TheString = ReplaceWord$(TheString, ";c", ",", -1)

TheString = ReplaceWord$(TheString, "Dp", "D+", -1)
TheString = ReplaceWord$(TheString, "Dm", "D-", -1)
TheString = ReplaceWord$(TheString, "Ep", "e+", -1)
TheString = ReplaceWord$(TheString, "Em", "e-", -1)

TheReturn = TheString
FormatForTerminal$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION EvalStep$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM LeftBrackPos AS INTEGER
DIM RightBrackPos AS INTEGER
DIM ScannedNameStart AS INTEGER
DIM ScannedName AS STRING
DIM ScannedNameFound AS STRING
DIM LeftFragment AS STRING
DIM MidFragment AS STRING
DIM RightFragment AS STRING
DIM k AS INTEGER
DIM n AS INTEGER
DIM m AS INTEGER
DIM t AS DOUBLE
DIM z AS DOUBLE
DIM c AS STRING
DIM d AS STRING
DIM e AS STRING
DIM c1 AS STRING
DIM c2 AS STRING
TheString = TheStringIn
TheReturn = ""
LeftBrackPos = -1
RightBrackPos = -1
ScannedNameStart = -1
ScannedName = ""
ScannedNameFound = "_no"
LeftFragment = ""
MidFragment = ""
RightFragment = ""

IF (TheReturn = "") THEN
    IF (LEFT$(TheString, 5) = "ERROR") THEN
        TheReturn = TheString
    END IF
END IF

'''PRINT "E: "; TheString
'''OPEN "parse.txt" FOR APPEND AS #1
'''PRINT #1, TheString
'''CLOSE #1

' Scan for most-embedded structure and break the input string into fragments.
IF (TheReturn = "") THEN
    LeftBrackPos = FindMostEmbedded(TheString)
    IF (LeftBrackPos > -1) THEN
        RightBrackPos = FindMatching(TheString, "(", LeftBrackPos)
    ELSE
        MidFragment = TheString
    END IF
    IF (RightBrackPos > -1) THEN
        MidFragment = MID$(TheString, LeftBrackPos, (RightBrackPos - LeftBrackPos) + 1)
        RightFragment = RIGHT$(TheString, LEN(TheString) - RightBrackPos)
        ScannedNameStart = ScanForName(TheString, LeftBrackPos, "left")
        IF (ScannedNameStart <> LeftBrackPos) THEN
            LeftFragment = LEFT$(TheString, ScannedNameStart - 1)
            ScannedName = MID$(TheString, ScannedNameStart, (LeftBrackPos - ScannedNameStart))
        ELSE
            LeftFragment = LEFT$(TheString, LeftBrackPos - 1)
        END IF
    END IF
END IF

'
' Input expression contains no zero-level parens.
'
IF ((LeftBrackPos = -1) AND (RightBrackPos = -1) AND (ScannedName = "")) THEN

    ' Replace variables.
    IF (TheReturn = "") THEN
        c = TheString
        FOR k = 1 TO VariableUserListSize
            c = ReplaceWord$(c, "[" + VariableUserList(k, 1) + "]", "(" + VariableUserList(k, 2) + ")", 0)
            c = ReplaceWord$(c, "[(" + VariableUserList(k, 1) + ")]", "(" + VariableUserList(k, 2) + ")", 0)
            c = ReplaceWord$(c, "{" + VariableUserList(k, 1) + "}", "(" + VariableUserList(k, 2) + ")", 2)
            c = ReplaceWord$(c, "{" + VariableUserList(k, 1) + "}", "(" + VariableUserList(k, 2) + ")", 3)
            c = ReplaceWord$(c, "{" + VariableUserList(k, 1) + "}", "(" + VariableUserList(k, 2) + ")", 4)
        NEXT
        IF (c <> TheString) THEN
            TheReturn = c
        END IF
    END IF

    ' Pass through the number cruncher.
    IF (TheReturn = "") THEN
        d = TheString
        c = ""
        DO WHILE (TheString <> c)
            c = TheString
            TheString = NumberCrunch$(TheString)
        LOOP
        c = TheString
        IF (c = d) THEN
            TheReturn = ""
        ELSE
            TheReturn = c
        END IF
    END IF

    ' Pass through the vector evaluator.
    IF (TheReturn = "") THEN
        c = TheString
        IF (TypeCheck$(c) = "vector") THEN
            d = c
            c = StructureEval$(c, "<", ">")
        END IF
        IF (c = d) THEN
            TheReturn = ""
        ELSE
            TheReturn = c
        END IF
    END IF

END IF

'
' Input expression contains zero-level parens but no scanned function name.
'
IF ((LeftBrackPos > -1) AND (RightBrackPos > -1) AND (ScannedName = "")) THEN

    ' Evaluate parenthesized lists and any single elements.
    IF (TheReturn = "") THEN
        n = CountElements(MidFragment, ",")
        IF (n = 1) THEN
            ' Single arguments lose their parens.
            c = RemoveWrapping$(MidFragment, "()")
            c = InternalEval$(c)
            MidFragment = c
            TheReturn = LeftFragment + MidFragment + RightFragment
        END IF
        IF (n > 1) THEN
            ' Lists remain as lists.
            c = StructureEval$(MidFragment, "(", ")")
            MidFragment = c
            TheReturn = LeftFragment + MidFragment + RightFragment
        END IF
    END IF

END IF

'
' Input expression contains parens and a name was scanned.
'
IF ((LeftBrackPos > -1) AND (RightBrackPos > -1) AND (ScannedName <> "")) THEN

    ' Check if scanned name is a user-defined function.
    IF (TheReturn = "") THEN
        '''
        m = CountElements(MidFragment, ",")
        '''
        FOR k = FunctionUserListSize TO 1 STEP -1
            IF (ScannedName = FunctionUserList(k, 1)) THEN
                c = FunctionUserList(k, 2)
                c = RemoveWrapping$(c, "{}")

                IF (m > 0) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 1))
                    c = ReplaceWord$(c, "[x]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[x]", "(" + d + ")", 1)
                END IF

                IF (m > 1) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 2))
                    c = ReplaceWord$(c, "[y]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[y]", "(" + d + ")", 1)
                END IF

                IF (m > 2) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 3))
                    c = ReplaceWord$(c, "[z]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[z]", "(" + d + ")", 1)
                END IF

                IF (m > 3) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 4))
                    c = ReplaceWord$(c, "[t]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[t]", "(" + d + ")", 1)
                END IF

                IF (m > 4) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 5))
                    c = ReplaceWord$(c, "[u]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[u]", "(" + d + ")", 1)
                END IF

                IF (m > 5) THEN
                    d = InternalEval$(ReturnElement$(MidFragment, 6))
                    c = ReplaceWord$(c, "[v]", "(" + d + ")", 0)
                    c = ReplaceWord$(c, "[v]", "(" + d + ")", 1)
                END IF

                MidFragment = c
                TheReturn = LeftFragment + MidFragment + RightFragment
                EXIT FOR
            END IF
        NEXT
    END IF

    ' Check if scanned name is a primitive.
    IF (TheReturn = "") THEN

        ' Evaluate argument list.
        MidFragment = InternalEval$(MidFragment)

        '
        ' Variables:
        '

        IF (ScannedName = "let") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            c = RemoveWrapping$(c, "`'")
            d = ReturnElement$(MidFragment, 2)
            IF (CountElements(MidFragment, ",") = 3) THEN
                n = VAL(ReturnElement$(MidFragment, 3))
                VariableUserList(n, 1) = c
                VariableUserList(n, 2) = d
                MidFragment = d
            ELSE
                FOR k = 1 TO VariableUserListSize
                    IF (c = VariableUserList(k, 1)) THEN
                        c = "_null"
                        VariableUserList(k, 2) = d
                        MidFragment = d
                        EXIT FOR
                    END IF
                NEXT
                IF (c <> "_null") THEN
                    VariableUserListSize = VariableUserListSize + 1
                    VariableUserList(VariableUserListSize, 1) = c
                    VariableUserList(VariableUserListSize, 2) = d
                    MidFragment = d
                END IF
            END IF
        END IF

        IF (ScannedName = "alet") THEN
            ScannedNameFound = "_yes"
            e = LEFT$(MidFragment, 1)
            IF (TypeCheck$(e) = "number") THEN
                k = VAL(MidFragment)
                d = VariableUserList(k, 1)
                MidFragment = d
            END IF
            IF ((TypeCheck$(e) = "quote") OR (TypeCheck$(e) = "word")) THEN
                c = RemoveWrapping$(MidFragment, "`'")
                d = "-1"
                FOR k = 1 TO VariableUserListSize
                    IF (c = VariableUserList(k, 1)) THEN
                        d = LTRIM$(RTRIM$(STR$(k)))
                        EXIT FOR
                    END IF
                NEXT
                MidFragment = d
            END IF
        END IF

        IF (ScannedName = "slet") THEN
            ScannedNameFound = "_yes"
            MidFragment = LTRIM$(RTRIM$(STR$(VariableUserListSize)))
        END IF

        'IF (ScannedName = "input") THEN
        '    ScannedNameFound = "_yes"
        '    c1 = ReturnElement$(MidFragment, 1)
        '    c2 = ReturnElement$(MidFragment, 2)

        '    ' CPP: STARTSKIP
        '    ' JavaScript: STARTSKIP
        '    PRINT c2
        '    INPUT "> ", c
        '    ' CPP: ENDSKIP
        '    ' JavaScript: ENDSKIP

        '    ' CPP: STARTSKIP
        '    '\\c = prompt(c2, "");
        '    ' CPP: ENDSKIP

        '    ' JavaScript: STARTSKIP
        '    '\\std::cout << c2;
        '    '\\std::cin >> c;
        '    ' JavaScript: ENDSKIP

        '    MidFragment = InternalEval$("let(" + c1 + "," + c + ")")
        'END IF

        '
        ' Functions:
        '

        IF (ScannedName = "func") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            c = RemoveWrapping$(c, "`'")
            d = ReturnElement$(MidFragment, 2)
            'd = RemoveWrapping$(d, "{}")
            FOR k = 1 TO FunctionUserListSize
                IF (c = FunctionUserList(k, 1)) THEN
                    FunctionUserList(k, 2) = d
                    MidFragment = c
                    c = "_null"
                    EXIT FOR
                END IF
            NEXT
            IF (c <> "_null") THEN
                FunctionUserListSize = FunctionUserListSize + 1
                FunctionUserList(FunctionUserListSize, 1) = c
                FunctionUserList(FunctionUserListSize, 2) = d
                MidFragment = c
            END IF
        END IF

        IF ((ScannedName = "lambda") OR (ScannedName = "$")) THEN
            ScannedNameFound = "_yes"
            c = "lambda" + LTRIM$(RTRIM$(STR$(INT(RND * 9999))))
            d = ReturnElement$(MidFragment, 1)
            'd = RemoveWrapping$(d, "{}")
            FOR k = 1 TO FunctionUserListSize
                IF (d = FunctionUserList(k, 2)) THEN
                    MidFragment = FunctionUserList(k, 1)
                    c = "_null"
                    EXIT FOR
                END IF
            NEXT
            IF (c <> "_null") THEN
                FunctionUserListSize = FunctionUserListSize + 1
                FunctionUserList(FunctionUserListSize, 1) = c
                FunctionUserList(FunctionUserListSize, 2) = d
                MidFragment = c
            END IF
        END IF

        '
        ' Memory:
        '

        IF (ScannedName = "report") THEN
            ScannedNameFound = "_yes"
            c = "{"
            FOR k = 1 TO FunctionUserListSize
                c = c + "func(" + FunctionUserList(k, 1) + "," + FunctionUserList(k, 2) + ")"
                c = c + " : "
            NEXT
            FOR k = 1 TO VariableUserListSize
                c = c + "let(" + VariableUserList(k, 1) + "," + VariableUserList(k, 2) + ")"
                c = c + " : "
            NEXT
            c = c + "print_()}"
            MidFragment = c
        END IF

        IF (ScannedName = "reset") THEN
            ScannedNameFound = "_yes"
            VariableUserListSize = 0
            FunctionUserListSize = 0
            MidFragment = "report()"
        END IF

        '
        ' Type-wrapping and unwrapping functions.
        '

        IF (ScannedName = "type") THEN
            ScannedNameFound = "_yes"
            MidFragment = "`" + TypeCheck$(LEFT$(MidFragment, 1)) + "'"
        END IF
        IF (ScannedName = "quote") THEN
            ScannedNameFound = "_yes"
            MidFragment = "`" + MidFragment + "'"
        END IF
        IF (ScannedName = "unquote") THEN
            ScannedNameFound = "_yes"
            MidFragment = RemoveWrapping$(MidFragment, "`'")
        END IF
        IF (ScannedName = "vector") THEN
            ScannedNameFound = "_yes"
            MidFragment = "<" + MidFragment + ">"
        END IF
        IF (ScannedName = "unvector") THEN
            ScannedNameFound = "_yes"
            MidFragment = RemoveWrapping$(MidFragment, "<>")
        END IF
        IF (ScannedName = "occult") THEN
            ScannedNameFound = "_yes"
            MidFragment = "{" + MidFragment + "}"
        END IF
        IF (ScannedName = "unoccult") THEN
            ScannedNameFound = "_yes"
            MidFragment = RemoveWrapping$(MidFragment, "{}")
        END IF
        IF (ScannedName = "symbol") THEN
            ScannedNameFound = "_yes"
            MidFragment = "[" + MidFragment + "]"
        END IF
        IF (ScannedName = "unsymbol") THEN
            ScannedNameFound = "_yes"
            MidFragment = RemoveWrapping$(MidFragment, "[]")
        END IF

        '
        ' Subprograms:
        '

        IF (ScannedName = "sub") THEN
            ScannedNameFound = "_yes"
            MidFragment = SubExecute$(RemoveWrapping$(MidFragment, "{}"), "inline", "_yes")
        END IF
        IF (ScannedName = "block") THEN
            ScannedNameFound = "_yes"
            MidFragment = SubExecute$(RemoveWrapping$(MidFragment, "{}"), "inline", "_no")
        END IF
        IF (ScannedName = "exe") THEN
            ScannedNameFound = "_yes"
            MidFragment = SubExecute$(RemoveWrapping$(MidFragment, "`'"), "file", "_yes")
        END IF
        IF (ScannedName = "include") THEN
            ScannedNameFound = "_yes"
            MidFragment = SubExecute$(RemoveWrapping$(MidFragment, "`'"), "file", "_no")
        END IF
        ' ASCII Plotting.
        IF (ScannedName = "plot") THEN
            ScannedNameFound = "_yes"
            MidFragment = PlotASCII$(ReturnElement$(MidFragment, 1), VAL(ReturnElement$(MidFragment, 2)), VAL(ReturnElement$(MidFragment, 3)), VAL(ReturnElement$(MidFragment, 4)))
        END IF

        '
        ' File Write:
        '

        ' CPP: STARTSKIP
        ' JavaScript: STARTSKIP

        'IF (ScannedName = "write") THEN
        '    ScannedNameFound = "_yes"
        '    c1 = RemoveWrapping$(ReturnElement$(MidFragment, 1), "`'")
        '    c2 = ReturnElement$(MidFragment, 2)
        '    d = ReturnElement$(MidFragment, 3)
        '    IF (VAL(d) > 0) THEN
        '        c2 = FormatForTerminal$(c2)
        '    END IF
        '    OPEN c1 FOR OUTPUT AS #1
        '    PRINT #1, c2
        '    CLOSE #1
        '    MidFragment = "`Output written to " + c1 + ".'"
        'END IF

        'IF (ScannedName = "append") THEN
        '    ScannedNameFound = "_yes"
        '    c1 = RemoveWrapping$(ReturnElement$(MidFragment, 1), "`'")
        '    c2 = ReturnElement$(MidFragment, 2)
        '    d = ReturnElement$(MidFragment, 3)
        '    IF (VAL(d) > 0) THEN
        '        c2 = FormatForTerminal$(c2)
        '    END IF
        '    OPEN c1 FOR APPEND AS #1
        '    PRINT #1, c2
        '    CLOSE #1
        '    MidFragment = "`Output appended to " + c1 + ".'"
        'END IF

        ' CPP: ENDSKIP
        ' JavaScript: ENDSKIP

        '
        ' Flow-Control:
        '

        IF (ScannedName = "iff") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            IF (VAL(c) = 1) THEN
                MidFragment = RemoveWrapping$(ReturnElement$(MidFragment, 2), "{}")
            ELSE
                IF (CountElements(MidFragment, ",") = 2) THEN
                    MidFragment = ""
                END IF
                IF (CountElements(MidFragment, ",") = 3) THEN
                    MidFragment = RemoveWrapping$(ReturnElement$(MidFragment, 3), "{}")
                END IF
            END IF
        END IF

        IF (ScannedName = "switch") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            n = CountElements(MidFragment, ",")
            e = "_yes"
            FOR k = 2 TO n - 1 STEP 2
                d = ReturnElement$(MidFragment, k)
                IF (c = d) THEN
                    MidFragment = RemoveWrapping$(ReturnElement$(MidFragment, k + 1), "{}")
                    e = "_no"
                    EXIT FOR
                END IF
            NEXT
            IF (e = "_yes") THEN
                d = ReturnElement$(MidFragment, n - 1)
                IF (d = "else") THEN
                    MidFragment = RemoveWrapping$(ReturnElement$(MidFragment, n), "{}")
                END IF
            END IF
        END IF

        IF (ScannedName = "for") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = RemoveWrapping$(ReturnElement$(MidFragment, 2), "{}")
            e = ""
            IF (VAL(ReturnElement$(c, 2)) < VAL(ReturnElement$(c, 3))) THEN
                z = VAL(ReturnElement$(c, 4))
                FOR t = VAL(ReturnElement$(c, 2)) TO VAL(ReturnElement$(c, 3)) STEP z
                    c1 = InternalEval$("let(" + ReturnElement$(c, 1) + "," + STR$(t) + ")")
                    e = e + InternalEval$(d)
                NEXT
            ELSE
                IF (VAL(ReturnElement$(c, 2)) = VAL(ReturnElement$(c, 3))) THEN
                    c1 = InternalEval$("let(" + ReturnElement$(c, 1) + "," + ReturnElement$(c, 2) + ")")
                    e = e + InternalEval$(d)
                ELSE
                    z = ABS(VAL(ReturnElement$(c, 4)))
                    FOR t = VAL(ReturnElement$(c, 2)) TO VAL(ReturnElement$(c, 3)) STEP -1 * z
                        c1 = InternalEval$("let(" + ReturnElement$(c, 1) + "," + STR$(t) + ")")
                        e = e + InternalEval$(d)
                    NEXT
                END IF
            END IF
            MidFragment = e
        END IF

        '
        ' Numerical:
        '

        IF (ScannedName = "greater") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            IF (VAL(c) > VAL(d)) THEN
                MidFragment = "1"
            ELSE
                MidFragment = "0"
            END IF
        END IF

        IF (ScannedName = "int") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                t = VAL(MidFragment)
                t = INT(t)
                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        IF (ScannedName = "rand") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                z = VAL(ReturnElement$(MidFragment, 1))

                ' JavaScript: STARTSKIP
                ' CPP: STARTSKIP
                t = RND * z
                ' JavaScript: ENDSKIP
                ' CPP: ENDSKIP

                ' CPP: STARTSKIP
                '\\t = z * Math.random();
                ' CPP: ENDSKIP

                ' JavaScript: STARTSKIP
                '\\t = (rand() % RAND_MAX) * (z / RAND_MAX);
                ' JavaScript: ENDSKIP

                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        IF (ScannedName = "cos") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                t = VAL(MidFragment)
                t = COS(t)
                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        IF (ScannedName = "sin") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                t = VAL(MidFragment)
                t = SIN(t)
                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        IF (ScannedName = "tan") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                t = VAL(MidFragment)
                t = TAN(t)
                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        IF (ScannedName = "atan") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "number") THEN
                t = VAL(MidFragment)
                t = ATN(t)
                MidFragment = LTRIM$(RTRIM$(STR$(t)))
            END IF
        END IF

        '
        ' Largenum:
        '

        IF (ScannedName = "largeadd") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            MidFragment = STxAxTICAdd$(c, d)
        END IF

        IF (ScannedName = "largesub") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            MidFragment = STxAxTICSub$(c, d)
        END IF

        IF (ScannedName = "largemul") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            MidFragment = STxAxTICMul$(c, d)
        END IF

        IF (ScannedName = "largediv") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            k = LEN(c)
            n = LEN(d)
            'IF (k < n) THEN
            '    n = k
            'END IF
            n = n + k
            IF (n < 16) THEN
                n = 16
            END IF
            MidFragment = STxAxTICDiv$(c, d, n)
        END IF

        '
        ' Stricts (strict):
        '

        IF (ScannedName = "ucase") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "quote") THEN
                MidFragment = UCASE$(MidFragment)
            END IF
        END IF

        IF (ScannedName = "lcase") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "quote") THEN
                MidFragment = LCASE$(MidFragment)
            END IF
        END IF

        ' CPP: STARTSKIP
        IF (ScannedName = "asc") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "quote") THEN
                c = RemoveWrapping$(MidFragment, "`'")
                MidFragment = LTRIM$(RTRIM$(STR$(ASC(c))))
            END IF
        END IF
        ' CPP: ENDSKIP

        '
        ' Stricts (overloaded):
        '

        IF (ScannedName = "mid") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = TypeCheck$(LEFT$(c, 1))
            IF (d = "number") THEN
                c1 = ReturnElement$(MidFragment, 2)
                c2 = ReturnElement$(MidFragment, 3)
                c = MID$(c, VAL(c1), VAL(c2))
                MidFragment = c
            END IF
            IF (d = "quote") THEN
                c = RemoveWrapping$(c, "`'")
                c1 = ReturnElement$(MidFragment, 2)
                c2 = ReturnElement$(MidFragment, 3)
                c = MID$(c, VAL(c1), VAL(c2))
                MidFragment = "`" + c + "'"
            END IF
            IF (d = "vector") THEN
                c1 = ReturnElement$(MidFragment, 2)
                c2 = ReturnElement$(MidFragment, 3)
                IF ((VAL(c1) > 0) AND (VAL(c2) > 0)) THEN
                    k = GetSeparatorPos(c, ",", VAL(c1) - 1, 1)
                    n = GetSeparatorPos(c, ",", VAL(c1) + VAL(c2) - 1, k + 1)
                    IF (k = -1) THEN
                        k = 1
                    END IF
                    IF (n = -1) THEN
                        n = FindMatching(c, LEFT$(c, 1), 1)
                    END IF
                    IF ((k > -1) AND (n > -1)) THEN
                        MidFragment = LEFT$(c, 1) + MID$(c, k + 1, n - k - 1) + RIGHT$(c, 1)
                    END IF
                ELSE
                    MidFragment = LEFT$(c, 1) + "" + RIGHT$(c, 1)
                END IF
            END IF
        END IF

        IF (ScannedName = "left") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = TypeCheck$(LEFT$(c, 1))
            IF (d = "number") THEN
                e = ReturnElement$(MidFragment, 2)
                c = LEFT$(c, VAL(e))
                MidFragment = c
            END IF
            IF (d = "quote") THEN
                c = RemoveWrapping$(c, "`'")
                e = ReturnElement$(MidFragment, 2)
                c = LEFT$(c, VAL(e))
                MidFragment = "`" + c + "'"
            END IF
            IF (d = "vector") THEN
                e = ReturnElement$(MidFragment, 2)
                IF (VAL(e) > 0) THEN
                    k = GetSeparatorPos(c, ",", VAL(e), 1)
                    IF (k = -1) THEN
                        k = FindMatching(c, LEFT$(c, 1), 1)
                    END IF
                    IF (k > -1) THEN
                        MidFragment = LEFT$(c, k - 1) + RIGHT$(c, 1)
                    END IF
                ELSE
                    MidFragment = LEFT$(c, 1) + "" + RIGHT$(c, 1)
                END IF
            END IF
        END IF

        IF (ScannedName = "right") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = TypeCheck$(LEFT$(c, 1))
            IF (d = "number") THEN
                e = ReturnElement$(MidFragment, 2)
                c = RIGHT$(c, VAL(e))
                MidFragment = c
            END IF
            IF (d = "quote") THEN
                c = RemoveWrapping$(c, "`'")
                e = ReturnElement$(MidFragment, 2)
                c = RIGHT$(c, VAL(e))
                MidFragment = "`" + c + "'"
            END IF
            IF (d = "vector") THEN
                ' Vectors, etc.
                e = ReturnElement$(MidFragment, 2)
                IF (VAL(e) > 0) THEN
                    k = GetSeparatorPos(c, ",", CountElements(c, ",") - VAL(e), 1)
                    IF (k = -1) THEN
                        k = 1
                    END IF
                    IF (k > -1) THEN
                        MidFragment = LEFT$(c, 1) + RIGHT$(c, LEN(c) - k)
                    END IF
                ELSE
                    MidFragment = LEFT$(c, 1) + "" + RIGHT$(c, 1)
                END IF
            END IF
        END IF

        IF (ScannedName = "len") THEN
            ScannedNameFound = "_yes"
            d = TypeCheck$(MidFragment)
            IF ((d = "number") OR (d = "word")) THEN
                c = ReturnElement$(MidFragment, 1)
                MidFragment = LTRIM$(RTRIM$(STR$(LEN(c))))
            END IF
            IF (d = "quote") THEN
                c = RemoveWrapping$((ReturnElement$(MidFragment, 1)), "`'")
                MidFragment = LTRIM$(RTRIM$(STR$(LEN(c))))
            END IF
            IF (d = "vector") THEN
                MidFragment = LTRIM$(RTRIM$(STR$(CountElements(MidFragment, ","))))
            END IF
        END IF

        IF (ScannedName = "instr") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(MidFragment, 1, 1)) = "paren") THEN
                c1 = RemoveWrapping$((ReturnElement$(MidFragment, 1)), "`'")
                c2 = RemoveWrapping$((ReturnElement$(MidFragment, 2)), "`'")
                MidFragment = LTRIM$(RTRIM$(STR$(INSTR(c1, c2))))
            END IF
        END IF

        '
        ' Vector Elements:
        '

        IF (ScannedName = "elem") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(ReturnElement$(MidFragment, 1), VAL(ReturnElement$(MidFragment, 2)))
            MidFragment = c
        END IF

        IF (ScannedName = "stack") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            c = RemoveWrapping$(c, "<>")
            d = RemoveWrapping$(d, "<>")
            e = "<" + c + "," + d + ">"
            MidFragment = e
        END IF

        IF (ScannedName = "replace") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            n = VAL(ReturnElement$(MidFragment, 2))
            d = ReturnElement$(MidFragment, 3)
            k = CountElements(c, ",")
            IF (n = 1) THEN
                c = RIGHT$(c, LEN(c) - GetSeparatorPos(c, ",", 1, 1) + 1)
                c = "<" + d + c
            END IF
            IF (n = k) THEN
                c = LEFT$(c, GetSeparatorPos(c, ",", k - 1, 1))
                c = c + d + ">"
            END IF
            IF ((n > 1) AND (n < CountElements(c, ","))) THEN
                c = LEFT$(c, GetSeparatorPos(c, ",", n - 1, 1)) + d + RIGHT$(c, LEN(c) - GetSeparatorPos(c, ",", n, 1) + 1)
            END IF
            MidFragment = c
        END IF

        IF (ScannedName = "column") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 2)
            n = CountElements(c, ",")
            e = ""
            IF (CountElements(ReturnElement$(c, 1), ",") > 1) THEN
                FOR k = 1 TO n
                    e = e + ReturnElement$(ReturnElement$(c, k), VAL(d))
                    IF (k < n) THEN
                        e = e + ","
                    END IF
                NEXT
                e = "<" + e + ">"
            ELSE
                e = ReturnElement$(c, VAL(d))
            END IF
            MidFragment = e
        END IF

        IF (ScannedName = "smooth") THEN
            ScannedNameFound = "_yes"
            c = MidFragment
            c = ReplaceWord$(c, ",,", ",", -1)
            c = ReplaceWord$(c, "<,", "<", -1)
            c = ReplaceWord$(c, ",>", ">", -1)
            MidFragment = c
        END IF

        '
        ' Vector Pocessing:
        '

        IF (ScannedName = "apply") THEN
            ScannedNameFound = "_yes"
            IF (TypeCheck$(MID$(ReturnElement$(MidFragment, 2), 1, 1)) = "vector") THEN
                MidFragment = StructureApplyFunc$(ReturnElement$(MidFragment, 2), ReturnElement$(MidFragment, 1), "<>")
            END IF
        END IF

        IF (ScannedName = "reduce") THEN
            ScannedNameFound = "_yes"
            d = ReturnElement$(MidFragment, 1)
            e = ReturnElement$(MidFragment, 2)
            c = d + "(" + ReturnElement$(e, 1) + "," + ReturnElement$(e, 2) + ")"
            FOR k = 2 TO CountElements(e, ",") - 1
                c = d + "(" + c + "," + ReturnElement$(e, k + 1) + ")"
            NEXT
            MidFragment = c
        END IF

        IF (ScannedName = "map") THEN
            ScannedNameFound = "_yes"
            c = ReturnElement$(MidFragment, 1)
            d = ReturnElement$(MidFragment, 3)
            e = ReturnElement$(MidFragment, 2)
            n = CountElements(c, ",")
            IF (n <> CountElements(d, ",")) THEN
                MidFragment = "ERROR:`Unequal dimensions sent to map.'"
            ELSE
                c1 = LEFT$(c, 1)
                FOR k = 1 TO n
                    c1 = c1 + e + "(" + ReturnElement$(c, k) + "," + ReturnElement$(d, k) + ")"
                    IF (k < n) THEN
                        c1 = c1 + ","
                    END IF
                NEXT
                c1 = c1 + RIGHT$(c, 1)
                MidFragment = c1
            END IF
        END IF

        IF (ScannedNameFound = "_no") THEN
            MidFragment = ScannedName + MidFragment
        END IF

        TheReturn = LeftFragment + MidFragment + RightFragment

    END IF

END IF

IF (TheReturn = "") THEN
    TheReturn = TheString
END IF

EvalStep$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION SxriptEval$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
TheString = TheStringIn
'''TheString = ManageWhiteSpace$(TheString)
TheString = InternalEval$(TheString)
TheString = FormatForTerminal$(TheString)
TheReturn = TheString
SxriptEval$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION NumberCrunch$ (TheStringIn AS STRING)
DIM TheReturn AS STRING
DIM TheString AS STRING
DIM TypeLeft AS STRING
DIM TypeRight AS STRING
DIM ArgLeft AS STRING
DIM ArgRight AS STRING
DIM LeftFragment AS STRING
DIM MidFragment AS STRING
DIM RightFragment AS STRING
DIM TheOperator AS STRING
DIM k AS INTEGER
DIM j AS INTEGER
DIM m AS INTEGER
DIM n AS INTEGER
DIM t1 AS DOUBLE
DIM t2 AS DOUBLE
DIM t3 AS DOUBLE
DIM c AS STRING
DIM c1 AS STRING
DIM c2 AS STRING
TheString = TheStringIn
TheReturn = ""
TypeLeft = ""
TypeRight = ""
ArgLeft = ""
ArgRight = ""
TheOperator = ""
k = -1
m = -1
n = -1
c = ""
c1 = ""
c2 = ""

TheString = ManageOperators$(TheString)
TheReturn = TheString

'''PRINT "N: "; TheString
'''OPEN "parse.txt" FOR APPEND AS #1
'''PRINT #1, TheString
'''CLOSE #1

IF (TheReturn = TheString) THEN

    FOR n = 1 TO LEN(OpList)
        c = MID$(OpList, n, 1)
        k = ScanForOperator(TheString, c)
        IF (k > -1) THEN
            m = k
            TheOperator = c
            EXIT FOR
        END IF
    NEXT

    ' Special case (1 of 2) for tilde operator.
    IF (TheOperator = "~") THEN
        m = ScanForName(TheString, k - 1, "left") - 1
        TheOperator = MID$(TheString, m, k - m + 1)
        k = m
    END IF
END IF

IF (TheOperator <> "") THEN

    c1 = MID$(TheString, k - 1, 1)
    c2 = MID$(TheString, k + LEN(TheOperator), 1)

    ' Special case (1 of 2) for factorial symbol as an operator.
    IF (TheOperator = "!") THEN
        c2 = "0"
    END IF

    IF ((c1 <> "") AND (c2 <> "")) THEN

        TypeLeft = TypeCheck$(c1)
        TypeRight = TypeCheck$(c2)

        ' Handle left side of operator.
        IF (TypeLeft = "number") THEN
            m = ScanForName(TheString, k - 1, "left")
            ''' the m>1 condition is an edit demanded by qb45!
            IF (m > 1) THEN
                IF ((MID$(TheString, m - 1, 1) = "+") OR (MID$(TheString, m - 1, 1) = "-")) THEN
                    m = m - 1
                END IF
            END IF
        END IF
        IF ((TypeLeft = "vector") OR (TypeLeft = "quote") OR (TypeLeft = "occulted")) THEN
            m = FindMatching(TheString, c1, k - 1)
            IF (m = -1) THEN
                m = 1
            END IF
        END IF
        IF (TypeLeft = "word") THEN
            m = ScanForName(TheString, k - 1, "left")
        END IF

        ' Handle right side of operator.
        IF (TypeRight = "number") THEN
            n = ScanForName(TheString, k + LEN(TheOperator), "right")
        END IF
        IF ((TypeRight = "vector") OR (TypeRight = "quote") OR (TypeRight = "occulted")) THEN
            n = FindMatching(TheString, c2, k + LEN(TheOperator))
            IF (n = -1) THEN
                n = LEN(TheString)
            END IF
        END IF
        IF (TypeRight = "word") THEN
            n = ScanForName(TheString, k + LEN(TheOperator), "right")
        END IF

        ' Special case (2 of 2) for factorial symbol as an operator.
        IF (TheOperator = "!") THEN
            n = k
            TypeRight = "number"
        END IF

        ' Break the string into fragments.
        ArgLeft = MID$(TheString, m, k - m)
        ArgRight = MID$(TheString, k + LEN(TheOperator), n - k - LEN(TheOperator) + 1)
        LeftFragment = LEFT$(TheString, m - 1)
        RightFragment = RIGHT$(TheString, LEN(TheString) - n)

        ' Special case (2 of 2) for tilde operator.
        IF (TheReturn = TheString) THEN
            IF (LEFT$(TheOperator, 1) = "~") THEN
                TheOperator = RemoveWrapping$(TheOperator, "~~")
                MidFragment = "(" + TheOperator + "(" + ArgLeft + "," + ArgRight + ")" + ")"
                MidFragment = InternalEval$(MidFragment)
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Special case for ? operator.
        IF (TheReturn = TheString) THEN
            IF (TheOperator = "?") THEN
                MidFragment = ArgLeft + "(" + ArgRight + ")"
                MidFragment = InternalEval$(MidFragment)
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: word @ word
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "word") AND (TypeRight = "word")) THEN
                IF (TheOperator = "=") THEN
                    IF (ArgLeft = ArgRight) THEN
                        MidFragment = "1"
                    ELSE
                        MidFragment = "0"
                    END IF
                END IF
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: number @ number
        ' (Check for division by zero.)
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "number") AND (TypeRight = "number")) THEN

                ArgLeft = ReplaceWord$(ArgLeft, "Dp", "D+", -1)
                ArgLeft = ReplaceWord$(ArgLeft, "Dm", "D-", -1)
                ArgRight = ReplaceWord$(ArgRight, "Dp", "D+", -1)
                ArgRight = ReplaceWord$(ArgRight, "Dm", "D-", -1)

                ArgLeft = ReplaceWord$(ArgLeft, "Ep", "e+", -1)
                ArgLeft = ReplaceWord$(ArgLeft, "Em", "e-", -1)
                ArgRight = ReplaceWord$(ArgRight, "Ep", "e+", -1)
                ArgRight = ReplaceWord$(ArgRight, "Em", "e-", -1)

                t1 = VAL(ArgLeft)
                t2 = VAL(ArgRight)

                IF (TheOperator = "!") THEN
                    t2 = ABS(t1)
                    t1 = t1 / ABS(t1)
                    t3 = 1
                    FOR k = 1 TO t2
                        t3 = t3 * k
                    NEXT
                    t3 = t3 * t1
                END IF

                IF (TheOperator = "^") THEN
                    ' CPP: STARTSKIP
                    ' JavaScript: STARTSKIP
                    t3 = t1 ^ t2
                    ' CPP: ENDSKIP
                    ' JavaScript: ENDSKIP
                    ' CPP: STARTSKIP
                    '\\t3 = Math.pow(t1, t2);
                    ' CPP: ENDSKIP
                    ' JavaScript: STARTSKIP
                    '\\t3 = pow(t1, t2);
                    ' JavaScript: ENDSKIP
                END IF

                IF (TheOperator = "*") THEN
                    t3 = t1 * t2
                END IF

                IF (TheOperator = "/") THEN
                    t3 = t1 / t2
                END IF
                IF (TheOperator = "%") THEN
                    ' CPP: STARTSKIP
                    t3 = t1 MOD t2
                    ' CPP: ENDSKIP
                END IF

                IF (TheOperator = "+") THEN
                    t3 = t1 + t2
                END IF

                IF (TheOperator = "-") THEN
                    t3 = t1 - t2
                END IF

                IF (TheOperator = "=") THEN
                    IF ((t1 - t2) = 0) THEN
                        t3 = 1
                    ELSE
                        t3 = 0
                    END IF
                END IF

                IF (TheOperator = "&") THEN
                    IF ((t1 > 0) AND (t2 > 0)) THEN
                        t3 = 1
                    ELSE
                        t3 = 0
                    END IF
                END IF

                IF (TheOperator = "|") THEN
                    IF ((t1 > 0) OR (t2 > 0)) THEN
                        t3 = 1
                    ELSE
                        t3 = 0
                    END IF
                END IF

                ' Inserts a "+" sign in front of positive results.
                IF (t3 >= 0) THEN
                    MidFragment = "+" + LTRIM$(RTRIM$(STR$(t3)))
                ELSE
                    MidFragment = LTRIM$(RTRIM$(STR$(t3)))
                END IF

                ' Inserts ".0" for numbers not containing decimals.
                IF (INSTR(MidFragment, ".") < 1) THEN
                    MidFragment = MidFragment + ".0"
                END IF

                ' More strict format for small decimals.
                MidFragment = ReplaceWord$(MidFragment, "+.", "+0.", -1)
                MidFragment = ReplaceWord$(MidFragment, "-.", "-0.", -1)

                TheReturn = LeftFragment + MidFragment + RightFragment

            END IF
        END IF

        ' Case: number @ quote
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "number") AND (TypeRight = "quote")) THEN
                ArgRight = RemoveWrapping$(ArgRight, "`'")
                c = ""
                FOR k = 1 TO INT(VAL(ArgLeft))
                    c = c + ArgRight
                NEXT
                c = "`" + c + "'"
                MidFragment = c
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: number @ vector
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "number") AND (TypeRight = "vector")) THEN
                MidFragment = StructureApplyFunc$(ArgRight, ArgLeft + TheOperator, "<>")
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: quote @ vector
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "quote") AND (TypeRight = "vector")) THEN
                MidFragment = StructureApplyFunc$(ArgRight, ArgLeft + TheOperator, "<>")
                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: quote @ quote
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "quote") AND (TypeRight = "quote")) THEN
                ArgLeft = RemoveWrapping$(ArgLeft, "`'")
                ArgRight = RemoveWrapping$(ArgRight, "`'")

                IF (TheOperator = "*") THEN
                    c = ""
                    FOR k = 1 TO LEN(ArgLeft)
                        c = c + MID$(ArgLeft, k, 1) + ArgRight
                    NEXT
                    MidFragment = "`" + c + "'"
                END IF

                IF (TheOperator = "/") THEN
                    c1 = ArgLeft
                    n = -1
                    DO WHILE (n = -1)
                        k = INSTR(c1, ArgRight)
                        IF (k > 0) THEN
                            c1 = LEFT$(c1, k - 1) + RIGHT$(c1, LEN(c1) - k - LEN(ArgRight) + 1)
                        ELSE
                            n = 1
                        END IF
                    LOOP
                    MidFragment = "`" + c1 + "'"
                END IF

                IF (TheOperator = "+") THEN
                    MidFragment = "`" + ArgLeft + ArgRight + "'"
                END IF

                IF (TheOperator = "-") THEN
                    IF (RIGHT$(ArgLeft, LEN(ArgRight)) = ArgRight) THEN
                        MidFragment = "`" + LEFT$(ArgLeft, LEN(ArgLeft) - LEN(ArgRight)) + "'"
                    ELSE
                        MidFragment = "`" + ArgLeft + "'-`" + ArgRight + "'"
                    END IF
                END IF

                IF (TheOperator = "=") THEN
                    IF (ArgLeft = ArgRight) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                IF (TheOperator = "&") THEN
                    IF ((ArgLeft <> "") AND (ArgRight <> "")) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                IF (TheOperator = "|") THEN
                    IF ((ArgLeft <> "") OR (ArgRight <> "")) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

        ' Case: vector @ vector
        IF (TheReturn = TheString) THEN
            IF ((TypeLeft = "vector") AND (TypeRight = "vector")) THEN

                IF (TheOperator = "^") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "^")
                END IF
                IF (TheOperator = "*") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "*")
                END IF
                IF (TheOperator = "/") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "/")
                END IF
                IF (TheOperator = "%") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "/")
                END IF
                IF (TheOperator = "+") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "+")
                END IF
                IF (TheOperator = "-") THEN
                    MidFragment = VectorASMD$(ArgLeft, ArgRight, "-")
                END IF

                IF (TheOperator = "=") THEN
                    IF (ArgLeft = ArgRight) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                IF (TheOperator = "&") THEN
                    IF ((ArgLeft <> "<>") AND (ArgRight <> "<>")) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                IF (TheOperator = "|") THEN
                    IF ((ArgLeft <> "<>") OR (ArgRight <> "<>")) THEN
                        c = "1"
                    ELSE
                        c = "0"
                    END IF
                    MidFragment = c
                END IF

                TheReturn = LeftFragment + MidFragment + RightFragment
            END IF
        END IF

    ELSE

        ' Operator found but no surrounding numbers.

    END IF

END IF

IF (TheReturn = "") THEN
    TheReturn = TheString
END IF

NumberCrunch$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''

FUNCTION SubExecute$ (TheScriptIn AS STRING, TheModeIn AS STRING, ScopeSwitchIn AS STRING)
DIM TheReturn AS STRING
DIM TheScript AS STRING
DIM TheMode AS STRING
DIM ScopeSwitch AS STRING
DIM TheFile AS STRING
DIM AnchorCount AS INTEGER
DIM LineCount AS INTEGER
DIM LoopCounter AS INTEGER
DIM LoopIndex AS INTEGER
DIM LineIndex AS INTEGER
DIM k AS INTEGER
DIM m AS INTEGER
DIM c AS STRING
DIM d AS STRING
DIM EvalDone AS INTEGER
DIM FunctionUserListSizeOrig AS INTEGER
DIM VariableUserListSizeOrig AS INTEGER
TheReturn = ""
TheScript = TheScriptIn
TheMode = TheModeIn
ScopeSwitch = ScopeSwitchIn
AnchorCount = 0
LineCount = 0
LoopCounter = 0
LoopIndex = 0
LineIndex = 0
EvalDone = 0

IF (ScopeSwitch = "_yes") THEN
    ' Increment function and variable scope.
    FunctionUserListSizeOrig = FunctionUserListSize
    VariableUserListSizeOrig = VariableUserListSize
    ScopeLevel = ScopeLevel + 1
    FOR k = 1 TO FunctionUserListSize
        FunctionUserListScope(k, 1, ScopeLevel) = FunctionUserList(k, 1)
        FunctionUserListScope(k, 2, ScopeLevel) = FunctionUserList(k, 2)
    NEXT
    FOR k = 1 TO VariableUserListSize
        VariableUserListScope(k, 1, ScopeLevel) = VariableUserList(k, 1)
        VariableUserListScope(k, 2, ScopeLevel) = VariableUserList(k, 2)
    NEXT

    '''PRINT "ScopeLevel: "; ScopeLevel

END IF

IF (TheMode = "file") THEN
    TheFile = RemoveWrapping$(TheScript, "`'")
    TheScript = ""

    ' CPP: STARTSKIP
    ' JavaScript: STARTSKIP
    '''IF (_FILEEXISTS(TheFile) <> 0) THEN
    OPEN TheFile FOR INPUT AS #1
    DO WHILE NOT EOF(1)
        LINE INPUT #1, d
        d = LTRIM$(RTRIM$(d))
        TheScript = TheScript + d
    LOOP
    CLOSE #1
    '''ELSE
    '''TheScript = "ERROR:`File not found.'"
    '''END IF
    ' CPP: ENDSKIP
    ' JavaScript: ENDSKIP

    ' CPP: STARTSKIP
    '\\$.ajax({
    '\\     url: "../" + TheFile,
    '\\     async: false,
    '\\     dataType: "text",
    '\\     success: function (data){
    '\\          TheScript = data;
    '\\     }
    '\\});
    '\\TheScript = TheScript.replace(/(\r\n|\n|\r)/gm,"");
    ' CPP: ENDSKIP

    ' JavaScript: STARTSKIP
    '\\std::ifstream myfile(TheFile.c_str());
    '\\if (myfile.is_open()) {
    '\\    while (std::getline(myfile, d)) {
    '\\        d = lTRIM(rTRIM(d));
    '\\        TheScript = TheScript + d;
    '\\    }
    '\\    myfile.close();
    '\\}
    ' JavaScript: ENDSKIP

    TheScript = ManageWhiteSpace$(TheScript)
END IF

' Scale arrays according to line count.
' Factors of +1 added to accomodate C++ implementation.
LineCount = CountElements("(" + TheScript + ")", ":")
DIM ScriptLine(LineCount + 1) AS STRING
DIM ScriptLinePrintFlag(LineCount + 1) AS INTEGER
DIM LoopStartPosition(LineCount + 1) AS INTEGER
DIM LoopIterationCount(LineCount + 1) AS INTEGER
DIM AnchorList(LineCount + 1, 2) AS STRING

' CPP: STARTSKIP
'\\for (k = 1; k <= 299; k += 1) {
'\\    AnchorList[k] = new Array(2);
'\\}
' CPP: ENDSKIP

' Break input string apart at each (:) symbol.
m = 0
DO WHILE (1 = 1)
    k = GetSeparatorPos("(" + TheScript + ")", ":", 1, 1) - 1
    IF (k > -1) THEN
        m = m + 1
        ScriptLine(m) = LEFT$(TheScript, k - 1)
        TheScript = RIGHT$(TheScript, LEN(TheScript) - k)
    ELSE
        m = m + 1
        ScriptLine(m) = TheScript
        EXIT DO
    END IF
LOOP

' Prepare loops.
k = LineCount
DO WHILE (k > 1)
    FOR k = LineCount TO 1 STEP -1
        IF (ScriptLine(k) = "do") THEN
            LoopCounter = LoopCounter + 1
            ScriptLine(k) = "_do " + LTRIM$(STR$(LoopCounter))
            LoopStartPosition(LoopCounter) = k
            FOR m = k TO LineCount
                IF (ScriptLine(m) = "loop") THEN
                    ScriptLine(m) = "_loop " + LTRIM$(STR$(LoopCounter))
                    EXIT FOR
                END IF
            NEXT
            EXIT FOR
        END IF
    NEXT
LOOP

' Prepare `print' and `anchor'.
FOR k = 1 TO LineCount
    c = ScriptLine(k)
    ScriptLinePrintFlag(k) = 0
    IF (LEFT$(c, 6) = "print_") THEN
        ScriptLinePrintFlag(k) = 1
        ScriptLine(k) = RIGHT$(c, LEN(c) - 6)
    END IF
    IF (LEFT$(c, 7) = "anchor_") THEN
        AnchorCount = AnchorCount + 1
        AnchorList(AnchorCount, 1) = RIGHT$(c, LEN(c) - 7)
        AnchorList(AnchorCount, 2) = LTRIM$(STR$(k))
    END IF
NEXT

' Main script evaluation loop.
DO WHILE (LineIndex < LineCount)
    LineIndex = LineIndex + 1
    c = ScriptLine(LineIndex)
    EvalDone = 0

    IF (LEFT$(c, 3) = "_do") THEN
        EvalDone = 1
        LoopIndex = VAL(RIGHT$(c, LEN(c) - 3))
        LoopIterationCount(LoopIndex) = VAL(InternalEval$(ScriptLine(LineIndex - 1)))
    END IF

    IF (LEFT$(c, 5) = "_loop") THEN
        EvalDone = 1
        LoopIndex = VAL(RIGHT$(c, LEN(c) - 5))
        IF (LoopIterationCount(LoopIndex) > 1) THEN
            LoopIterationCount(LoopIndex) = LoopIterationCount(LoopIndex) - 1
            LineIndex = LoopStartPosition(LoopIndex)
        END IF
    END IF

    IF (LEFT$(c, 5) = "goto_") THEN
        EvalDone = 1
        FOR k = 1 TO AnchorCount
            IF (AnchorList(k, 1) = RIGHT$(c, LEN(c) - 5)) THEN
                LineIndex = VAL(AnchorList(k, 2))
            END IF
        NEXT
    END IF

    IF (LEFT$(c, 3) = "if_") THEN
        EvalDone = 1
        c = RIGHT$(c, LEN(c) - 3)
        k = ScanForOperator(c, "@")
        d = RIGHT$(c, LEN(c) - k)
        c = LEFT$(c, k - 1)
        c = InternalEval$(c)
        IF (VAL(c) = 1) THEN
            FOR k = 1 TO AnchorCount
                IF (AnchorList(k, 1) = d) THEN
                    LineIndex = VAL(AnchorList(k, 2))
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF

    IF (LEFT$(c, 7) = "anchor_") THEN
        EvalDone = 1
    END IF

    IF (EvalDone = 0) THEN
        EvalDone = 1
        c = InternalEval$(c)
        IF (ScriptLinePrintFlag(LineIndex) = 1) THEN
            TheReturn = TheReturn + c
        END IF
    END IF

LOOP

' CPP: STARTSKIP
' JavaScript: STARTSKIP
'IF (TheMode = "file") THEN
'    OPEN ReplaceWord$(TheFile, ".txt", "", -1) + "-out.txt" FOR OUTPUT AS #1
'    PRINT #1, FormatForTerminal$(TheReturn)
'    CLOSE #1
'END IF
' CPP: ENDSKIP
' JavaScript: ENDSKIP

IF (ScopeSwitch = "_yes") THEN
    ' Decrement function and variable scope.
    FOR k = 1 TO FunctionUserListSize
        FunctionUserList(k, 1) = FunctionUserListScope(k, 1, ScopeLevel)
        FunctionUserList(k, 2) = FunctionUserListScope(k, 2, ScopeLevel)
    NEXT
    FOR k = 1 TO VariableUserListSize
        VariableUserList(k, 1) = VariableUserListScope(k, 1, ScopeLevel)
        VariableUserList(k, 2) = VariableUserListScope(k, 2, ScopeLevel)
    NEXT
    ScopeLevel = ScopeLevel - 1
    FunctionUserListSize = FunctionUserListSizeOrig
    VariableUserListSize = VariableUserListSizeOrig
END IF

SubExecute$ = TheReturn
END FUNCTION

' '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''
