синтаксический анализ — C ++ Написание интерпретатора — определение цели циклов для оператора break Переполнение стека

Я пишу простой программный интерпретатор на C ++. Когда я создаю внутреннее представление программы и получаю инструкцию break, как мне определить целевое местоположение охватывающих циклов?

void Imp::whilestmt()
{
Expr *pExpr;
accept(Token::WHILE);
expr(pExpr);
WhileStmt *pwhilestmt = new WhileStmt(pExpr,vm.getLocationCounter);
vm.add(pwhilestmt);
accept(Token::LOOP);
stmtlist();
pwhilestmt->setTarget(vm.getLocationCounter);
accept(Token::END);
accept(Token::LOOP);
vm.add(new EndLoopStmt);
}

Мой объект оператора break будет принимать цель оператора while в качестве параметра, как я могу это определить?

0

Решение

Я думаю, что решение состоит в том, чтобы добавить прямую ссылку, которая разрешается (путем поиска местоположения конца цикла), когда весь код для этого уровня цикла был произведен.

Другими словами, при генерации кода для цикла вам необходимо сформировать инструкцию «jump», в которой ее цель установлена ​​в том месте, где вы еще не знаете, где она находится. Решение состоит в том, чтобы выполнить переход с неизвестным назначением (установите для «назначения» инструкцию 0 или -1 или 0xdeaddead или что-то еще, что может быть легко идентифицировано для целей отладки позже — потому что лучший способ избежать ошибок «я не сделал» «исправить это должным образом» означает облегчить идентификацию этих мест — ошибки возникают только в тех вещах, которые трудно идентифицировать, точно так же, как никогда не идет дождь, когда вы носите зонтик), и сохраняйте список исправлений таких прыжков, пока вы сгенерировал весь цикл, затем пролистайте этот список исправлений и заполните соответствующий адрес, который, как вы теперь знаете, находится «здесь» (следующая инструкция после цикла). Я подозреваю, что вам также нужно что-то подобное для условия самого цикла — если это ложно, то вам нужно продолжить «после» цикла.

2

Другие решения

Я хотел бы рассмотреть создание своего рода дерева исполнения / конвейера. Каждый LOOP / WHILE будет новой ветвью (аналогично каждой функции), поэтому, когда вы сталкиваетесь с инструкцией END / BREAK, вы просто возвращаетесь к исходной точке ветвления и продолжаете вниз по линии.

3

Я добавил setTarget как виртуальную функцию Stmt.

Я сохранил начальное местоположение в части, которая обрабатывает операторы if, и затем проверил, имел ли я какие-либо разрывы stmts от начального местоположения до текущего местоположения, и если я сделал, я установил цель в текущее местоположение.

действительно грязный способ сделать это, но пока работает

0
По вопросам рекламы [email protected]