Я написал интерпретатор для C-подобного языка, используя Flex и Bison для сканера / парсера. Он отлично работает при выполнении полных программных файлов.
Теперь я пытаюсь реализовать REPL в интерпретаторе для интерактивного использования. Я хочу, чтобы он работал как интерпретаторы командной строки в Ruby или ML:
Моя грамматика начинается с продукции top_level
, которая представляет собой одно выражение на языке. Лексер настроен для интерактивного режима на стандартном вводе. Я использую один и тот же сканер и грамматику как в полноформатном режиме, так и в режиме REPL, потому что нет семантической разницы в двух интерфейсах.
Мой основной цикл оценки структурирован следующим образом.
while (!interpreter.done) {
if (interpreter.repl)
printf(prompt);
int status = yyparse(interpreter);
if (status) {
if (interpreter.error)
report_error(interpreter);
}
else {
if (interpreter.repl)
puts(interpreter.result);
}
}
Это отлично работает, за исключением приглашения и эхо-логика. Если пользователь вводит несколько операторов в строке, этот цикл распечатывает лишние подсказки и выражения. И если выражение продолжается в нескольких строках, этот код не распечатывает запросы продолжения. Эти проблемы возникают из-за того, что степень детализации логики подсказки / эха - это оператор top_level
в грамматике, но логика чтения строк находится глубоко в лексере.
Как лучше всего реструктурировать цикл оценки. обрабатывать подсказки REPL и эхо? То есть:
( Я бы предпочел не менять язык сканера для передачи токенов новой строки, поскольку это серьезно изменит грамматику. Можно изменить YY_INPUT
и добавить несколько действий в грамматику Bison. Кроме того, я использую стандартные Flex 2.5.35 и Bison 2.3, которые поставляются с Xcode.)