Rem File: Equate.bas - for Cmd*.bas modules.
Rem $Include: 'dndbbs.inc'

' entry to recursive descent parser
'   input: Out2
'   output: Temp#
Sub Equate(Temp#)
 On Local Error Goto Error.Trap23
 Temp#=DFalse
 Var=Instr(Out2," ")
 While Var
    Out2=Left$(Out2,Var-1)+Mid$(Out2,Var+1)
    Var=Instr(Out2," ")
 WEND
 If Out2<>Nul Then
    Out2=Ucase$(Out2)
    Token.Index=1
    Call Get.Token
    Call Parse1(Temp#)
 Endif
Error.Resume23:
 Exit Sub
Error.Trap23:
 Temp#=DFalse
 Resume Error.Resume23
End Sub

 ' logical parser
Sub Parse1(Temp#)
 On Local Error Goto Error.Trap23a
 Call Parse2(Temp#)
 Token.Parsed$=Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "|", "&", "~", "?", ":", "#", "@", "`"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse2(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23a:
 Exit Sub
Error.Trap23a:
 Temp#=DFalse
 Resume Error.Resume23a
End Sub

 ' relational parser
Sub Parse2(Temp#)
 On Local Error Goto Error.Trap23b
 CALL Parse3(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "<", ">", "=", ">=", "<=", "<>"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse3(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23b:
 Exit Sub
Error.Trap23b:
 Temp#=DFalse
 Resume Error.Resume23b
End Sub

 ' addition/subtraction parser
Sub Parse3(Temp#)
 On Local Error Goto Error.Trap23c
 CALL Parse4(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "+", "-"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse4(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23c:
 Exit Sub
Error.Trap23c:
 Temp#=DFalse
 Resume Error.Resume23c
End Sub

 ' modulo parser
Sub Parse4(Temp#)
 On Local Error Goto Error.Trap23d
 CALL Parse5(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "%"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse5(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23d:
 Exit Sub
Error.Trap23d:
 Temp#=DFalse
 Resume Error.Resume23d
End Sub

 ' integer division parser
Sub Parse5(Temp#)
 On Local Error Goto Error.Trap23e
 CALL Parse6(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "\"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse6(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23e:
 Exit Sub
Error.Trap23e:
 Temp#=DFalse
 Resume Error.Resume23e
End Sub

 ' multiplication/division parser
Sub Parse6(Temp#)
 On Local Error Goto Error.Trap23f
 CALL Parse7(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "*", "/"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse7(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23f:
 Exit Sub
Error.Trap23f:
 Temp#=DFalse
 Resume Error.Resume23f
End Sub

 ' power parser
Sub Parse7(Temp#)
 On Local Error Goto Error.Trap23g
 CALL Parse7a(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "^", "^=", "^-=", "^+="
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
    CALL Parse7a(Temp2#)
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23g:
 Exit Sub
Error.Trap23g:
 Temp#=DFalse
 Resume Error.Resume23g
END SUB

 ' dual-unary parser
Sub Parse7a(Temp#)
 On Local Error Goto Error.Trap23g2
 CALL Parse8(Temp#)
 Token.Parsed$ = Token2$
 DO
    SELECT CASE Token.Parsed$
    CASE "<<", ">>", "--", "++", "**", "//", "||", "##", "^^"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    Token.Stored$ = Token1$
    CALL Get.Token
'    CALL Parse8(Temp2#) ' no secondary token
    Token1$ = Token.Stored$
    CALL Arith(Token.Parsed$, Temp#, Temp2#)
    Token.Parsed$ = Token2$
 LOOP
Error.Resume23g2:
 Exit Sub
Error.Trap23g2:
 Temp#=DFalse
 Resume Error.Resume23g2
END SUB

 ' not/unary plus/unary negative parser
Sub Parse8(Temp#)
 On Local Error Goto Error.Trap23h
 Token.Negate$ = Nul ' reset token storage
 Token.Parsed$ = Token2$ ' store token
 ' process token
 DO
    SELECT CASE Token.Parsed$
    CASE "!", "-", "+", "--", "++"
       Eat$ = Nul
    CASE ELSE
       EXIT DO
    END SELECT
    CALL Get.Token ' read next token
    Token.Negate$ = Token.Negate$ + Token.Parsed$
    Token.Parsed$ = Token2$ ' store token
 LOOP
 CALL Parse9(Temp#) ' get next operator

 ' process the combined operators in reverse
 FOR Token.Type = LEN(Token.Negate$) TO 1 STEP -1
    SELECT CASE MID$(Token.Negate$, Token.Type, 1) ' get previous token
    CASE "+" ' eat unary plus
       Eat$ = Nul
    CASE "-" ' perform negate
       Temp# = -Temp#
    CASE "!" ' perform not calculation
       Temp# = NOT Temp#
    END SELECT
 NEXT
Error.Resume23h:
 Exit Sub
Error.Trap23h:
 Temp#=DFalse
 Resume Error.Resume23h
END SUB

Sub Parse9(Temp#)
 On Local Error Goto Error.Trap23i
 Select Case Token
 Case 1
    Select Case Token2$
    Case "("
       Call Get.Token
       If Token2$<>")" Then
          Do
             Call Parse1(Temp#)
          Loop Until Token2$=")" Or Token=False
          Call Get.Token
       Endif
    Case "["
       Call Get.Token
       If Token2$<>"]" Then
          Do
             Call Parse1(Temp#)
          Loop Until Token2$="]" Or Token=False
          Call Get.Token
       Endif
    Case "{"
       Call Get.Token
       If Token2$<>"}" Then
          Do
             Call Parse1(Temp#)
          Loop Until Token2$="}" Or Token=False
          Call Get.Token
       Endif
    Case ")", "]", "}"
       Call Get.Token
       Exit Sub
    End Select
 Case 2
    Select Case Right$(Token2$,1)
    Case "H" ' hexidecimal
       Temp#=DFalse
       Var=False
       FOR Var1=LEN(Token2$)-1 TO 1 STEP -1
          Var2=VAL("&H"+(MID$(Token2$,Var1,1)))
          Temp#=Temp#+Var2*16^Var
          Var=Var+1
       NEXT
    Case "O" ' octal
       Temp#=DFalse
       Var=False
       FOR Var1=LEN(Token2$)-1 TO 1 STEP -1
          Var2=VAL(MID$(Token2$,Var1,1))
          Temp#=Temp#+Var2*8^Var
          Var=Var+1
       NEXT
    Case "B" ' binary
       Temp#=DFalse
       Var=False
       For Var1=Len(Token2$)-1 To 1 Step -1
          If Mid$(Token2$,Var1,1)="1" Then
             Temp#=Temp#+2^Var
          Endif
          Var=Var+1
       Next
    Case Else ' decimal
       Temp#=Val(Token2$)
    End Select
    Call Get.Token
 Case 3
    Select Case Token2$
    Case "BET" ' russian roulette/poison bottles
       Temp#=TempX
    Case "BOTTLE" ' poison bottles
       Temp#=TempY
    Case "CHOICE" ' poison bottles
       Temp#=TempZ
    Case "CONFIG1" ' Config1!()
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       VarX=Cint(Temp#)
       Temp# = Cdbl(Config1!(VarX))
    Case "CONFIG2" ' Config2%()
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       VarX=Cint(Temp#)
       Temp# = Cdbl(Config2%(VarX))
    Case "STR"
       Temp#=UserRecord.Stats(1)
    Case "STR2"
       Temp#=UserRecord2.Stats(1)
    Case "INT"
       Temp#=UserRecord.Stats(2)
    Case "INT2"
       Temp#=UserRecord2.Stats(2)
    Case "WIS"
       Temp#=UserRecord.Stats(3)
    Case "WIS2"
       Temp#=UserRecord2.Stats(3)
    Case "DEX"
       Temp#=UserRecord.Stats(4)
    Case "DEX2"
       Temp#=UserRecord2.Stats(4)
    Case "CON"
       Temp#=UserRecord.Stats(5)
    Case "CON2"
       Temp#=UserRecord2.Stats(5)
    Case "PIE"
       Temp#=UserRecord.Stats(6)
    Case "PIE2"
       Temp#=UserRecord2.Stats(6)
    Case "CHA"
       Temp#=UserRecord.Stats(7)
    Case "CHA2"
       Temp#=UserRecord2.Stats(7)
    Case "FAT"
       Temp#=UserRecord.Fatigue
    Case "FAT2"
       Temp#=UserRecord2.Fatigue
    Case "VIT"
       Temp#=UserRecord.Vitality
    Case "VIT2"
       Temp#=UserRecord2.Vitality
    Case "MAG"
       Temp#=UserRecord.Magic
    Case "MAG2"
       Temp#=UserRecord2.Magic
    Case "EXP"
       Temp#=UserRecord.Experience
    Case "EXP2"
       Temp#=UserRecord2.Experience
    Case "LVL"
       Temp#=UserRecord.Level
    Case "LVL2"
       Temp#=UserRecord2.Level
    Case "BEA"
       Temp#=UserRecord.Beauty
    Case "BEA2"
       Temp#=UserRecord2.Beauty
    Case "GLA"
       Temp#=UserRecord.Glamour
    Case "GLA2"
       Temp#=UserRecord2.Glamour
    Case "AR" ' armor plus
       Temp#=UserRecord.Weapon(1).Plus
    Case "AR2" ' armor plus
       Temp#=UserRecord2.Weapon(1).Plus
    Case "BO" ' boot plus
       Temp#=UserRecord.Weapon(2).Plus
    Case "BO2" ' boot plus
       Temp#=UserRecord2.Weapon(2).Plus
    Case "HE" ' helmet plus
       Temp#=UserRecord.Weapon(3).Plus
    Case "HE2" ' helmet plus
       Temp#=UserRecord2.Weapon(3).Plus
    Case "RG1" ' left ring plus
       Temp#=UserRecord.Weapon(4).Plus
    Case "RG1X" ' left ring plus
       Temp#=UserRecord2.Weapon(4).Plus
    Case "SH" ' shield plus
       Temp#=UserRecord.Weapon(5).Plus
    Case "SH2" ' shield plus
       Temp#=UserRecord2.Weapon(5).Plus
    Case "TW" ' bracers plus
       Temp#=UserRecord.Weapon(6).Plus
    Case "TW2" ' bracers plus
       Temp#=UserRecord2.Weapon(6).Plus
    Case "WE" ' weapon plus
       Temp#=UserRecord.Weapon(7).Plus
    Case "WE2" ' weapon plus
       Temp#=UserRecord2.Weapon(7).Plus
    Case "CL" ' cloak plus
       Temp#=UserRecord.Weapon(8).Plus
    Case "CL2" ' cloak plus
       Temp#=UserRecord2.Weapon(8).Plus
    Case "RG2" ' right ring plus
       Temp#=UserRecord.Weapon(9).Plus
    Case "RG2X" ' right ring plus
       Temp#=UserRecord2.Weapon(9).Plus
    Case "AM" ' amulet plus
       Temp#=UserRecord.Weapon(10).Plus
    Case "AM2" ' amulet plus
       Temp#=UserRecord2.Weapon(10).Plus
    Case "C6" ' item charges
       Temp#=MessWorkRecord6.Charges
    Case "WP1"
       Temp#=UserRecord.Weapons(1)
    Case "WP1X"
       Temp#=UserRecord2.Weapons(1)
    Case "WP2"
       Temp#=UserRecord.Weapons(2)
    Case "WP2X"
       Temp#=UserRecord2.Weapons(2)
    Case "WP3"
       Temp#=UserRecord.Weapons(3)
    Case "WP3X"
       Temp#=UserRecord2.Weapons(3)
    Case "WP4"
       Temp#=UserRecord.Weapons(4)
    Case "WP4X"
       Temp#=UserRecord2.Weapons(4)
    Case "PROF"
       If UserRecord.Proficiency Then
          Temp#=UserRecord.Weapons(UserRecord.Proficiency)
       Else
          Temp#=0#
       Endif
    Case "PROF2"
       If UserRecord2.Proficiency Then
          Temp#=UserRecord2.Weapons(UserRecord2.Proficiency)
       Else
          Temp#=0#
       Endif
    Case "MHP"
       Temp#=MessWorkRecord3.Monster.Hits
    Case "HP2"
       Temp#=MessWorkRecord4.Hits
    Case "MEXP"
       Temp#=MessWorkRecord3.Monster.Experience
    Case "MLVL"
       Temp#=MessWorkRecord3.Monster.Level
    Case "MW" ' monster weapon plus
       If MessWorkRecord3.Weapon(1).Charges>0 Then
          Temp#=MessWorkRecord3.Weapon(1).Plus
       Else
          Temp#=0#
       Endif
    Case "MS" ' monster shield plus
       If MessWorkRecord3.Weapon(2).Charges>0 Then
          Temp#=MessWorkRecord3.Weapon(2).Plus
       Else
          Temp#=0#
       Endif
    Case "MA" ' monster armor plus 
       If MessWorkRecord3.Weapon(3).Charges>0 Then
          Temp#=MessWorkRecord3.Weapon(3).Plus
       Else
          Temp#=0#
       Endif
    Case "XX"
       Temp#=Multiplier
    Case "XXX"
       Temp#=Multiplier2
    Case "RND"
       Temp#=Rnd
    Case "WT"
       Temp#=Weight
    Case "WS"
       Temp#=UserRecord.WishsLeft
    Case "GD"
       Temp#=UserRecord.Gold
    Case "GD2"
       Temp#=UserRecord2.Gold
    Case "BR"
       Temp#=UserRecord.Brief
    Case "BR2"
       Temp#=UserRecord2.Brief
    Case "PSIA"
       Temp#=Psi.Attack.Mode
    Case "PSID"
       Temp#=Psi.Defense.Mode
    Case "MPSI"
       Temp#=MessWorkRecord3.Monster.Psionic
    Case "PI"
       Temp#=Atn(1#)*4#
    Case "E"
       Temp#=Exp(1#)
    CASE "ABS"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = ABS(Temp#)
    CASE "CBR"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Temp# ^ (1#/3#)
    Case "EXP"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = EXP(Temp#)
    CASE "FIX"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = FIX(Temp#)
    Case "LOG"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = LOG(Temp#)
    Case "NOT"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = NOT(Temp#)
    CASE "SGN"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = SGN(Temp#)
    Case "SQR"
       Call Get.Token
       Call Get.Token
       Call Parse1(Temp#)
       Temp# = SQR(Temp#)
    Case "NTH"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# ^ (1# / Temp#)
    CASE "PWR"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# ^ Temp#
    CASE "OR"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# OR Temp#
    CASE "AND"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# AND Temp#
    CASE "EQV"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# EQV Temp#
    CASE "IMP"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# IMP Temp#
    CASE "MOD"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# MOD Temp#
    CASE "XOR"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = Number# XOR Temp#
    CASE "NOR"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = NOT (Number# OR Temp#)
    CASE "NON"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = NOT (Number# IMP Temp#)
    CASE "XAN"
       CALL Get.Token
       CALL Get.Token
       CALL Parse1(Temp#)
       Number# = Temp#
       CALL Get.Token
       CALL Parse1(Temp#)
       Temp# = NOT (Number# AND Temp#)
    End Select
    Call Get.Token
 End Select
Error.Resume23i:
 Exit Sub
Error.Trap23i:
 Temp#=DFalse
 Call Display.Error(Temp#)
 Resume Error.Resume23i
End Sub

Sub Arith(Token.Parsed$,Temp#,Temp2#)
 On Local Error Goto Error.Trap23j
 Select Case Token.Parsed$
 Case "+"
    Temp#=Temp#+Temp2#
 Case "-"
    Temp#=Temp#-Temp2#
 Case "/"
    Temp#=Temp#/Temp2#
 Case "\"
    Temp#=Temp#\Temp2#
 Case "*"
    Temp#=Temp#*Temp2#
 Case "^"
    Temp#=Temp#^Temp2#
 Case "<"
    Temp#=Temp#<Temp2#
 Case ">"
    Temp#=Temp#>Temp2#
 CASE "<<"
    Temp# = Temp# * 2#
 CASE ">>"
    Temp# = Temp# \ 2#
 CASE "||"
    Temp# = Temp# * 10#
 CASE "##"
    Temp# = Temp# \ 10#
 Case "^^"
    Temp# = Temp# ^ 10#
 CASE "++"
    Temp# = Temp# + 1#
 CASE "--"
    Temp# = Temp# - 1#
 CASE "**"
    Temp# = Temp# ^ 2#
 CASE "//"
    Temp# = SQR(Temp#)
 Case "="
    Temp#=Temp#=Temp2#
 Case "<="
    Temp#=Temp#<=Temp2#
 Case ">="
    Temp#=Temp#>=Temp2#
 Case "<>"
    Temp#=Temp#<>Temp2#
 Case "^=", "^+="
    Temp#=Temp#^Temp2#
 Case "^-="
    Temp#=Temp#^(-Temp2#)
 Case "|"
    Temp#=Temp# Or Temp2#
 Case "&"
    Temp#=Temp# And Temp2#
 Case "%"
    Temp#=Temp# Mod Temp2#
 Case "~"
    Temp#=Temp# Xor Temp2#
 Case "?"
    Temp#=Temp# Imp Temp2#
 Case ":"
    Temp#=Temp# Eqv Temp2#
 CASE "#"
    Temp# = NOT (Temp# OR Temp2#)
 CASE "@"
    Temp# = NOT (Temp# IMP Temp2#)
 CASE "`"
    Temp# = NOT (Temp# AND Temp2#)
 End Select
Error.Resume23j:
 Exit Sub
Error.Trap23j:
 Temp#=DFalse
 Call Display.Error(Temp#)
 Resume Error.Resume23j
End Sub

Sub Get.Token
 On Local Error Goto Error.Trap23k
 Token.List$="-+*/\^()[]{}<>=#|&!%~?:,;@`"
 Token2$=Nul
 Token=False
 If Token.Index>Len(Out2) Then
    Token2$=Nul
    Exit Sub
 Endif
 ' get tokens of length 3
 CALL Get.Token3(Token.Exists)
 IF Token.Exists THEN
    EXIT SUB
 END IF
 ' get tokens of length 2
 CALL Get.Token2(Token.Exists)
 IF Token.Exists THEN
    EXIT SUB
 END IF
 ' get tokens of length 1
 Token.Element$=Mid$(Out2,Token.Index,1)
 If Len(Token.Element$) Then
    If Instr(Token.List$,Token.Element$) Then
       Token=1
       Token2$=Token.Element$
       Token.Index=Token.Index+1
       Exit Sub
    Endif
 Endif
 ' get numeric token
 Token.Element$=Mid$(Out2,Token.Index,1)
 If (Token.Element$>="0" And Token.Element$<="9") Or Token.Element$="." Then
    Do
       If Len(Token.Element$)=False Then
          Exit Do
       Endif
       If Instr(Token.List$,Token.Element$) Then
          Exit Do
       Endif
       Token2$=Token2$+Token.Element$
       Token.Index=Token.Index+1
       Token.Element$=Mid$(Out2,Token.Index,1)
    Loop
    Token=2
    Exit Sub
 Endif
 ' get alphabetic token
 Token.Element$=Mid$(Out2,Token.Index,1)
 If Token.Element$>="A" And Token.Element$<="Z" Then
    Do
       If Len(Token.Element$)=False Then
          Exit Do
       Endif
       If Instr(Token.List$,Mid$(Out2,Token.Index,1)) Then
          Exit Do
       Endif
       Token2$=Token2$+Token.Element$
       Token.Index=Token.Index+1
       Token.Element$=Mid$(Out2,Token.Index,1)
    Loop
    Token=3
    Exit Sub
 Endif
Error.Resume23k:
 Exit Sub
Error.Trap23k:
 Temp#=DFalse
 Resume Error.Resume23k
End Sub

' tokens of length 2
Sub Get.Token2(Token.Exists)
 On Local Error Goto Error.Trap23l
 Token.Exists = False
 Next.Token$ = MID$(Out2, Token.Index, 2)
 SELECT CASE Next.Token$
 CASE ">=", "=>"
    Token2$ = ">="
    Goto Next.Token2
 CASE "<=", "=<"
    Token2$ = "<="
    Goto Next.Token2
 CASE "<>", "><"
    Token2$ = "<>"
    Goto Next.Token2
 CASE "||", "##", "<<", ">>", "--", "++", "**", "//", "^=", "^^"
    Token2$ = Next.Token$
    Goto Next.Token2
 END SELECT
 Exit Sub
Next.Token2:
 Token = 1
 Token.Index = Token.Index + 2
 Token.Exists = True
Error.Resume23l:
 Exit Sub
Error.Trap23l:
 Temp#=DFalse
 Resume Error.Resume23l
END SUB

' tokens of length 3
Sub Get.Token3(Token.Exists)
 On Local Error Goto Error.Trap23lx
 Token.Exists = False
 Next.Token$ = MID$(Out2, Token.Index, 3)
 IF Next.Token$ = "^-=" THEN
    Token = 1
    Token2$ = "^-="
    Token.Index = Token.Index + 3
    Token.Exists = True
 END IF
 IF Next.Token$ = "^+=" THEN
    Token = 1
    Token2$ = "^+="
    Token.Index = Token.Index + 3
    Token.Exists = True
 END IF
Error.Resume23lx:
 Exit Sub
Error.Trap23lx:
 Temp#=DFalse
 Resume Error.Resume23lx
END SUB

Sub Display.Error(Temp#)
 If Err=6 Then ' overflow
    Temp#=1D308
 Endif
 If Equate.Debug Then
    Strng=Str$(Err)
    Select Case Err
    Case 5
       Strng=" Syntax error"
    Case 6
       Strng=" Overflow"
    Case 11
       Strng=" Division by zero"
    End Select
    Strng="Debug:"+Strng
    Call IO.O
 Endif
End Sub
