Я исправил баг с AST в своём самописном интерпретаторе Tokype!

Всем привет. Я создатель своего пет-проекта Tokype. Если вы следите за моими постами, то я в этом посте говорил о том, что parser почему-то строит неправильный AST.

Я понял, что ошибка происходит из-за того, что в Tokype блоки заканчиваются на end. Классический рекурсивный спуск (как в Lua) ломается: внутренний parseBlock поглощает END, а внешний думает, что это его END — и выходит раньше времени. У меня print после цикла вылезал за функцию.

И мне в голову пришла такая мысль:
Парсер, когда находится в теле функции и видит for, if или while, останавливает парсинг блока функции и начинает парсить блок этой конструкции. Когда конструкция заканчивается на end, парсер перешагивает через этот end и продолжает парсить блок функции - до тех пор, пока не дойдёт до своего end. Так каждый блок знает, где он заканчивается, и print после цикла остаётся внутри функции.

В версии 0.0.3 можно просматривать AST командой tokype ast <file>.tp. Вот как это выглядит:

Program FunctionStatement main BlockStatement ForStatement ... CallExpression Identifier print // внутри main, как и должно быть Identifier sum CallExpression Identifier main

Код:

funct main(): n = 1000 start = get_time() sum = 0 for i = 1, n: for j = 1, n: if (i + j) % 2 == 0: sum = sum + i else: sum = sum + j end end end print(sum) stop = get_time() print(stop - start + " sec.") end main()

Раньше в AST print валялся на Program, а не в main. Теперь AST строится правильно - подход сработал. Теперь можно делать несколько вызовов функций с циклами подряд.

Также я планирую отложить встроенные библиотеки до версии 0.0.4 или 0.0.5. Причина - сложность кроссплатформенной реализации: загрузка нативных .dll / .so / .dylib из Go требует разных подходов под каждую ОС, и пока что я не нашёл решения, которое устраивало бы меня по сложности. Сами библиотеки уже написаны, но не на Go — думаю, найду альтернативный способ их подключить.

На этом у меня все, всем пока!

Теги:

22