ANTLR4中如何跳过指定输出内容的Statement代码块?
Absolutely, you can skip processing the target statement block when the output string equals "Hello World 2". Let's walk through practical, maintainable approaches, starting with a quick fix to your grammar (your sample code uses begin/end but your grammar defines start/end—this mismatch would cause parsing errors otherwise).
Step 1: Fix the Grammar Keyword Mismatch
First, update your program rule to match the keywords in your input code:
grammar fileName; program : 'begin' statements+ 'end'; // Changed 'start' to 'begin' to match input statements : print; print: 'output' STRING; STRING : ["] ( ~["\r\n\\] | '\\' ~[\r\n] )* ["] | ['] ( ~['\r\n\\] | '\\' ~[\r\n] )* ['];
Approach 1: Use a Custom Listener (Recommended)
ANTLR's listener system lets you hook into parse tree traversal and skip processing specific nodes without breaking the parsing logic itself. This is the most flexible and clean approach.
1. Generate ANTLR Artifacts
Run the ANTLR tool to create the lexer, parser, and base listener:
antlr4 fileName.g4
2. Build a Custom Listener
Extend the auto-generated fileNameBaseListener and override the enterPrint method to skip processing for your target string:
public class SkipSpecificPrintListener extends fileNameBaseListener { @Override public void enterPrint(fileNameParser.PrintContext ctx) { // Extract the actual string content (strip surrounding quotes) String rawString = ctx.STRING().getText(); String content = rawString.substring(1, rawString.length() - 1); // Skip processing if we match the target string if ("Hello World 2".equals(content)) { System.out.println("Skipping print statement: " + content); return; } // Handle valid print statements as normal System.out.println("Processing print statement: " + content); } }
3. Wire Up the Listener in Your Main Code
Initialize the lexer, parser, and listener to process your input:
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; public class Main { public static void main(String[] args) { String input = """ begin output "Hello World" end begin output "Hello World 2" end """; // Set up lexer and parser fileNameLexer lexer = new fileNameLexer(CharStreams.fromString(input)); CommonTokenStream tokens = new CommonTokenStream(lexer); fileNameParser parser = new fileNameParser(tokens); // Generate the parse tree fileNameParser.ProgramContext tree = parser.program(); // Traverse the tree with our custom listener SkipSpecificPrintListener listener = new SkipSpecificPrintListener(); ParseTreeWalker.DEFAULT.walk(listener, tree); } }
Approach 2: Use a Visitor
If you prefer explicit control over parse tree traversal, ANTLR's visitor pattern works equally well:
1. Create a Custom Visitor
Extend fileNameBaseVisitor and override visitPrint to skip processing:
public class SkipSpecificPrintVisitor extends fileNameBaseVisitor<Void> { @Override public Void visitPrint(fileNameParser.PrintContext ctx) { String rawString = ctx.STRING().getText(); String content = rawString.substring(1, rawString.length() - 1); if ("Hello World 2".equals(content)) { System.out.println("Skipping print statement: " + content); return null; // Skip further processing for this node } System.out.println("Processing print statement: " + content); return null; } }
2. Use the Visitor
Replace the listener code in your main class with:
SkipSpecificPrintVisitor visitor = new SkipSpecificPrintVisitor(); visitor.visit(tree);
Should I Skip in the Grammar Directly?
You could use a semantic predicate in the grammar to prevent the print rule from matching your target string:
print: 'output' STRING { !$STRING.text.substring(1, $STRING.text.length()-1).equals("Hello World 2") }?;
But this will throw a syntax error when the string is matched, since the statements rule expects a valid print statement but won't find one. This is almost never desirable—you want to parse the input correctly, just skip processing that specific node. Listeners/visitors are the far better choice here.
内容的提问来源于stack exchange,提问作者Pun3rs

