首页 > 解决方案 > 使用 Antlr 解析代码后如何检测 for 循环块?

问题描述

标签: javac++loopsantlrantlr4

解决方案


您没有提供足够的代码/语法来重现您所描述的内容。因此,我将演示如何使用ANTLR 存储库中的 C++ 语法来解决它。

我只稍微改变了 1 条规则。代替:

iterationstatement
   : While '(' condition ')' statement
   | Do statement While '(' expression ')' ';'
   | For '(' forinitstatement condition? ';' expression? ')' statement
   | For '(' forrangedeclaration ':' forrangeinitializer ')' statement
   ;

我给它添加了一些标签

iterationstatement
   : While '(' condition ')' statement                                 #WhileStatement
   | Do statement While '(' expression ')' ';'                         #DoWhileStatement
   | For '(' forinitstatement condition? ';' expression? ')' statement #ClassicForStatement
   | For '(' forrangedeclaration ':' forrangeinitializer ')' statement #ForEachStatement
   ;

通过这些更改,以下演示类:

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

public class Main {

    public static void main(String[] args) throws Exception {

        String source = "#include <iostream>\n" +
                "using namespace std;\n" +
                "int main()\n" +
                "{\n" +
                "    for (int i = 0; i <= 5; i++)\n" +
                "    {\n" +
                "        for (int j = 0; j <= 5; j++) {\n" +
                "            cout << i << j << \" \\t\";\n" +
                "        }\n" +
                "        cout << \"\\n\";\n" +
                "    }\n" +
                "    for (int  i = 0; i < 100; i++)\n" +
                "    {\n" +
                "       cout<<\"Test\"<<endl;\n" +
                "    }    return 0;\n" +
                "}";

        CPP14Lexer lexer = new CPP14Lexer(CharStreams.fromString(source));
        CPP14Parser parser = new CPP14Parser(new CommonTokenStream(lexer));
        ParseTreeWalker.DEFAULT.walk(new ForListener(), parser.translationunit());
    }
}

class ForListener extends CPP14BaseListener {

    private int forLevel = 0;

    @Override
    public void enterClassicForStatement(CPP14Parser.ClassicForStatementContext ctx) {
        this.forLevel++;
        printInfo("classic", ctx);
    }

    @Override
    public void exitClassicForStatement(CPP14Parser.ClassicForStatementContext ctx) {
        this.forLevel--;
    }

    @Override
    public void enterForEachStatement(CPP14Parser.ForEachStatementContext ctx) {
        this.forLevel++;
        printInfo("each", ctx);
    }

    @Override
    public void exitForEachStatement(CPP14Parser.ForEachStatementContext ctx) {
        this.forLevel--;
    }

    private void printInfo(String forType, ParserRuleContext ctx) {
        System.out.printf("%s %s for-statement on line %d.%n",
                this.forLevel == 1 ? "OUTER" : "INNER", forType, ctx.getStart().getLine());
    }
}

将提供以下输出:

OUTER classic for-statement on line 5.
INNER classic for-statement on line 7.
OUTER classic for-statement on line 12.

推荐阅读