home *** CD-ROM | disk | FTP | other *** search
- Attribute VB_Name = "APIMOD1"
- ' Copyright (c) 1996 by Desaware
- ' Part of the Desaware API Toolkit
- ' All Rights Reserved
-
- Option Explicit
-
- Global Separators$ ' Separators between tokens
- Global Const ReturnType$ = "%&!#@$"
- Global ReturnTypeName$(7) ' Individual names
-
- ' State for parsing
- ' 0 = Normal
- ' 1 = In quote
- Dim ParseState%
-
- ' Location of special characters in string
- Const idComment% = 4 ' ' character
- Const idSpace% = 1 ' Space character
- Const IdTab% = 7 ' Tab character
- Const idQuote% = 8 ' " character
- Const idLineCont% = 5 ' _ - Line continuation char
-
- ' State machine information
- Dim MajorState% ' Major state as follows:
- ' 0 - Clear
- ' 1 - In Comment
- ' 2 - In Declare
- ' 3 - In Type
- ' 4 - In Global
- Dim MinorState% ' Used by individual state machines as follows
-
- ' Current category description (via '')
- Global Category$
-
- ' Object identification information
- Type paramType
- ParamName As String ' Name of parameter
- paramType As String
- IsArray As Integer
- IsByVal As Integer
- End Type
-
- Global objType% ' 0 = Clear
- ' 1 = Sub
- ' 2 = Function
- ' 3 = Type
- ' 4 = Constant
-
- Global objName$ ' Name of the object
- Global objLib$ ' Library or value for globals
- Global objAlias$ ' Alias
- Global objReturn% ' Return type (VB char) - See ReturnTypes$
- ' 0 - Variant (default)
- ' 1 - Integer, 2 - Long, 3 - Single, 4 - Double
- ' 5 - Currency, 6 - String, 7 - Object
-
- Global pDesc() As paramType ' Array of parameter names or type field names
-
- '
- ' Initialize the constants
- '
- Sub am1Initialize()
- ' Characters that separate the tokens
- Separators$ = " ()'_," & Chr$(9) & Chr$(34) & "%#$!@&="
- ' We append the tab and " character as well
-
- ReturnTypeName(0) = "Variant"
- ReturnTypeName(1) = "Integer"
- ReturnTypeName(2) = "Long"
- ReturnTypeName(3) = "Single"
- ReturnTypeName(4) = "Double"
- ReturnTypeName(5) = "Currency"
- ReturnTypeName(6) = "String"
- ReturnTypeName(7) = "Object"
- End Sub
-
- '
- ' This is the main input line for the state machine
- ' InputString$ is the string read from the file.
- ' Returns 0 on success.
- ' Returns 1 On object ready.
- ' Returns 2 on syntax error.
- '
- Function am1ParseLine%(ByVal InputString$)
- Dim s$
- Dim res% ' Set by state machines to return value (above)
- Dim TokenRes%
-
- InputString$ = Trim(InputString$) ' Trim whitespace
-
- Do ' We'll loop through every token in the string
- s$ = GetToken1(InputString$, TokenRes%)
- ' Debug.Print s$, MajorState% & "." & MinorState%
- ' How the string is handled depends on the state
- Select Case MajorState%
- Case 0 ' Clear state
- res% = ProcessClearState(s$, TokenRes%)
- Case 1 ' Processing Comment
- res% = ProcessCommentState(s$, TokenRes%)
- Case 2 ' Processing Declaration
- res% = ProcessDeclareState(s$, TokenRes%)
- Case 3 ' Processing User Type
- res% = ProcessTypeState(s$, TokenRes%)
- Case 4 ' Processing Global
- res% = ProcessGlobalState(s$, TokenRes%)
- End Select
- Loop While Len(s$) > 0
-
- am1ParseLine% = res%
-
- End Function
-
- '
- ' Returns the position of the next separator.
- ' Valid separator is any separator unless ParseState% is 1, in which
- ' case only a quote is valid.
- ' TokenId% is the location of the token in the separator string
- '
- Function FindSeparator%(InputString$, TokenId%)
- Dim InputLength%
- Dim c%
-
- If ParseState% = 1 Then ' Find next quote only
- c% = InStr(InputString$, Chr$(34))
- If c% > 0 Then
- TokenId% = InStr(Separators$, Chr$(34))
- End If
- FindSeparator = c%
- Exit Function
- End If
-
- InputLength% = Len(InputString$)
- For c% = 1 To InputLength%
- TokenId% = InStr(Separators$, Mid$(InputString$, c%, 1))
- Select Case TokenId%
- Case 0 ' Ignore - it's not a separator
-
- Case idLineCont
- ' A line continuation character is valid only
- ' if it is the first character in the string
- If c% = 1 Then
- FindSeparator = c%
- Exit Function
- End If
- Case Else
- ' This character is a separator
- FindSeparator = c%
- Exit Function
- End Select
-
- Next c%
-
- FindSeparator = 0
- TokenId% = 0
-
- End Function
-
- '
- ' Retrieves the left token from the input string, modifies
- ' the input string to remove the token. Ignores white space
- ' result% = 0 - on success, 1 - Missing close quote
- '
- Function GetToken1$(instring$, result%)
- Dim maxlen%
- Dim Separatorloc%, Quote2%
- Dim TokenId%
- Dim Quote2Loc%
- result% = 0
- maxlen% = Len(instring$)
- If maxlen% = 0 Then ' Empty string
- GetToken1$ = instring$
- result% = 0
- End If
-
- Separatorloc% = FindSeparator(instring$, TokenId%)
- Select Case Separatorloc%
- Case 0 ' Just retrieve through the rest of the line
- GetToken1 = instring$
- instring$ = ""
-
- Case 1 ' First char is a separator
- ' Special cases are comment and quote
- Select Case TokenId%
- Case idQuote% ' Return quoted string as a single token
- ParseState% = 1
- Quote2% = FindSeparator(Mid$(instring$, 2), TokenId%) + 1
- ParseState% = 0
- If Quote2% <= 1 Then
- result% = 1
- Exit Function
- Else
- GetToken1$ = Left$(instring$, Quote2%)
- If maxlen% > Quote2% Then instring$ = Mid$(instring$, Quote2% + 1) Else instring$ = ""
- Exit Function
- End If
- Case idComment% ' Return comment as a single token
- GetToken1$ = instring$
- ' If there's a line continuation at the end, parse it separately
- TrimWhiteSpace instring$, 2 ' Trim trailing spaces
- If instring$ = "" Then Exit Function
- If InStr(Separators$, Right$(instring$, 1)) = idLineCont Then
- ' Check if it's a line continuation
- maxlen% = Len(instring$)
- TokenId% = InStr(Separators$, Mid$(instring$, maxlen% - 1, 1))
- If TokenId% = idSpace Or TokenId% = IdTab Then
- GetToken1$ = Left(instring$, maxlen% - 1)
- instring$ = Right$(instring$, 1)
- Exit Function
- End If
- End If
- instring$ = ""
- Case idSpace%, IdTab% ' It's whitespace
- TrimWhiteSpace instring$, 1
- If Len(instring$) > 0 Then
- ' Recursive call on rest of string
- GetToken1 = GetToken1(instring$, TokenId%)
- Else
- GetToken1$ = ""
- instring$ = ""
- End If
- Case Else
- ' All other separators are tokens
- GetToken1$ = Left$(instring$, 1)
- If maxlen% > 1 Then
- instring$ = Mid$(instring$, 2)
- Else
- instring$ = ""
- End If
-
- End Select
-
-
- Case Else ' First char is not a separator
- ' Return the string up to the separator
- GetToken1$ = Left$(instring$, Separatorloc% - 1)
- instring$ = Mid$(instring$, Separatorloc%)
- End Select
-
-
-
-
- End Function
-
- '
- ' Checks the string against the return type name array
- ' to find out which return type it is.
- ' Returns -1 on error
- '
- Function GetTypeValue%(s As String)
- Dim x%
- Dim us$
- us$ = UCase$(s)
- For x = 0 To UBound(ReturnTypeName)
- If us$ = UCase$(ReturnTypeName(x)) Then
- GetTypeValue% = x
- Exit Function
- End If
- Next x
-
-
- End Function
-
- '
- ' MajorState% is zero - processes the clear
- ' MinorState% = 0 - Normal entry
- ' 1 - Line term pending
- Function ProcessClearState%(s As String, TokenRes%)
- Select Case UCase$(s)
- Case "DECLARE"
- MajorState% = 2
- MinorState% = 0
- Case "PUBLIC"
- MajorState% = 4
- MinorState% = 0
- Case "TYPE"
- MajorState% = 3
- MinorState% = 0
- Case "GLOBAL"
- MajorState% = 4
- MinorState% = 0
- Case "_"
- MinorState% = 1
- Case Else
- If s = "REM" Or Left$(s, 1) = "'" Then ' It's a comment
- MajorState% = 1
- MinorState% = 0
- If Len(s) > 1 Then
- If Mid$(s, 2, 1) = "'" Then
- ' Double '' sets current category
- If Len(s) > 2 Then
- Category$ = Mid$(s, 3)
- TrimWhiteSpace Category$, 3
- End If
- End If
- End If
- Else
- MinorState% = 0
- ' Anything else is simply ignored
- End If
- End Select
- ' Clear state never terminates an object
- ProcessClearState% = 0
- End Function
-
- '
- ' Comment state
- ' MinorState% = 0 - In comment, throw out everything
- ' 1 - Line continuation received, watch for newline
- ' Exit on receipt of new line.
- ' If anything else arrives, throw it out
- '
- Function ProcessCommentState%(s As String, TokenRes%)
- Select Case s
- Case "_"
- MinorState% = 1
- Case ""
- ' If newline arrived, if last item was line continuation
- ' stay in comment state for next line
- ' Otherwise, switch back to clear state
- Select Case MinorState%
- Case 0
- MajorState% = 0
- Case Else
- MinorState% = 0
- End Select
- Case Else
- MinorState% = 0
- End Select
-
- ' Just ignore anything else
- ProcessCommentState = 0
- End Function
-
- '
- ' Declare state
- ' MinorState% = 0 - Entry point
- ' 1 - Processing comment
- '
- ' Exit on receipt of new line.
- ' If anything else arrives, throw it out
- '
- ' MinorState 0 - Declare received
- ' 1 - Comment
- ' 2 - Syntax error found - throw away rest
- ' 3 - Sub,Function received, waiting on name
- ' 4 - Name received, waiting on lib
- ' 5 - Lib received, waiting on lib name
- ' 6 - Libname recorded, waiting on ( or Alias
- ' 7 - Alias received waiting on Aliasname
- ' 8 - Aliasname received, waiting on (
- ' 9 - Start of parameter
- ' 10 - ) received, can get EOL, comment or As
- ' 11 - Type word received
- ' 12 - Like 9, except ByVal received
- ' 13 - Just processed param name
- ' 14 - Appending array info to var name
- ' 15 - AS received, waiting for type
- ' 16 - Full parameter received, look for , or )
- '
- '
- Function ProcessDeclareState%(s As String, TokenRes%)
-
- Static lineterm% ' Separate state machine for line timer character
- Static CompletionState% ' Set to 1 on legal statement
- Static CurParamNum%
-
- If CompletionState% = 0 Then CompletionState% = 2 ' Default to error state
-
- ' The following conditions apply regardless of minor state
- Select Case s
- Case "_"
- lineterm% = True
- ProcessDeclareState% = 0
- Exit Function
- Case ""
- If Not lineterm% Then
- MajorState% = 0
- MinorState% = 0
- ProcessDeclareState% = CompletionState%
- Exit Function
- End If
- lineterm% = False
- Case Else
- lineterm% = False
- If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
- ' Enter internal comment state
- ProcessDeclareState% = 0
- MinorState% = 1
- Exit Function
- End If
- End Select
-
-
- Select Case MinorState%
- Case 0
- objName$ = ""
- objLib$ = ""
- objAlias$ = ""
- objReturn% = 0
- Select Case UCase$(s)
- Case "SUB"
- objType = 1
- ReDim pDesc(0)
- MinorState% = 3
- Case "FUNCTION"
- objType = 2
- ReDim pDesc(0)
- MinorState% = 3
- Case Else
- objType = 0
- MinorState% = 2
- End Select
- CompletionState% = 2 ' Set error status
- Case 1, 2 ' Internal comment mode or syntax error
- ' Just ignore everything - top level will
- ' handle it
- Case 3
- If Len(s) = 1 And InStr(Separators, s) Then
- ' Not a legal name
- MinorState% = 2
- Else
- objName$ = s
- objReturn% = 0 ' Default variant
- MinorState% = 4
- End If
- Case 4 ' We might also get type char at this point
- If Len(s) = 1 And objReturn% = 0 And InStr(ReturnType$, s) > 0 Then
- ' It's a type character
- objReturn% = InStr(ReturnType$, s)
- ' Stay in current minor state for lib
- ' Multiple type chars are not detected as error
- Else
- If UCase$(s) = "LIB" Then MinorState% = 5 Else MinorState% = 2
- End If
- Case 5
- If Left$(s, 1) <> Chr$(34) Or Len(s) < 3 Or TokenRes% = 1 Then
- MinorState% = 2
- Else
- MinorState% = 6
- objLib$ = Mid$(s, 2, Len(s) - 2)
- End If
- Case 6
- Select Case UCase$(s)
- Case "("
- MinorState% = 9
- Case "ALIAS"
- MinorState% = 7
- Case Else
- MinorState% = 2
- End Select
- Case 7
- If Left$(s, 1) <> Chr$(34) Or Len(s) < 3 Or TokenRes% = 1 Then
- MinorState% = 2
- Else
- MinorState% = 8
- objAlias$ = Mid$(s, 2, Len(s) - 2)
- End If
- Case 8
- If s = "(" Then MinorState% = 9 Else MinorState% = 2
- Case 9, 12 ' ( received (or , on prev param), processing param
- Select Case UCase$(s)
- Case ")" ' Possible legal state
- CompletionState = 1
- MinorState = 10
- Case "BYVAL"
- If MinorState% = 12 Then
- MinorState% = 2
- Else
- MinorState% = 12
- End If
- Case Else
- If Len(s) = 1 And InStr(Separators, s) Then
- MinorState% = 2
- Else
- ' Record the name
- CurParamNum = UBound(pDesc) + 1
- ReDim Preserve pDesc(CurParamNum)
- pDesc(CurParamNum).ParamName = s
- If MinorState% = 12 Then pDesc(CurParamNum).IsByVal = True
- MinorState% = 13
- End If
-
- End Select
- Case 10 ' Only "AS" acceptable
- If UCase$(s) = "AS" And objReturn% = 0 Then MinorState% = 11 Else MinorState% = 2
- CompletionState% = 2 ' Must finish
- Case 11
- objReturn% = GetTypeValue(s)
- If objReturn% >= 0 Then CompletionState% = 1
- Case 13
- Select Case UCase$(s)
- Case "("
- MinorState% = 14
- pDesc(CurParamNum).IsArray = True
- Case "AS"
- MinorState% = 15
- Case ","
- MinorState% = 9 ' Get ready for next
- Case Else
- ' It might be a type character
- If Len(s) = 1 And InStr(ReturnType$, s) > 0 Then
- pDesc(CurParamNum).paramType = ReturnTypeName(InStr(ReturnType$, s))
- ' pDesc(CurParamNum).ParamType = InStr(ReturnType$, s)
- MinorState% = 16
- Else
- MinorState% = 2
- End If
-
- End Select
- Case 14
- If s = ")" Then
- MinorState% = 13
- End If
- Case 15
- pDesc(CurParamNum).paramType = s
- MinorState% = 16
- 'objReturn% = GetTypeValue(s)
- 'If objReturn% >= 0 Then
- ' pDesc(CurParamNum).ParamType = objReturn%
- ' MinorState% = 16
- 'Else
- ' MinorState% = 2
- 'End If
- Case 16
- Select Case s
- Case ","
- MinorState% = 9
- Case ")"
- CompletionState% = 1
- MinorState% = 10
- Case Else
- MinorState% = 2
- End Select
-
- End Select
-
-
-
-
-
- End Function
-
- '
- ' Declare state
- ' MinorState% = 0 - Entry point
- ' 1 - Processing comment
- '
- ' Exit on receipt of new line.
- ' If anything else arrives, throw it out
- '
- ' MinorState 0 - Global or Public received
- ' 1 - Comment
- ' 2 - Syntax error found - throw away rest
- ' 3 - Const received, waiting on name
- ' 4 - Name received, waiting on =
- ' 5 - = received, waiting on Value
- '
- '
- Function ProcessGlobalState%(ByVal s$, TokenRes As Integer)
-
- Static lineterm% ' Separate state machine for line timer character
- Static CompletionState% ' Set to 1 on legal statement
-
- If CompletionState% = 0 Then CompletionState% = 2 ' Default to error state
-
- ' The following conditions apply regardless of minor state
- Select Case s
- Case "_"
- lineterm% = True
- ProcessGlobalState% = 0
- Exit Function
- Case ""
- If Not lineterm% Then
- MajorState% = 0
- MinorState% = 0
- ProcessGlobalState% = CompletionState%
- Exit Function
- End If
- lineterm% = False
- Case Else
- lineterm% = False
- If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
- ' Enter internal comment state
- ProcessGlobalState% = 0
- MinorState% = 1
- Exit Function
- End If
- End Select
-
-
- Select Case MinorState%
- Case 0
- objName$ = ""
- objLib$ = ""
- Select Case UCase$(s)
- Case "CONST"
- objType = 4
- MinorState% = 3
- Case Else
- objType = 0
- MinorState% = 2
- End Select
- CompletionState% = 2 ' Set error status
- Case 1, 2 ' Internal comment mode or syntax error
- ' Just ignore everything - top level will
- ' handle it
- Case 3
- If Len(s) = 1 And InStr(Separators, s) Then
- ' Not a legal name
- MinorState% = 2
- Else
- objName$ = s
- MinorState% = 4
- End If
- Case 4 ' We might also get type char at this point
- If s = "=" Then
- MinorState% = 5
- objLib$ = ""
- Exit Function
- End If
-
- If Len(s) = 1 And InStr(ReturnType$, s) > 0 Then
- ' It's a type character
- objReturn% = InStr(ReturnType$, s)
- Else
- MinorState% = 2
- End If
- Case 5
- objLib$ = objLib$ & s ' Keep adding to value
- CompletionState% = 1
- End Select
- End Function
-
- '
- ' Type state
- ' MinorState% = 0 - Entry point
- ' 1 - Processing comment
- '
- ' Exit on receipt of new line.
- ' If anything else arrives, throw it out
- '
- ' MinorState 0 - Type received waiting on name or comment
- ' 1 - Comment
- ' 2 - Syntax error found - throw away rest
- ' 3 - Ready for first Field name
- ' 4 - Comment during Field
- ' 5 - Field name recorded
- ' 6 - End received, waiting on type
- ' 7 - Comment after completion
- '
- '
- '
- '
- Function ProcessTypeState%(ByVal s$, TokenRes%)
-
- Static CompletionState% ' Set to 1 on legal statement
- Static lineterm% ' Separate state machine for line timer character
- Static CurrentParamNum%
-
- If CompletionState% = 0 Then CompletionState% = 2 ' Default to error state
-
- Select Case s
- Case "_"
- lineterm% = True
- ProcessTypeState% = 0
- Exit Function
- Case ""
- If lineterm% Then
- ' No change to state for Types
- lineterm% = False
- Exit Function
- End If
- lineterm% = False
- Case Else
- lineterm% = False
- End Select
-
-
- Select Case MinorState%
- Case 0
- If (Len(s) = 1 And InStr(Separators$, s) > 0) Or s = "" Then
- MinorState% = 2
- Exit Function
- End If
- objType = 3
- objName$ = s
- ReDim pDesc(0) ' Clear array
- MinorState% = 3
-
- Case 1 ' It's a comment
- ' True EOL means time for next variable
- If s = "" Then MinorState% = 3
-
- Case 2
- If s = "" Then
- MajorState = 0
- ProcessTypeState% = CompletionState%
- End If
-
- Case 3
- If s = "" Then Exit Function 'Ignore extra lines
- If UCase$(s) = "END" Then
- MinorState% = 6
- Exit Function
- End If
-
- If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
- MinorState% = 4
- Exit Function
- End If
- If (Len(s) = 1 And InStr(Separators$, s) > 0) Then
- MinorState% = 2
- Exit Function
- End If
- CurrentParamNum = UBound(pDesc) + 1
- ReDim Preserve pDesc(CurrentParamNum)
- pDesc(CurrentParamNum).ParamName$ = s
- MinorState% = 5
-
- Case 4
- If s = "" Then MinorState% = 3
-
- Case 5
- If Left$(s, 1) = "'" Or UCase$(s) = "REM" Then
- MinorState% = 4
- Exit Function
- End If
- If s = "" Then ' Line end
- MinorState% = 3
- Exit Function
- End If
- pDesc(CurrentParamNum).ParamName$ = pDesc(CurrentParamNum).ParamName$ & " " & s
-
- Case 6
- Select Case UCase$(s)
- Case "TYPE"
- MinorState% = 7
- CompletionState% = 1
- Case Else
- MinorState% = 2
- End Select
-
- Case 7
- If s = "" Then
- MajorState% = 0
- MinorState% = 0
- ProcessTypeState% = CompletionState%
- End If
-
- End Select
-
- End Function
-
- '
- ' Trims whitespace from string per mode
- ' mode 1 = left, 2 = right, 3 = both
- '
- Sub TrimWhiteSpace(s$, ByVal mode%)
- Dim ch%
- If s$ = "" Then Exit Sub
- If mode% And 1 Then
- Do
- ch% = Asc(s$)
- If ch% = 32 Then s$ = LTrim$(s$)
- If ch% = 9 Then
- If Len(s$) > 1 Then s$ = Mid$(s$, 2) Else s$ = ""
- End If
- Loop While s$ <> "" And (ch% = 32 Or ch% = 9)
- End If
- If mode% And 2 Then
- Do
- ch% = Asc(Right$(s$, 1))
- If ch% = 32 Then s$ = RTrim$(s$)
- If ch% = 9 Then
- If Len(s$) > 1 Then s$ = Mid$(s$, 1, Len(s$) - 1) Else s$ = ""
- End If
- Loop While s$ <> "" And (ch% = 32 Or ch% = 9)
- End If
-
-
- End Sub
-
-