uwol / proleap-vb6-parser

ProLeap ANTLR4-based parser for Visual Basic 6.0
MIT License
79 stars 26 forks source link

Precompilation directives not supported (#If, #Else, #ElseIf, #End If, #Const) #5

Closed zbagz closed 7 years ago

zbagz commented 7 years ago

MyModule.bas

Option Explicit

#Const ReturnsByte = 0

#If ReturnsByte = 1 Then
Public Function FirstFunction() As Byte
#ElseIf ReturnsByte = 0 Then
Public Function FirstFunction() As Integer
#End If
    FirstFunction = 1
End Function

Public Function SecondFunction() As Byte
    SecondFunction = 2
End Function

VB6Parser

Program program = new io.proleap.vb6.asg.runner.impl.VbParserRunnerImpl().analyzeDirectory(inputDirectory);

for (Statement statement: program.getModule("MyModule").getStatements()) {
    System.out.println(statement.getStatementType().toString() + ": " + ((Procedure)statement).getName());
}

Result

Parsing file MyModule.bas.
line 4:0 mismatched input '#Const' expecting <EOF>

Result without #Const directive

Parsing file MyModule.bas.
line 6:0 no viable alternative at input '#If ReturnsByte = 1 Then\r\nPublic Function FirstFunction() As Byte\r\n#ElseIf'
line 4:4 mismatched input 'ReturnsByte' expecting <EOF>

Expected Result

Function: FirstFunction
Function: SecondFunction
uwol commented 7 years ago

Yes, this is a known bug. To be able to parse the examples given by you, we would need a preprocessor based on its own grammar, wich parses those precompilation directives, executes them, and generates valid output VB6 source code. That output then could be parsed by the main parser/grammar.

I have implemented that exact process in case of cobol85parser, as COBOL heavily depends on COPY REPLACE statements, but unfortunately do not have time to implement the process for VB6 right now.

However, the VB6 parser should be able to cope with precompilation directives, if they contain valid VB6 code like such:

#If ReturnsByte = 1 Then
Public Function FirstFunction() As Byte
    FirstFunction = 1
End Function
#ElseIf ReturnsByte = 0 Then
Public Function FirstFunction() As Integer
    FirstFunction = 1
End Function
#End If
zbagz commented 7 years ago

At the time of opening this issue I didn't realize this should be done with a preprocessor. I'm doing something very similar to what you proposed in my tool now: evaluating expressions and skipping those lines that aren't needed in a way that the parser receives, "normalized", valid vb6 code. Thank you Ulrich!