![](/img/trans.png)
[英]Difference Between Two Iterative Solutions for PreOrder Traversal of a Binary Tree
[英]Why is there such a difference between parse tree visualization and my visitor/listener traversal?
我使用IntelliJ中的ANTLR4 插件創建了這個示例語法,當我使用它的工具鏈為一些無效內容生成可視化表示時(在這種情況下是一個空字符串),這種表示似乎與我能夠的不同在使用針對相同輸入的示例訪問者/偵聽器實現進行實際的解析樹遍歷時獲取。
這是語法:
grammar TestParser;
THIS : 'this';
Identifier
: [a-zA-Z0-9]+
;
WS : [ \t\r\n\u000C]+ -> skip;
parseExpression:
expression EOF
;
expression
: expression bop='.' (Identifier | THIS ) #DottedExpression
| primary #PrimaryExpression
;
primary
: THIS #This
| Identifier #PrimaryIdentifier
;
對於空字符串,我得到以下樹:
此樹表明解析器構建了一個包含“DottedExpression”和“primary:This”的解析樹(假設它使用自己的訪問者/監聽器實現來執行此操作)。 然而,當我嘗試使用以下代碼時:
package org.example.so;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
public class TestParser {
public static void main(String[] args) {
String input = "";
TestParserLexer lexer = new TestParserLexer(CharStreams.fromString(input));
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
TestParserParser parser = new TestParserParser(tokenStream);
TestParserParser.ParseExpressionContext parseExpressionContext = parser.parseExpression();
MyVisitor visitor = new MyVisitor();
visitor.visit(parseExpressionContext);
System.out.println("----------------");
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new MyListener(), parseExpressionContext);
System.out.println("----------------");
}
private static class MyVisitor extends TestParserBaseVisitor {
@Override
public Object visitParseExpression(TestParserParser.ParseExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
return super.visitParseExpression(ctx);
}
@Override
public Object visitDottedExpression(TestParserParser.DottedExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":DottedExpression");
return super.visitDottedExpression(ctx);
}
@Override
public Object visitPrimaryExpression(TestParserParser.PrimaryExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":PrimaryExpression");
return super.visitPrimaryExpression(ctx);
}
@Override
public Object visitThis(TestParserParser.ThisContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
return super.visitThis(ctx);
}
@Override
public Object visitPrimaryIdentifier(TestParserParser.PrimaryIdentifierContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
return super.visitPrimaryIdentifier(ctx);
}
}
private static class MyListener extends TestParserBaseListener {
@Override
public void enterParseExpression(TestParserParser.ParseExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
}
@Override
public void enterDottedExpression(TestParserParser.DottedExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":DottedExpression");
}
@Override
public void enterPrimaryExpression(TestParserParser.PrimaryExpressionContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":PrimaryExpression");
}
@Override
public void enterThis(TestParserParser.ThisContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
}
@Override
public void enterPrimaryIdentifier(TestParserParser.PrimaryIdentifierContext ctx) {
System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
}
}
}
我得到以下輸出:
line 1:0 mismatched input '<EOF>' expecting {'this', Identifier}
parseExpression
expression:PrimaryExpression
----------------
parseExpression
expression:PrimaryExpression
----------------
因此,不僅樹深度不匹配,輸出甚至表示不同的規則匹配第二(“PrimaryExpression”而不是“DottedExpression”)。
為什么我所展示的內容和我試圖展示的內容之間存在這樣的差異? 如何創建插件所示的相同樹表示?
使用ANTLR版本4.7。 插件版本是1.8.4。
此問題已在插件的1.8.2版本中修復。 如果您有1.8.2或更高版本,那么您可能發現了該問題的另一個未知子案例。
但是(根據我所指的問題),樹只在解析導致錯誤時才有所不同。 因此,如果您對使用錯誤信息不感興趣,那么您應該沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.