Давайте посмотрим на лес сначала, прежде чем смотреть на деревья.
Здесь есть много информативных ответов с большими подробностями, я не буду повторять ни одного из них. Ключ к программированию в JavaScript имеет сначала правильную ментальную модель общего исполнения.
Хорошие новости заключается в том, что, если вы хорошо понимаете этот момент, вам никогда не придется беспокоиться о гоночных условиях. Прежде всего вы должны понимать, как вы хотите упорядочить свой код как по существу ответ на разные дискретные события, и как вы хотите объединить их в логическую последовательность. Вы можете использовать обещания или новые асинхронные / ожидающие более высокие уровни в качестве инструментов для этой цели, или вы можете откатывать свои собственные.
Но вы не должны использовать какие-либо тактические инструменты для решения проблемы, пока вам не понравится актуальная проблемная область. Нарисуйте карту этих зависимостей, чтобы знать, что нужно запускать, когда. Попытка ad-hoc подхода ко всем этим обратным вызовам просто не поможет вам.
Это кажется распространенным недоразумением ANTLR
:
Обработка языка в ANTLR:
Обработка языка выполняется в двух строго разделенных фазах:
Поскольку лексирование должно предшествовать синтаксическому анализу, возникает следствие : Lexer не зависит от анализатора, парсер не может влиять на лексику.
Лексинг
Лексинг в ANTLR работает следующим образом:
Пример: что не так с вашей грамматикой
Ваша грамматика имеет два правила, которые являются критическими:
FILEPATH: ('A'..'Z'|'a'..'z'|'0'..'9'|':'|'\\'|'/'|' '|'-'|'_'|'.')+ ;
TITLE: ('A'..'Z'|'a'..'z'|' ')+ ;
Каждое совпадение, соответствующее TITLE, также будет соответствовать FILEPATH. И FILEPATH определяется до TITLE: Таким образом, каждый токен, который вы ожидаете стать заголовком, будет FILEPATH.
Для этого есть два намека: