Skip to content

Visual Basic 6 lexer & parser written in TypeScript using ANTLR 4 & ANTLR4TS

License

Notifications You must be signed in to change notification settings

brucificus/vb6-antlr4-typescript

Repository files navigation

vb6-antlr4

Dependabot Status Libraries.io dependency status for latest release npm latest release License Release semantic-release Gitmoji PRs Welcome Commitizen friendly Awesome Badges

A Visual Basic 6 lexer & parser that provides both visitor and listener patterns to traverse the parse tree. The parser is based on grammar that has been test-driven and successfully applied to large Visual Basic 6.0 projects.

Overview

This is a continuous-delivery focused synthesis of the ProLeap Visual Basic 6.0 parser's ANTLR4 grammar and the Optimized ANLTR TypeScript target provided by antlr4ts.

  • Releases: See the GitHub Releases page for release notes and links to the distribution.

  • Feedback: Got a feature request to make, or a bug to complain about? Depending on the nature of your feedback, it probably needs to go to one of three places:

    If in doubt, talk to us first so we can try to point you in the right direction.

Features

  • The grammar is line-based and takes into account whitespace, so that member calls (e.g. A.B) are distinguished from contextual object calls in WITH statements (e.g. A .B).
  • Keywords can be used as identifiers depending on the context, enabling e.g. A.Type, but not Type.B.
  • The ANTLR4 grammar is derived from the Visual Basic 6.0 language reference and tested against MSDN VB6 statement examples as well as several Visual Basic 6.0 code repositories.
  • Rigorous test-driven development.

Getting started

  1. Install vb6-antlr4 and antlr4ts as dependencies using your preferred package manager.
npm install vb6-antlr4 antlr4ts --save
yarn add vb6-antlr4 antlr4ts
  1. Use your grammar in TypeScript (or JavaScript)
import { VisualBasic6Lexer, VisualBasic6Parser } from "vb6-antlr4";
import { ANTLRInputStream, CommonTokenStream } from "antlr4ts";

// Create the lexer and parser
let inputStream = new ANTLRInputStream(`
Private Sub Command1_Click ()
   Text1.Text = "Hello, world!"
End Sub
`);
let lexer = new VisualBasic6Lexer(inputStream);
let tokenStream = new CommonTokenStream(lexer);
let parser = new VisualBasic6Parser(tokenStream);

let tree = parser.startRule();

The two main ways to inspect the tree are by using a listener or a visitor, you can read about the differences between the two here.

Listener Approach
// ...
import { VisualBasic6Listener, SubStmtContext } from "vb6-antlr4";
import { ParseTreeWalker } from "antlr4ts/tree";

class EnterSubListener implements VisualBasic6Listener {
  enterSubStmt(context: SubStmtContext) {
    console.log(`Sub start line number ${context._start.line}`);
    // ...
  }

  // other enterX functions...
}

// Create the listener
const listener: VisualBasic6Listener = new EnterSubListener();
// Use the entry point for listeners
ParseTreeWalker.DEFAULT.walk(listener, tree);
Visitor Approach
// ...
import { VisualBasic6Visitor, SubStmtContext } from "vb6-antlr4";
import { AbstractParseTreeVisitor } from "antlr4ts/tree";

// Extend the AbstractParseTreeVisitor to get default visitor behaviour
class CountSubsVisitor
  extends AbstractParseTreeVisitor<number>
  implements VisualBasic6Visitor<number> {

  defaultResult() {
    return 0;
  }

  aggregateResult(aggregate: number, nextResult: number) {
    return aggregate + nextResult;
  }

  visitSubStmt(context: SubStmtContext): number {
    return 1 + super.visitChildren(context);
  }
}

// Create the visitor
const countSubsVisitor = new CountSubsVisitor();
// Use the visitor entry point
const count = countSubsVisitor.visit(tree);
console.log(`There are ${count} Subs`);