Let's build a transpiler! Part 16
This is the sixteenth post in a series of building a transpiler.You can find the previous ones here.
Last time I said we would start parsing whatever is inside classes and modules.
There are two different areas inside a class or a module.
The first is called the declaration area. It is there that we introduce new elements like Consts, Enums, Types, Declares, and Events.
It is there also that we set Options and Deftypes, declare variables with class, module, or global scope, and state Implements.
The second area does not have a formal name, but we'll call it the procedure area.
It is there that we implement Subs, Functions, and Propertys.
The procedure area follows the declaration area and ends it.
Any declaration area element can appear in any order, but there are interdependencies between some of them.
Deftypes must precede any variable declarations because the former may or may not affect the latter.
Option Base must precede any array variable declaration because - again - it may or may not affect them.
We'll start simple/naive and refactor our code along the way, as we deal with more complex situations.
Let's start with the options. There are three of them:
- Option Explicit forces the user to declare every variable before using it.
- Option Base sets the default to the lower subscript of array variables declared having only the upper subscript.
So, if the class or module has the statement Option Base 1 and a variable is declared as "Dim Months(12) As Integer", it is the same as the variable was declared like "Dim Months(1 To 12) As Integer".
If the class or module has an Option Base 0 statement or no Option Base at all, the declaration above would be the same as "Dim Months(0 To 12) As Integer".
Note that in the first case Months would have 12 elements, while in the second case it would have 13 elements. - The last option is Option Compare. It can be Option Compare Binary - that's the default - or Option Compare Text.
When set to Text, VB will compare strings in a case-insensitive way, so "Joe" = "joe" would return True.
If set to Binary, only "Joe" = "Joe" would return True.
(There is a fourth option, Option Compare Database, but we will not support it.)
Class Entity
Public IsClass As Boolean
Public Accessibility As Accessibility
Public Name As Token
Public OptionBase As Integer
Public OptionCompare As VbCompareMethod
Public OptionExplicit As Boolean
End Class
We will create a utility function to check if a token is a specific keyword:
Private Function IsKw(ByVal Token As Token, ByVal Name As String) As Boolean
If Token.Suffix <> vbNullChar Then Exit Function
If Token.Kind <> tkKeyword Then Exit Function
If Token.Text <> Name Then Exit Function
IsKw = True
End Function
Now, we'll create a ParseDeclarationArea function to deal with the declaration area elements, starting with Options:
Private Function ParseDeclarationArea(ByVal Entity As Entity) As Token
Dim HadBase As Boolean
Dim HadCompare As Boolean
Dim Token As Token
Do
Set Token = SkipLineBreaks
If IsKw(Token, "Option") Then
Set Token = NextToken
If IsKw(Token, "Base") Then
If HadBase Then Fail Token, "Duplicate Option statement"
HadBase = True
Set Token = NextToken
If Token.Kind <> tkIntegerNumber Or (Token.Text <> "0" And Token.Text <> "1") Then
Fail Token, "Option Base (0 | 1)", "0 or 1"
End If
Entity.OptionBase = IIf(Token.Text = "0", 0, 1)
ElseIf IsKw(Token, "Compare") Then
If HadCompare Then Fail Token, "Duplicate Option statement"
HadCompare = True
Set Token = NextToken
If IsKw(Token, "Binary") Then
Entity.OptionCompare = vbBinaryCompare
ElseIf IsKw(Token, "Text") Then
Entity.OptionCompare = vbTextCompare
Else
Fail Token, "Option Compare (Binary | Text)", "Binary or Text"
End If
ElseIf IsKw(Token, "Explicit") Then
If Entity.OptionExplicit Then Fail Token, "Duplicate Option statement"
Entity.OptionExplicit = True
Else
Fail Token, "Rule: Option (Base | Compare | Explicit)", "Option"
End If
ElseIf IsKw(Token, "End") Then
Exit Do
Else
Fail Token, "Rule: Option (Base | Compare | Explicit)", "Option"
End If
Loop
Set ParseDeclarationArea = Token
End Function
Next week we'll parse Deftypes.
Andrej Biasic
2020-11-04