shad-go/forth/README.md

105 lines
5.4 KiB
Markdown
Raw Normal View History

2021-02-18 20:13:55 +00:00
## forth
В этой задаче нужно написать интерпретатор [языка программирования Forth](https://en.wikipedia.org/wiki/Forth_(programming_language)).
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 имя новой операции,
2021-02-28 10:46:34 +00:00
а `definition` состоит из известных слов и чисел, разделённых пробелами.
2021-02-18 20:13:55 +00:00
Слова можно переопределять.
### Проверка решения
Для запуска тестов нужно выполнить следующую команду:
```
go test -v ./forth/...
```
#### Интерактивная среда
В [main.go](./main.go) написана небольшая обёртка вашей реализации,
позволяющая интерактивно взаимодействовать с интерпретатором.
```
go build . && ./forth
Welcome to Forth evaluator! To exit type "bye".
>1 2 +
Stack: 3
>
```
### Ссылки
* https://en.wikipedia.org/wiki/Forth_(programming_language)
* https://golang.org/pkg/strings/