Giter Site home page Giter Site logo

uwol / proleap-vb6-parser Goto Github PK

View Code? Open in Web Editor NEW
75.0 12.0 26.0 893 KB

ProLeap ANTLR4-based parser for Visual Basic 6.0

License: MIT License

ANTLR 4.20% Java 87.32% Apex 0.17% TeX 0.12% VBA 3.61% Visual Basic 6.0 4.59%
asg syntax-tree antlr vb6 grammar parser antlr4-grammar antlr4 ast

proleap-vb6-parser's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proleap-vb6-parser's Issues

Support named parameters ?

Does vb6parser support for named parameters ?
I attempted to retrieve Arg object form ArgValueAssignment. ex: follow to after

NamedParameters.cls

Sub studentInfo(ByVal name As String, Optional ByVal age As Integer = 0, Optional ByVal birth As Date = #1/1/2000#)
  Debug.Print "Name = " & name & "; age = " & CStr(age) & "; birth date = " & CStr(birth)
End Sub

Call studentInfo(age:=19, birth:=#9/21/1981#, name:="Mary")

NameParametersTest.java

  @Test
  public void test() throws Exception {
      final File inputFile = new File("src/test/resources/io/proleap/vb6/asg/call/arg/name/NamedParameters.cls");
      final Program program = new VbParserRunnerImpl().analyzeFile(inputFile);

      final Module module = program.getClazzModule("NamedParameters");

      final Sub studentInfo = module.getSub("studentInfo");
      assertNotNull(studentInfo);
      VisualBasic6BaseVisitor<Void> visitor = new VisualBasic6BaseVisitor<Void>() {

        @Override
        public Void visitArgsCall(ArgsCallContext ctx) {
          List<ArgCallContext> argCallCtxList = ctx.argCall();
          ASGElementRegistry registry = program.getASGElementRegistry();
          ArgCallContext argCallCtx = argCallCtxList.get(0);
          ArgValueAssignment argValueAssignment1 = (ArgValueAssignment) registry.getASGElement(argCallCtx);
          assertThat(argValueAssignment1.getArg().getName(), is("age")); // actual "name"
          
          ArgValueAssignment argValueAssignment2 = (ArgValueAssignment) registry.getASGElement(argCallCtx);
          assertThat(argValueAssignment2.getArg().getName(), is("birth")); // actual "age"
          
          ArgValueAssignment argValueAssignment3 = (ArgValueAssignment) registry.getASGElement(argCallCtx);
          assertThat(argValueAssignment3.getArg().getName(), is("name")); // actual "birth"
          return null;
        }
      };
      visitor.visit(module.getCtx());
  }

But, Actual Arg object mismatched to expected object.
Also, I attempted Arg object from ValueAssignment. But it's always null.

java.lang.NoClassDefFoundError: io/proleap/vb6/VisualBasic6BaseVisitor

I tried to follow the "Getting started" steps. I added the repository and dependency. My code looks like this:

package com.mycompany.app;

/**
 * Hello world!
 *
 */
public class App 
{
	
	public static io.proleap.vb6.asg.metamodel.Program program;
	
    public static void main( String[] args ) throws java.io.IOException
    {
        //System.out.println( "Hello World!" );
		
		// generate ASG from plain VB6 code
		java.io.File inputFile = new java.io.File("src/test/resources/test.cls");
		
		program = new io.proleap.vb6.asg.runner.impl.VbParserRunnerImpl().analyzeFile(inputFile);

		// traverse the AST
		io.proleap.vb6.VisualBasic6BaseVisitor<Boolean> visitor = new io.proleap.vb6.VisualBasic6BaseVisitor<Boolean>() {
		  @Override
		  public Boolean visitVariableSubStmt(final io.proleap.vb6.VisualBasic6Parser.VariableSubStmtContext ctx) {
			io.proleap.vb6.asg.metamodel.Variable variable = (io.proleap.vb6.asg.metamodel.Variable) program.getASGElementRegistry().getASGElement(ctx);
			String name = variable.getName();
			io.proleap.vb6.asg.metamodel.type.Type type = variable.getType();

			return visitChildren(ctx);
		  }
		};

		for (final io.proleap.vb6.asg.metamodel.Module module : program.getModules()) {
		  visitor.visit(module.getCtx());
		}
		
		
    }
}

The building is successful. But if I try to run it, I get this error:

Error: Unable to initialize main class com.mycompany.app.App
Caused by: java.lang.NoClassDefFoundError: io/proleap/vb6/VisualBasic6BaseVisitor

What do I wrong? Did I miss something?

My test.cls is the same as the "Input: VB6 code" from the example

Line numbers not supported

1    MsgBox("Line 1")
2    MsgBox("Line 2")
3    MsgBox("Line 3")

line 116:0 extraneous input '1' expecting {END_SUB, NEWLINE}

Not sure how complex this is to implement honestly. I can probably get around it by stripping out line numbers before sending the files to the parser, but maybe somebody else needs it, who knows.

Thanks.

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

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

Suggested changes

Hello,
I made some changes that are not errors, but are necessary for my project.

Following is a description of the changes in VisualBasic6.g4.

This change allows the Object.Value expression to the default value of the parameter.
argDefaultValue
: EQ WS? (literal | ambiguousIdentifier (DOT ambiguousIdentifier)*)
;

This change allows the expression Object.value(0)(1).method param
iCS_S_ProcedureOrArrayCall
: (ambiguousIdentifier | baseType) typeHint? WS? ( LPAREN WS? (argsCall WS?)? RPAREN )+ dictionaryCallStmt?
;

// letters

The next change is because my language is Brazilian Portuguese, although we do not recommend to programmers to create variables or methods with accentuation I located this use in several parts of the code.
fragment LETTER
: [a-zA-Z_äöüÄÖÜáéíóúÁÉÍÓÚâêîôûÂÊÎÔÛàèìòùÀÈÌÒÙãẽĩõũÃẼĨÕŨçÇ]
;
fragment LETTERORDIGIT
: [a-zA-Z0-9_äöüÄÖÜáéíóúÁÉÍÓÚâêîôûÂÊÎÔÛàèìòùÀÈÌÒÙãẽĩõũÃẼĨÕŨçÇ]
;

ASG only available for BAS/CLS?

I'm not a VB6 programmer but should write some analysis tools for existing VB6 applications. The ASG feature sounds promising, but I'm wondering why this is limited to CLS and BAS files. From an AST point of view Forms are matching the structure of a BAS module, so it doesn't seem to be a technical restriction.
Happy to get some feedback!

About the many issues fixed in Rubberduck's fork

FYI - Rubberduck PR 4068 fixed an interesting edge case that I don't think this version of the grammar handles. Consider this legal VBA/VB6 code:

For x = 1 To 10
For Each c In Items
For y = 1 To 10
'....
Next y, c, x

A number of special-form VB6-specific syntaxes were also added; VB6 MSForms are now handled too, and so many other things now diverge rather significantly between this version and Rubberduck's.

Many, many commits were made to Rubberduck's grammar since 2016, so much that I'm struggling to figure out a way to contribute the grammar file back - the lexer grammar was separated from the parser grammar, for one; another thing is that the grammar now includes a Rubberduck-specific '@Annotation argument-capable comment syntax that I believe shouldn't be in a VBA/VB6 grammar outside of Rubberduck; precompiler rules were pulled into their own grammar, as Rubberduck only provides the parser with the "live" code (precompiler directives are literally interpreted to achieve that); more specialized expression grammars (e.g. Like syntax) have spawned, too.

Line numbers & labels, line continuations, superfluous parentheses at call sites, and various other things, are among the issues likely still present in this version, fixed in Rubberduck's current/latest grammar.

I would want to bring all (most?) these fixes into here, but it would very very very likely be a complete wreck of a breaking change for anyone using it. OTOH, the Rubberduck fork correctly parses quite a lot of things (including lots of edge cases) that the original grammar didn't... but re-implementing all these changes in this version would be rather daunting. Not sure how similar this version is to the original version we forked all the way back in 2014 (2015?).

What would you recommend? Is status-quo ok?

I also just noticed that this repo is under MIT and not GPLv3 like the original grammar we used back then... not sure what that entails, Rubberduck is GPLv3.

Optional Argument

Hello,
In the sample call below

MetodoCall Param1, , Param2

The ArgsCallContext returns 2 arguments and 2 commas.
With the 2 commas I detect that there are 3 parameters, but the order of them is not detectable.
Is there an example of how to detect the second null parameter?

Maven artefact not available

I notice that in the commit to the readme on July 24th 2018 and 23rd September 2018, the instructions to use the repository http://maven.proleap.io have been removed, and the current instructions seem to point to using a standard maven central hosted artefact.

However, I am unable to locate the artefact on maven central, and maven.proleap.io has been taken down.

Is there an official location for the artefact?

get*Calls returns type members with the same name

MyClass.cls

Public Function MyFunction() As String
    MyFunction = "MyFunction"
End Function

Public Sub MySub()
    DoEvents
End Sub

MyModule.bas

Public Type MyType
    MyFunction As String
    MySub As String
End Type

Public Sub Test()
    Dim MyTypeInstance As MyType
    
    MyTypeInstance.MyFunction = "MyModule" ' not detected as a call - fine
    MsgBox MyTypeInstance.MyFunction ' detected as a call - wrong
    
    MyTypeInstance.MySub = "MySub" ' not detected as a call - fine
    MsgBox MyTypeInstance.MySub ' detected as a call - wrong
End Sub

VB6Parser

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

for (FunctionCall functionCall : program.getClazzModule("MyClass").getFunction("MyFunction").getFunctionCalls()) {
    ParserRuleContext ctx = (ParserRuleContext)functionCall.getCtx();
    System.out.println("Function Call: " + ctx.getText() + " (line: " + ctx.start.getLine() + ") (pos: " + ctx.start.getCharPositionInLine() + ")");
}

for (SubCall subCall : program.getClazzModule("MyClass").getSub("MySub").getSubCalls()) {
    ParserRuleContext ctx = (ParserRuleContext)subCall.getCtx();
    System.out.println("Sub Call: " + ctx.getText() + " (line: " + ctx.start.getLine() + ") (pos: " + ctx.start.getCharPositionInLine() + ")");
}

Result

Function Call: MyFunction (line: 13) (pos: 26)
Sub Call: MySub (line: 16) (pos: 26)

Expected Result

Emtpy result as there're no calls.

If I'm not wrong this error happens with getFunctionCalls, getSubCalls, getPropertyGetCalls, getPropertyLetCalls, and getPropertySetCalls functions.

By the way, I'm using this to create a small obfuscator applying source code transformations to prevent abusers from cracking or abusing my software.

This parser is just perfect, thank you so much for saving me countless hours of learning and research time.

Variation in the SSTab statement

The TabDlg.SSTab object uses a variation in the declaration that generates errors in the parse of frm files.
Here is an example of a layout.
       TabCaption (0) = "& Location"
       Tab (0) .ControlEnabled = -1 'True
       Tab (0) .Control (0) = "lblEst"
       Tab (0) .Control (0) .Enabled = 0 'False

VB6 Designer files throw parsing error

An example moduleConfig for a VB6 .dsr-file looks like this.

Begin {2D4C5A66-E9BE-4274-8824-E181D24D3C7E} myThing
    Caption         = "myThing"
    ClientHeight    = 10000
    ClientLeft      = 100
    ClientTop       = 100
    ClientWidth     = 10000
    StartUpPosition = 3  'Windows Default
    _ExtentX        = 28000
    _ExtentY        = 24000
    SectionData     = "myThing.dsx":0000
End

Trying to parse it, following exception is thrown.

[main] INFO io.proleap.vb6.asg.runner.impl.VbParserRunnerImpl - Parsing file myThing.dsr with charset UTF-8.
Exception in thread "main" io.proleap.vb6.asg.exception.VbParserException: syntax error in line 1:6 no viable alternative at input 'Begin {2D4C5A66-E9BE-4274-8824-E181D24D3C7E}'

Removing the GUID and the name makes it parseable again.

SelectCase test fails for case expression list

The test for SelectCase fails for following input.

Select Case Percent
	Case 0 To 25, 26 To 45
		Beep
	Case Else
		Beep
End Select

The parser throws "no viable alternative at input 'To 45'." Seems like sc_Cond rule is missing INTEGERLITERAL WS TO WS valueStmt (WS? COMMA WS? ((INTEGERLITERAL WS TO WS valueStmt) | (valueStmt)))* # caseCondExpressionList

VB6 string concatenation with TextBox.Text$ not working

I'm using the VB6.g4 grammar file. It seems to throw an exception on statements like filepath$ = filename.Text$ & "\abc" & filepath$ & ".txt" and If Func1(filname.Text$ & "\Logfiles", True) = True Then.
Removing the $ from filename.Text$ would solve the issue but I would've expected the grammar to successfully match the statement. So I'm trying to understand why $ is throwing off the parser.

Any help in identifying the problem is much appreciated!

On Local Error not supported

MyModule.bas

Private Sub MyFirstSub()
On Local Error GoTo ErrHandler
        
    MsgBox "MyFirstSub"
    Exit Sub

ErrHandler:
End Sub

Private Sub MySecondSub()
    MsgBox "MySecondSub"
End Sub

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.
Found declared module name MyModule.
Collecting types in file MyModule.bas.
Analyzing declaration of module MyModule.
line 5:9 no viable alternative at input 'On Local Error'
line 5:3 mismatched input 'Local' expecting <EOF>
Analyzing expressions of module MyModule.
call to unknown element VB_Name
Analyzing type assignments of module MyModule.
Analyzing type assignments of module MyModule.
Analyzing type assignments of module MyModule.
Analyzing type assignments of module MyModule.
Sub: MyFirstSub

Expected Result

Sub: MyFirstSub
Sub: MySecondSub

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.