- Download and set up ANTLR4
- Download
PlSqlLexer.g4
andPlSqlParser.g4
from https://github.com/antlr/grammars-v4/tree/master/sql/plsql
-
Build the lexer (https://stackoverflow.com/a/55379369/1958726):
antlr4 PlSqlLexer.g4 -Dlanguage=CSharp
-
Build the parser:
antlr4 PlSqlParser.g4 -Dlanguage=CSharp
-
PowerShell:
dotnet new console -n MyPlSqlProject cd .\MyPlSqlProject iwr https://github.com/antlr/grammars-v4/raw/master/sql/plsql/CSharp/PlSqlLexerBase.cs -OutFile PlSqlLexerBase.cs iwr https://github.com/antlr/grammars-v4/raw/master/sql/plsql/CSharp/PlSqlParserBase.cs -OutFile PlSqlParserBase.cs iwr https://raw.githubusercontent.com/antlr/antlr4/master/doc/resources/CaseChangingCharStream.cs -OutFile CaseChangingCharStream.cs
-
Copy the
.cs
files that ANTLR generated in the previous section into the project folder. -
Fix namespaces; remove namespaces from
PlSqlLexerBase.cs
andPlSqlParserBase.cs
, or addPlSqlParseTree
using
s to their subclasses, or do something else (maybeantlr4
takes a namespace argument when building the lexer and parser?). -
Add missing constructor overload to
PlSqlLexerBase.cs
:public PlSqlLexerBase(ICharStream input, TextWriter output, TextWriter errorOutput) : base(input, output, errorOutput) { }
-
Add missing constructor overload to
PlSqlParserBase.cs
:protected PlSqlParserBase(ITokenStream input, TextWriter output, TextWriter errorOutput) : base(input, output, errorOutput) { }
-
In
PlSqlLexerBase
, changeint la = _input.La(pos);
toint la = InputStream.LA(pos);
if it hasn't been fixed in the repo yet. -
Insert into
Program.cs
:var charStream = CharStreams.fromstring("My PL/SQL"); // or .fromPath or whatever var caseChangingCharStream = new CaseChangingCharStream(charStream, true); // Required for PL/SQL; see https://github.com/antlr/grammars-v4/blob/master/sql/plsql/README.md var lexer = new PlSqlLexer(caseChangingCharStream); var commonTokenStream = new CommonTokenStream(lexer); var parser = new PlSqlParser(commonTokenStream);
-
For faster compilation, separate the ANTLR classes into their own class library project, and uncheck Build for it under Build > Configuration Manager.
If you just need to grab specific things, like all tableview names in a view DDL's from
clause, you can use ANTLR's XPath
class. Example:
var tableviews = XPath.FindAll(tree, "//create_view//from_clause//tableview_name", parser);
context.GetText()
just returns the combined text of all child nodes; whitespace isn't included.
To get the full, original text, including whitespace, use:
caseChangingCharStream.GetText(new Interval(context.Start.StartIndex, context.Stop.StopIndex);
Thanks awfully.