You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ANTLR4中如何跳过指定输出内容的Statement代码块?

Can I skip processing a statement when a specific string is matched in ANTLR4?

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] )* ['];

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:39:04