#antlr4
#antlr4
Вопрос:
Как только появится дерево синтаксического анализа, посетитель или слушатель, проходящий по дереву синтаксического анализа для выполнения фактического перевода, столкнется с ошибками, о которых синтаксический анализ не может знать (например, ссылки на внешние объекты, которые не существуют). Когда пользователю представлены ошибки из его исходного кода, он должен видеть как ошибки, сгенерированные синтаксическим анализатором, так и эти «семантические» ошибки.
Прямо сейчас у меня есть пользовательский прослушиватель, который фиксирует ошибки синтаксического анализа, а затем у меня есть совершенно другой механизм сбора ошибок второго прохода, и когда я представляю ошибки пользователю, я объединяю эти два источника ошибок в один поток ошибок. Я спешил, и работа была выполнена, теперь пришло время сделать лучше.
Чтобы исправить это, у меня есть два варианта.
- Измените мой пользовательский прослушиватель, чтобы переформатировать ошибки синтаксического анализа, чтобы их можно было добавлять в объединенный поток по мере их создания. Тогда объединенный поток является авторитетным источником всех ошибок.
- Каким-то образом иметь возможность добавлять семантические ошибки в поток ошибок, который получает мой клиент-слушатель, что-то вроде возможности вызова
notifyErrorListener
изнутри функции посещения. Тогда мой пользовательский сборщик ошибок теперь является авторитетным источником всех ошибок.
Я легко могу сделать #1, но мне кажется, что # 2 — это правильный выбор, и я просто не совсем понимаю, как я это делаю.
Ответ №1:
Один из ответов заключается в том, что я могу вызвать свой пользовательский прослушиватель ошибок непосредственно на втором проходе, я могу создать достаточное количество аргументов из объектов контекста, чтобы сгенерировать вызов, на syntaxError
который может ответить мой пользовательский прослушиватель.
// Typescript fragment implementation of visitor with ability to add
// semantic errors to error stream
export class MYLANGUAGETranslator
extends AbstractParseTreeVisitor<MYNODETYPE>
implements MYLANGUAGEVisitor<MYNODETYPE> {
/**
* Adds a second pass error to the error stream.
*
* @param ecx The context token which triggered the error
* @param msg The error message
*/
semanticError(ecx: ParserRuleContext, msg: string): void {
customErrorListenerInstance.syntaxError(undefined, undefined, ecx.start.line, ecx.start.charPositionInLine, msg, undefined);
}
Однако … чтение комментариев ниже немного прояснило ситуацию. На данный момент я считаю, что правильнее всего создать свой собственный пользовательский сборщик сообщений об ошибках, а затем использовать пользовательский прослушиватель ошибок и метод семантической ошибки для этого сборщика, ошибочно продолжать использовать прослушиватель ошибок ANTLR после завершения синтаксического анализа.
Комментарии:
1. Хорошее решение. Однако я бы не стал вызывать
syntaxError
функцию семантической ошибки. Это может сбить с толку. Вместо этого пусть ваш прослушиватель обрабатывает только синтаксические ошибки, а на семантической фазе записывает непосредственно в список ошибок, созданный вашим прослушивателем ошибок, чтобы добавить семантические ошибки. Для этого вам не нужен слушатель.2. Это зависит от требований к дизайну. Но я бы предложил требование, чтобы вы разделили две фазы. Я бы не хотел, чтобы посетитель Antlr вызывал синтаксическую ошибку синтаксического анализатора Antlr SyntaxError(). (И, возможно, вы захотите прочитать среду выполнения Antlr, чтобы увидеть, что делает SyntaxError() .) Вы можете решить создать AST для замены Antlr CST. Если вы решите это сделать, не имеет смысла вызывать код ошибки синтаксического анализатора Antlr при семантическом анализе. Вместо этого я бы попросил анализатор и семантический анализ добавить сообщение с сортировкой в общую систему отчетов об ошибках.
3. Да, я думаю, я согласен с вами обоими в этом, ваши рассуждения проясняют. Пользовательский прослушиватель ошибок должен отбрасывать ошибки в корзину, а подпрограмма семантических ошибок должна отбрасывать ошибки в ту же корзину. Я отредактирую «ответ», чтобы отразить это.