Reputation: 379
I want to use Antlr4 to parse some files in my C# application. I have been able to generate the parser and lexer files so far given my grammer. Now I would like to use read in the files and apply the parser and lexer to them. I have been searching for documentation on how to do that but I am coming up short. I have found some old examples using previous versions of Antlr but they don't appear to work for Antlr4. Any help would be appreciated. Thanks.
Upvotes: 19
Views: 29495
Reputation: 2072
I am using Visual Studio 2019 Professional (latest version 16.7.3)
As for now ANTLR Language Support are not available for VS 2019. There is an unofficial version available https://github.com/tunnelvisionlabs/antlr4cs/issues/353 but it not complaint with VS2019 extension API (more info here: https://devblogs.microsoft.com/visualstudio/updates-to-synchronous-autoload-of-extensions-in-visual-studio-2019/)
You may try the following (steps for .net standard library)
Install VS extension AntlrVSIX 8.0 (using the Extension Manager)
create a .NET Standard Library project (MyLib.Parser.Grammar)
Created a dummy (.cs) class - not sure if its still necessary, there were some issues in the past if the project contained only grammar files
Reference the following packages (using Nuget)
Add grammar files (.g4) e.g. you can used the grammar repository available here https://github.com/antlr/grammars-v4
Let's say you would like to parse TSQL (https://github.com/antlr/grammars-v4/tree/master/sql/tsql) - add TSqlParser.g4 and TSqllexer.g4 to your project
Edit the project file MyLib.Parser.Grammar.csproj, it should look something like
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Antlr4 Include="TSqlLexer.g4">
<Package>MyLib.Parser</Package>
<Visitor>true</Visitor>
<Error>false</Error>
<Listener>true</Listener>
</Antlr4>
<Antlr4 Include="TSqlParser.g4">
<Package>MyLib.Parser</Package>
<Visitor>true</Visitor>
<Error>false</Error>
<Listener>true</Listener>
</Antlr4>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.8.0" />
<PackageReference Include="Antlr4BuildTasks" Version="8.3.0" />
</ItemGroup>
</Project>
At this point when you build the MyLib.Parser.Grammar project the Antlr4BuildTasks tools will create the parser .cs files, but they will be available in the project bin
folder (e.g. \MyLib.Parser.Grammar\bin\Debug\netstandard2.1
)
Create another library project MyLib.Parser
Create project dependency so MyLib.Parser.Grammar is build before MyLib.Parser
Direct the output files from MyLib.Parser.Grammar to MyLib.Parser project by using the AntOutDir attribute and relative paths in the project definition. Now the Antlr4 section in the project file should like something like:
<ItemGroup> <Antlr4 Include="TSqlLexer.g4"> <Package>MyLib.Parser</Package> <Visitor>true</Visitor> <Error>false</Error> <Listener>true</Listener> <AntOutDir>..\MyLib.Parser</AntOutDir> </Antlr4> <Antlr4 Include="TSqlParser.g4"> <Package>MyLib.Parser</Package> <Visitor>true</Visitor> <Error>false</Error> <Listener>true</Listener> <AntOutDir>..\MyLib.Parser</AntOutDir> </Antlr4> </ItemGroup>
Upvotes: 5
Reputation: 31
here are a sample of ErrorListener
public class ErrorListener : BaseErrorListener
{
public void SyntaxError(IRecognizer recognizer, int offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
{
Console.WriteLine("{0}: line {1}/column {2} {3}", e, line, charPositionInLine, msg);
}
}
Upvotes: 2
Reputation: 559
As a side note, "The Definitive ANTLR 4 Reference" by Terence Parr is an excellent resource to understand how ANTLR4 works and the difference development patterns. All the examples are in java, but the concepts apply to both Java and C#.
Upvotes: 32
Reputation: 1197
try with
using (StreamReader fileStream = new StreamReader(fileName)) {
AntlrInputStream inputStream = new AntlrInputStream(fileStream);
SearchLexer lexer = new SearchLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
SearchParser parser = new SearchParser(commonTokenStream);
parser.RemoveErrorListeners();
parser.AddErrorListener(new ErrorListener()); // add ours
parser.root();
}
Upvotes: 11