.. | ||
eval.go | ||
eval_test.go | ||
main.go | ||
README.md |
forth
В этой задаче нужно написать интерпретатор языка программирования Forth.
Forth - это стек-ориентированный, конкатенативный (конкатенация двух фрагментов кода выражает их композицию) язык программирования.
В нашем примитивном случае язык состоит из стека, хранящего целые числа, и словаря известных операций. Каждая операция вынимает некоторое (возможно нулевое) количество чисел со стека и кладёт некоторое (возможно нулевое) количество чисел на стек.
Полноценный Forth, с ячейками памяти, циклами, условными переходами и множеством стандартных операций позволяет писать довольно сложные программы и используется в микропроцессорах.
Примеры программ
В каждом примере на последней строке приведено результирующее значение стека.
Положить 3 числа на стек:
1 2 3
Stack: 1, 2, 3
Положить 2 числа на стек, исполнить операцию +
(достать 2 числа со стека и положить на стек их сумму)
1 2 +
Stack: 3
Положить число на стек и выполнить операцию drop
(достать верхнее значение из стека)
1 drop
Stack:
Определить операцию ("слово" в терминологии Forth) drop2
для удаления двух верхних значений со стека,
положить 2 числа на стек и воспользоваться drop2
:
: drop2 drop drop ;
1 2 drop2
Stack:
Грамматика
У языка нет официальной грамматики. Она определяется простым алгоритмом. Интерпретатор считывает строку ввода, разбивает на части, используя пробелы в качестве разделителя, анализирует каждую часть на принадлежность к лексемам языка ("словам").
Все известные языку слова хранятся в словаре. Если алгоритм натыкается на знакомое слово, он исполняет связанный с ним исходный код. Незнакомые слова интерпретируются как числа и добавляются в стек.
В случае успеха интерпретатор продолжает разбор входного потока. Если и поиск, и преобразование чисел завершаются неудачно, интерпретатор печатает слово, за которым следует сообщение об ошибке, указывающее, что слово не распознано, сбрасывает входной поток и ждет нового пользовательского ввода.
Что нужно сделать?
Нужно написать реализацию функций NewEvaluator
и Evaluator.Process
.
Первая создаёт объект исполнителя Forth кода, а вторая парсит и исполняет.
Требуется поддержать следующие слова:
+
,-
,*
,/
удаляют со стека два верхних значения и кладут результат соответствующей целочисленной арифметической операцииdup
кладёт на стек верхнее значениеover
кладёт на стек второе сверху значениеdrop
удаляет верхнее значение со стекаswap
меняет два верхних значения стека местами
При нехватке аргументов Process
должна возвращать ошибки.
Также нужно поддержать определение новых слов.
: word definition ;
где word
-- это case-insensitive имя новой операции,
а definition
состоит из известных слов и чисел, разделённых пробелами.
Слова можно переопределять.
Проверка решения
Для запуска тестов нужно выполнить следующую команду:
go test -v ./forth/...
Интерактивная среда
В main.go написана небольшая обёртка вашей реализации, позволяющая интерактивно взаимодействовать с интерпретатором.
go build . && ./forth
Welcome to Forth evaluator! To exit type "bye".
>1 2 +
Stack: 3
>