如何在通用遍历解析树的同时访问ANTLR4中的备用标签?或者,是否有任何方法可以复制^ANTLR3 的运算符的功能,因为这样可以解决问题.
我正在尝试为任何符合简单方法的ANTLR4语法编写AST漂亮的打印机(比如用替代标签命名产品).我希望能够打印出更漂亮的一个术语类似3 + 5的(int_expression (plus (int_literal 3) (int_literal 5))),或类似的东西,给出类似下面的语法:
int_expression
: int_expression '+' int_expression # plus
| int_expression '-' int_expression # minus
| raw_int # int_literal
;
raw_int
: Int
;
Int : [0-9]+ ;
Run Code Online (Sandbox Code Playgroud)
我无法有效地为制作plus和minus制作命名,因为将它们拉到自己的制作中会导致工具抱怨规则是相互左递归的.如果我不能把它们拉出来,我怎么能给这些作品命名呢?
注1:+通过将"好"终端(例如,Int上面的)放在特殊制作中(以特殊前缀开头的制作等raw_),我能够在方法论上摆脱论证.然后,我只能打印那些父作品被命名为" raw_......"而终止所有其他作品的终端.这非常适合摆脱+,同时保持3和5输出.这可以通过!ANTLR3完成.
注意2:我知道我可以编写一个专门的漂亮的打印机或为给定语言的每个产生使用动作,但我想使用ANTLR4来解析和生成各种语言的AST,看起来我应该是能够编写如此简单漂亮的打印机.换句话说,我只关心获得AST,而我宁愿不用每个语法来使用量身定制的漂亮打印机来获取AST.也许我应该回到ANTLR3?
我正在尝试编写一段代码,它将采用ANTLR4解析器并使用它为输入生成AST,类似于grun(misc.TestRig)上的-tree选项给出的输入.但是,我还希望输出包含所有行号/偏移信息.
例如,而不是打印
(add (int 5) '+' (int 6))
Run Code Online (Sandbox Code Playgroud)
我想得到
(add (int 5 [line 3, offset 6:7]) '+' (int 6 [line 3, offset 8:9]) [line 3, offset 5:10])
Run Code Online (Sandbox Code Playgroud)
或类似的东西.
ANTLR4还没有大量的访问者示例,但我很确定我可以通过复制toStringTree(由grun使用)的默认实现来完成大部分工作.但是,我没有看到有关行号或偏移量的任何信息.
我希望能够编写如下的超简单代码:
String visit(ParseTree t) {
return "(" + t.productionName + t.visitChildren() + t.lineNumber + ")";
}
Run Code Online (Sandbox Code Playgroud)
但它似乎并不那么简单.我猜我应该能够从解析器中获取行号信息,但我还没弄清楚如何这样做.如何在遍历中获取此行号/偏移量信息?
为了填写下面解决方案中的几个空白,我使用了:
List<String> ruleNames = Arrays.asList(parser.getRuleNames());
parser.setBuildParseTree(true);
ParserRuleContext prc = parser.program();
ParseTree tree = prc;
Run Code Online (Sandbox Code Playgroud)
得到的tree和ruleNames. program是我语法中顶级作品的名称.
我正在努力弄清楚如何使用visual studio 理智地调试异步代码,因为它没有破坏我想要的地方。例如,在这段代码中:
using System;
using System.Threading.Tasks;
namespace TestNS{
class Program {
static void Main(string[] args) {
Foo().Wait(); // sadly, it breaks here
}
static async Task Foo() {
var foo = 42;
if (foo == 42) {
throw new Exception(); // want it to break here
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如何让 Visual Studio 自动中断引发异常的位置而不是程序顶部?或者等效地,在不重新启动进程的情况下,我可以跳转到该上下文并查看那些本地人的值吗?
我理解根本问题是异常在技术上由幕后异步代码处理,因此 VS 不会将它们视为未处理的。当然没有其他人喜欢这种行为,并且有一种方法可以告诉 VS 没有真正捕获到异步调用的异常......抛出”等,断断续续,但没有任何帮助。
我不是在寻找包括编辑我的代码或手动添加断点的解决方案。同样,以特殊方式处理某些异常也不是真正的解决方案。并非我想打破的所有异常都来自我自己的代码;通常它来自字典中丢失的键或类似的东西。开发代码时总是会发生意外异常,我想轻松查看程序状态,而无需手动放置断点和/或 try/catch 代码,重新运行程序,手动推进程序直到我碰巧到达该功能。而且,这一切都是在我什至可以让它再次触发的假设下,当我一开始不知道它为什么会发生时。然后对开发过程中可能发生的每个异常执行此操作。
最重要的是,如果您正在查看AggregateException确实返回的那个,则甚至没有一个很好的方法来找出该异常的来源。您必须“查看详细信息”,然后展开异常,展开内部异常,将鼠标悬停在堆栈跟踪上,记住文件和行号,关闭详细信息,手动转到正确的位置,现在放置手动断点和去手动调试。为什么系统不能使用此堆栈跟踪来做正确的事情?
我把所有这些细节都放进去是因为我已经阅读了 20 篇关于类似主题的其他 SO 帖子。他们没有把所有这些细节都放进去,人们似乎很开心,所以我很困惑我做错了什么。在开发非异步代码时,这些都不会发生。我在上面做的所有步骤都是必要的吗?在检查异常上下文方面,使编写异步代码与编写非异步代码一样愉快的最佳实践是什么?