HishamMohammedA Ответов: 1

Как обнаружить блок цикла C++ после синтаксического анализа кода с помощью antlr4?


Я работаю с Antlr4 и хочу проанализировать и проанализировать любой код c++, чтобы обнаружить любые циклы в любом исходном коде c++, чтобы сделать анализ зависимостей от них, но я не могу обнаружить ни одного цикла в исходном коде.

Что я уже пробовал:

Это правило, которое я использовал для "for loops" в Antlr:
forBlock: 'for' '(' (classicFor | forEach) ')' controlStructureBody ;
forExpression: primaryExpression (',' primaryExpression)* ;

Я распечатываю токены в этом коде:
<pre>#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;
}

использование этого кода:
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.
Токены.Токены -> 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 и различить внешний и внутренний циклы?

Stefan_Lang

Я понятия не имею ни о Antlr, ни о том, как он работает. Но Граммер, который вы определили, не делает различия между телом цикла for, состоящим из одного оператора, заканчивающегося на';', или блоком кода, заключенным в '{' и'}', который может не заканчиваться на ';'. В частности, ваш последний пример кода имеет несколько циклов for, не заканчивающихся на ';'

1 Ответов

Рейтинг:
2

Jiri111

Почему бы тебе не выложить всю грамматику целиком? И это лишь малая толика. В ваших примерах он должен войти в "классику". Как определяется этот классицизм?

Выходные данные указывают на то, что код только что распознал маркер "for".


HishamMohammedA

хорошо, я смог найти цикл for, но теперь у меня есть проблема с распознаванием вложенного цикла, когда я использую visitor.

Я использую этот мир грамматики,
iterationstatement
: While '(' condition ')' оператор #WhileStatement
| Do оператор While '(' expression ')' ';' #DoWhileStatemen
Для '(' условие forinitstatement? ";" выражение лица? ')' заявление #ClassicForStatement
;
чтобы посетить цикл for и написать над ним, после выполнения некоторого анализа строки forStr.

public T visitClassicForStatement(GrammarParser.ClassicForStatementContext СТХ) {
Строка forStr =ctx.statement().compoundstatement().statementseq().statement().getText();

эта строка предполагает, что это операторы внутри цикла for, но я сталкиваюсь с проблемой, что когда я помещаю вложенный цикл и когда я получаю этот текст, я получаю цикл for вместе с ним.
проблема:
когда я получаю такое заявление, как это:
для заявлений}
мой анализ работает над утверждениями просто отлично но когда я получаю его вот так:
for(){for(){statments}}
У меня есть проблема, потому что внутренний цикл поставляется с утверждениями, и это создает проблему для моего способа анализа.

Как я могу игнорировать внутренний цикл for и принимать только операторы, подобные тому, как я принимаю его, когда у меня есть только один цикл, и писать только над внешним циклом.


это грамматика, которую я использую:
https://gofile.io/d/CLRikA