Восстановление множественных ошибок Bison C ++ с отсутствующей точкой с запятой

Я разрабатываю свой собственный компилятор, и у меня есть проблема с дизайном восстановления после ошибок
в режиме паники для грамматики Java.

Я думал о нескольких решениях, но реальный вопрос:

Как я мог сделать это с Bison C ++?

Я это сделал:

пакет 2

импорт java.lang. *;

ошибка должна указывать на первую точку с запятой, и это правильно работает с правилом

package_rule: ошибка PACKAGE ‘;’

но если бы я написал этот код:

пакет 2

импорт java.lang. *

class y {void method () {int m}

}

что мне нужно от парсера как стандартный компилятор, чтобы сообщать об ошибках:

Ожидается идентификатор в строке пакета.
отсутствует ‘;’ укажите один для пакета в строке инструкции по импорту.
mssing ‘;’ в строке м.

Я имею в виду, что мне нужно после ошибки пакета использовать токен до первой точки с запятой или остановиться, когда найти объявление класса или интерфейса в последней строке перед тем, как объявить их! и сообщать о любых других ошибках, найденных после строки:

int m // отсутствует ‘;’

Пожалуйста, помогите мне, на мой взгляд, несколько решений, но как это сделать с Bison C ++ для Java грамматики?

0

Решение

Ну, ваша основная проблема в том, как вы хотите, чтобы он пытался восстановиться после синтаксических ошибок. Когда у вас есть входная последовательность, как

package x import

Вы хотите, чтобы он предполагал, что там должна быть точка с запятой, или вы хотите, чтобы он предполагал, что что-то еще застряло до точки с запятой, и он должен выбрасывать вещи, пока не достигнет точки с запятой?

Последнее то, что у вас есть — правило package: PACKAGE error ';' делает именно это — всякий раз, когда он видит ключевое слово PACKAGE но то, что последует за ним, не соответствует остальным package Правило, он должен выбросить ввод, пока не увидит ';' и попытаться продолжить оттуда.

Если вы хотите первое, вы бы использовали правило как package: PACKAGE name error — если он видит PACKAGE с чем-то, похожим на правильное имя пакета, но без точки с запятой, обработайте его так, как если бы там была точка с запятой, и попробуйте продолжить.

Сделать так, чтобы ОБА из вышеперечисленных вещей было чрезвычайно сложно. Наиболее близким было бы, чтобы грамматика выглядела примерно так:

package: PACKAGE name ';'  /* normal package decl */
| PACKAGE name      /* missing semicolon -- treat this as a semantic error */
| PACKAGE error ';' /* no name -- skip up to the next semicolon to recover */

Однако такого рода вещи, вероятно, дадут вам грамматические конфликты, которые трудно разрешить.

1

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

Вы не будете возражать, чтобы решить эту проблему способом C ++ ООП, а не бизоном, не так ли?

Предположим, у вас есть определенные типы узлов AST

struct BaseExpression {
virtual std::string toIdentifier() = 0;
// other member. remember to declare a virtual destructor
};

struct IntLiteral : BaseExpression {
std::string toIdentifier() {
error::toAnIdentifier();
return "";
}
};

struct Identifier: BaseExpression {
std::string ident;

explicit Identifier(std::string id) : ident(id) {}

std::string toIdentifer() {
return ident;
}
};

Определите такое правило

%union {
BaseExpression* expr_type;
}

%type <expr_type> simple_expr

package_expr: simple_expr
{
$1->toIdentifer(); // thus integers or float numbers would generate errors
// do sth with that identifer
}
;

package_expr: package_rule '.' simple_expr
{
$3->toIdentifer(); // same trick
// do sth with that identifer
}
;

где simple_expr является

simple_expr: int_literal { return new IntLiteral; }
| ...
| identifier { return new Identifier(yytext); }
;
0

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