如何解决使用Antlr解析代码后如何检测循环块?
我正在与Antlr4合作,我想解析和分析任何c ++代码以检测任何c ++源代码中的任何循环以对其进行依赖关系分析,我想检测外部循环,如果它具有内部循环,我想将其检测为内部循环,但是我无法在源代码中检测到任何循环。
我做了什么并尝试过:
这是我在Antlr中用于“ for循环”的规则:
forBlock: 'for' '(' (classicFor | forEach) ')' controlStructureBody ;
forExpression: primaryExpression (',' primaryExpression)* ;
我用以下代码打印出令牌:
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i <= 5; i++) {
for (int j = 0; j <= 5; j++) {
cout << i << j << " \t";
}
cout << "\n";
}
return 0;
}
将此代码与jave一起使用
public void printToken(String inputFile) throws FileNotFoundException,IOException {
System.out.println("The tokens of the source code is: \n");
CharStream inputStream = CharStreams.fromFileName(inputFile);
TokensLexer tokensLexer = new TokensLexer(inputStream);
CommonTokenStream tokenStream = new CommonTokenStream(tokensLexer);
tokenStream.fill();
for (Token token : tokenStream.getTokens()) {
System.out.println("<" + token.getText() + "> " + "<" + token.getType() + ">");
}
}
它给了我每个for循环的类型:
<for> <45>
<for> <45>
我尝试了以下代码:
CharStream inputStream = CharStreams.fromFileName(inputFile);
// lexing the code
TokensLexer tokensLexer = new TokensLexer(inputStream);
CommonTokenStream tokenStream = new CommonTokenStream(tokensLexer);
// parsing the code
TokensParser tokensParser = new TokensParser(tokenStream);
tokenStream.fill();
for (Token token : tokenStream.getTokens()) {
if (token.getType() == 45)
System.out.println("loop is found");
}
}
当我输入“ 45”时,它会打印出“找到回路” 。当我将数字更改为“ 39”时,它会打印出“找到回路” 只有一次。 我尝试使用“ 39”,因为我从Antlr语法生成的文件中具有此值。
Tokens.tokens-> for = 45。
Tokens.lexer.tokens-> for = 45
TokensParser.java-> Rule_forBlock = 39; Rule_forExpression = 40;
,当我尝试添加更多循环时:
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 5; j++) {
cout << i << j << " \t";
}
cout << "\n";
}
for (int i = 0; i < 100; i++)
{
cout<<"Test"<<endl;
} return 0;
}
使用数字39,仍然只检测到一个循环。
是否可以使用Antlr检测源代码中的循环并区分外部循环和内部循环?
解决方法
您没有提供足够的代码/语法来重现您所描述的内容。因此,我将给您演示如何使用the C++ grammar in the ANTLR repository解决该问题的示例。
我只更改了1条规则。代替:
iterationstatement
: While '(' condition ')' statement
| Do statement While '(' expression ')' ';'
| For '(' forinitstatement condition? ';' expression? ')' statement
| For '(' forrangedeclaration ':' forrangeinitializer ')' statement
;
我在其中添加了labels:
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.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。