Мы предприняли титанические усилия и реализовали интерпретатор Common Lisp (ну, почти всего), способный в любой момент приостановить своё выполнение и вернуть состояние. Состояние можно скопировать и потом перезапустить несколько раз. При этом мы умеем что-то делать и с биндингами специальных переменных. Чтобы копировать состояния эффективно, мы начали делать «версионное состояние», которое копируется более дёшево, чем просто глубокая копия графа объектов. Его, правда, пока не используем, но планируем.
Ничего, что вся эта конструкция тормозная и привязана к SBCL. На этой основе реализована раскраска Яра (пока старой версии, но не суть).
Мы напускаем наш обычный парсер, который входит в транслятор, на текст в файле. Состояние парсера запоминаем в начале каждой строки, чтобы сэкономить усилия и не парсить файл целиком с начала до конца на каждое нажатие кнопки.
Смысл всех наворотов ровно в том, чтобы иметь один общий парсер, пригодный и для компиляции, и для среды.
Но на этом страдания не закончились. Оказывается (кто бы мог подумать?), современная среда должна ещё подсказывать, чем можно продолжить текст. И оказалось что это имеет прямое отношение к грамматике языка и к информации, которую накапливает парсер.
И наш рекурсивно-спускающийся парсер не подходит для этого, потому что как кажется, подсказки можно построить (насколько я понимаю) только на основе формального описания грамматики.
Посоветуйте, какой код посмотреть, что почитать (не занудное и простое). Что взять в качестве примера парсера, который может подсказать, что сейчас ожидается. Или может быть есть идеи, как можно рекурсивно-спускающийся парсер приспособить для этого.
При этом понятно, что список ожидаемого, вообще говоря, строится динамически. Например (для лиспа), если написали (defsystem :foo (, то дальше нужно откуда-то взять список всевозможных кляуз для defsystem и предложить именно их. Это не входит в грамматику языка, а входит в метаданные. Т.е. статически сгенерировать сам список продолжений невозможно.