19

我想使用 Antlr4 来解析我的 C# 应用程序中的一些文件。到目前为止,鉴于我的语法,我已经能够生成解析器和词法分析器文件。现在我想在文件中使用读取并将解析器和词法分析器应用于它们。我一直在寻找有关如何做到这一点的文档,但我做得不够。我发现了一些使用以前版本的 Antlr 的旧示例,但它们似乎不适用于 Antlr4。任何帮助,将不胜感激。谢谢。

4

4 回答 4

31
  • 在 Visual Studio 中,转到工具 -> 扩展和更新并在在线部分搜索 Sam Harwell 的“ANTLR 语言支持”。更多信息可以在GitHub 项目网站上找到
    • 这做了几件事:
      • 为组合语法添加模板。
      • 添加语法高亮
      • 为语法添加 MSBuild 目标以生成解析器。
  • 在您的解决方案中,设置您的项目结构,如下所示:
    • 解决方案
      • 语法项目
        • 计算器.g4
      • 实施项目
        • GeneratedFiles(此文件夹中的所有文件都作为链接添加到位于 GrammarProject\obj\Debug 中的文件)
          • CalculatorBaseListener.cs
          • CalculatorBaseVisitor.cs
          • 计算器Lexer.cs
          • CalculatorListener.cs
          • 计算器解析器.cs
          • CalculatorVistor.cs
        • MyCalcualtorImplementation.cs
  • 编写和编译你的语法。
  • 在指向生成文件的链接的文件夹中,右键单击该文件夹,然后单击添加 -> 现有项目
  • 浏览到 Grammar Project\obj\Debug 并选择所有生成的解析器文件。
  • 下一步很重要。在添加按钮上有一个小的下拉箭头。单击下拉箭头,然后单击“添加为链接”。
    • 这将使用符号链接而不是直接复制将生成的文件添加到实现项目中。
    • 如果您以后必须更改语法,这会带来额外的好处,即不必删除和重新添加解析器文件。
  • 一旦你做到了这一点,那么你可以从 GrammarProject.CalculatorBaseListener 或 GrammarProject.CalculatorBaseParser 继承,这取决于你决定使用什么开发模式。

作为旁注, Terence Parr 的“The Definitive ANTLR 4 Reference”是了解 ANTLR4 工作原理和不同开发模式的绝佳资源。所有示例都使用 Java,但这些概念适用于 Java 和 C#。

于 2014-04-26T15:35:43.720 回答
11

尝试

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();
}
于 2014-01-16T10:50:52.413 回答
3

我正在使用 Visual Studio 2019 Professional(最新版​​本 16.7.3)

至于现在ANTLR 语言支持不适用于 VS 2019。有一个非官方版本可用https://github.com/tunnelvisionlabs/antlr4cs/issues/353但它不抱怨 VS2019 扩展 API(更多信息在这里:https:// /devblogs.microsoft.com/visualstudio/updates-to-synchronous-autoload-of-extensions-in-visual-studio-2019/

您可以尝试以下(.net 标准库的步骤)

  1. 安装 VS 扩展 AntlrVSIX 8.0(使用扩展管理器)

  2. 创建一个 .NET 标准库项目 (MyLib.Parser.Grammar)

  3. 创建了一个虚拟(.cs)类 - 不确定它是否仍然需要,如果项目只包含语法文件,过去会出现一些问题

  4. 参考以下包(使用 Nuget)

    • Antlr4.Runtime.Standard
    • Antlr4BuildTasks
  5. 添加语法文件 (.g4) 例如,您可以使用此处提供的语法存储库 https://github.com/antlr/grammars-v4

  6. 假设您想解析 TSQL ( https://github.com/antlr/grammars-v4/tree/master/sql/tsql ) - 将 TSqlParser.g4 和 TSqllexer.g4 添加到您的项目中

  7. 编辑项目文件 MyLib.Parser.Grammar.csproj,它应该看起来像

       <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>
    
  8. 此时,当您构建 MyLib.Parser.Grammar 项目时,Antlr4BuildTasks 工具将创建解析器 .cs 文件,但它们将在项目bin文件夹中可用(例如\MyLib.Parser.Grammar\bin\Debug\netstandard2.1

  9. 创建另一个库项目 MyLib.Parser

  10. 创建项目依赖项,以便在 MyLib.Parser 之前构建 MyLib.Parser.Grammar

  11. 使用项目定义中的 AntOutDir 属性和相对路径将输出文件从 MyLib.Parser.Grammar 定向到 MyLib.Parser 项目。现在项目文件中的 Antlr4 部分应该类似于:

<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>
  1. 现在重建后,生成的 .cs 文件应该会自动添加到 MyLib.Parser 项目中
于 2020-09-11T05:29:18.627 回答
2

这是 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);
    }
}
于 2017-09-20T14:10:31.907 回答