使用ANTLR 3.3?
我正在尝试开始使用 ANTLR 和 C#,但由于缺乏文档/教程,我发现它非常困难。我发现了一些针对旧版本的半心半意的教程,但此后 API 似乎发生了一些重大变化。
谁能给我一个简单的例子来说明如何创建语法并在短程序中使用它?
我终于成功地将我的语法文件编译到词法分析器和解析器中,并且我可以在 Visual Studio 中编译并运行这些文件(在必须重新编译 ANTLR 源之后,因为 C# 二进制文件似乎也已过时!--更不用说如果没有一些修复,源代码就无法编译),但我仍然不知道如何处理我的解析器/词法分析器类。据说它可以在给定一些输入的情况下生成 AST……然后我应该能够用它做一些奇特的事情。
I'm trying to get started with ANTLR and C# but I'm finding it extraordinarily difficult due to the lack of documentation/tutorials. I've found a couple half-hearted tutorials for older versions, but it seems there have been some major changes to the API since.
Can anyone give me a simple example of how to create a grammar and use it in a short program?
I've finally managed to get my grammar file compiling into a lexer and parser, and I can get those compiled and running in Visual Studio (after having to recompile the ANTLR source because the C# binaries seem to be out of date too! -- not to mention the source doesn't compile without some fixes), but I still have no idea what to do with my parser/lexer classes. Supposedly it can produce an AST given some input...and then I should be able to do something fancy with that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
假设您想要解析由以下标记组成的简单表达式:
-
减法(也是一元);+
加法;*
乘法;/
除法;(...)
分组(子)表达式;ANTLR 语法可能如下所示:
现在要创建正确的 AST,请在
options { ... }
部分中添加output=AST;
,然后混合一些“语法中的“树运算符”定义哪些标记应该是树的根。有两种方法可以执行此操作:^
和!
。^
使令牌成为根,而!
将令牌从 ast 中排除;... -> ^(根孩子孩子...)
。以规则
foo
为例:假设您希望
TokenB
成为根,而TokenA
和TokenC
成为根成为其子级,并且您希望从树中排除 TokenD。以下是使用选项 1 执行此操作的方法:以下是使用选项 2 执行此操作的方法:
因此,这是包含树运算符的语法:
我还添加了一个
Space
规则来忽略中的任何空格源文件并为词法分析器和解析器添加了一些额外的标记和命名空间。请注意,顺序很重要(首先是options { ... }
,然后是tokens { ... }
,最后是@... {}-命名空间声明)。
就是这样。
现在从语法文件生成词法分析器和解析器:
并将
.cs
文件与 C# 运行时 DLL。您可以使用以下类对其进行测试:
产生以下输出:
对应于以下 AST:
(使用 graph.gafol.net 创建的图表)
请注意,ANTLR 3.3 刚刚发布CSharp 目标处于“测试阶段”。这就是我在示例中使用 ANTLR 3.2 的原因。
对于相当简单的语言(如上面的示例),您还可以即时评估结果,而无需创建 AST。您可以通过在语法文件中嵌入纯 C# 代码并让解析器规则返回特定值来实现此目的。
这是一个示例:
可以使用类进行测试:
并产生以下输出:
编辑
Let's say you want to parse simple expressions consisting of the following tokens:
-
subtraction (also unary);+
addition;*
multiplication;/
division;(...)
grouping (sub) expressions;An ANTLR grammar could look like this:
Now to create a proper AST, you add
output=AST;
in youroptions { ... }
section, and you mix some "tree operators" in your grammar defining which tokens should be the root of a tree. There are two ways to do this:^
and!
after your tokens. The^
causes the token to become a root and the!
excludes the token from the ast;... -> ^(Root Child Child ...)
.Take the rule
foo
for example:and let's say you want
TokenB
to become the root andTokenA
andTokenC
to become its children, and you want to excludeTokenD
from the tree. Here's how to do that using option 1:and here's how to do that using option 2:
So, here's the grammar with the tree operators in it:
I also added a
Space
rule to ignore any white spaces in the source file and added some extra tokens and namespaces for the lexer and parser. Note that the order is important (options { ... }
first, thentokens { ... }
and finally the@... {}
-namespace declarations).That's it.
Now generate a lexer and parser from your grammar file:
and put the
.cs
files in your project together with the C# runtime DLL's.You can test it using the following class:
which produces the following output:
which corresponds to the following AST:
(diagram created using graph.gafol.net)
Note that ANTLR 3.3 has just been released and the CSharp target is "in beta". That's why I used ANTLR 3.2 in my example.
In case of rather simple languages (like my example above), you could also evaluate the result on the fly without creating an AST. You can do that by embedding plain C# code inside your grammar file, and letting your parser rules return a specific value.
Here's an example:
which can be tested with the class:
and produces the following output:
EDIT
您看过Irony.net吗?它针对 .Net,因此工作得非常好,有适当的工具、适当的示例并且可以正常工作。唯一的问题是它仍然有点“alpha-ish”,所以文档和版本似乎有点变化,但如果你坚持使用一个版本,你可以做一些漂亮的事情。
ps 很抱歉这个错误的答案,当你问一个关于 X 的问题时,有人使用 Y 提出了不同的建议;^)
Have you looked at Irony.net? It's aimed at .Net and therefore works really well, has proper tooling, proper examples and just works. The only problem is that it is still a bit 'alpha-ish' so documentation and versions seem to change a bit, but if you just stick with a version, you can do nifty things.
p.s. sorry for the bad answer where you ask a problem about X and someone suggests something different using Y ;^)
我个人的经验是,在学习 C#/.NET 上的 ANTLR 之前,应该腾出足够的时间来学习 Java 上的 ANTLR。这为您提供了所有构建块的知识,稍后您可以在 C#/.NET 上应用。
我最近写了一些博客文章,
假设您熟悉 Java 上的 ANTLR,并准备好将语法文件迁移到 C#/.NET。
My personal experience is that before learning ANTLR on C#/.NET, you should spare enough time to learn ANTLR on Java. That gives you knowledge on all the building blocks and later you can apply on C#/.NET.
I wrote a few blog posts recently,
The assumption is that you are familiar with ANTLR on Java and is ready to migrate your grammar file to C#/.NET.
这里有一篇关于如何一起使用 antlr 和 C# 的精彩文章:
http://www. codeproject.com/KB/recipes/sota_expression_evaluator.aspx
这是 NCalc 创建者的一篇“如何完成”文章,NCalc 是 C# 的数学表达式求值器 - http://ncalc.codeplex.com
您还可以在此处下载 NCalc 的语法:
http://ncalc.codeplex.com/SourceControl/changeset/view /914d819f2865#Grammar%2fNCalc.g
NCalc 工作原理的示例:
希望有帮助
There is a great article on how to use antlr and C# together here:
http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx
it's a "how it was done" article by the creator of NCalc which is a mathematical expression evaluator for C# - http://ncalc.codeplex.com
You can also download the grammar for NCalc here:
http://ncalc.codeplex.com/SourceControl/changeset/view/914d819f2865#Grammar%2fNCalc.g
example of how NCalc works:
hope its helpful