>>20882
Подвисла дура чего-то... Основная задача интерпретатора — это REPL, поэтому такие требования.
В выбранный способ работы не поместилась наивная реализация рекурсивного спуска, бо она не имеет перзистентного состояния. Тогда дура сэмулировала её при помощи программного стэка. Поскольку конкретные исполнители могут и обязаны делегировать разбор другим исполнителям согласно формальным правилам для языка, дура сделала фабрику исполнителей, а так как создавать по исполнителю на каждое рекурсивно определённое правило слишком жирно, дура решила их закэшировать. Результатом работы исполнителя является синтаксическое дерево, которое сохраняется на стэке. Работать должно как-то так:
(Involved performers, Analysis result, Last involved performer)
( 1, In_Progress, Performer.Program)
> function f (x) is
( 2, Delegated, Performer.Declaration)
( 3, Delegated, Performer.Function_Declaration) -> (enter scope)↑
>> if x < 2 then
( 4, Delegated, Performer.Statement)
( 5, Delegated, Performer.If_Statement) -> (enter scope)↑
>>> return false;
( 6, Delegated, Performer.Statement)
( 7, Delegated, Performer.Return_Statement)
( 7, Finished, Performer.Return_Statement)
( 6, Finished, Performer.Statement)
( 5, In_Progress, Performer.If_Statement)
>> end if;
( 5, Finished, Performer.If_Statement) -> (leave scope)↑
( 4, Finished, Performer.Statement)
( 3, In_Progress, Performer.Function_Declaration)
>> end function;
( 3, Finished, Performer.Function_Declaration) -> (leave scope)↑
( 2, Finished, Performer.Declaration) -> (interpret current subtree)↑
( 1, In_Progress, Performer.Program)
(На самом деле цепочки делегирований более длинные, поскольку BNF этого недо-Паскаля занял пару страниц, ну и половина исполнителей не делает больше ровным счётом ничего, прямо как в жизни.)
По сути, это тот же рекурсивный спуск, только с постоянным состоянием на каждом этапе анализа, ну и один огромный token-driven автомат.
Не нравится, что исполнители вовлекают новых исполнителей самостоятельно, в результате управление слабо централизовано. Ну и поток управления у паровоза lexer->parser->binder->performer начал раздваиваться из-за введения областей видимости. Хотя видится вполне возможным обойтись деревьями утверждений, если всё-равно их потом сплющивать в байт-код.
>>20902
Классика со свичом мне не нравится, если ты про неё: во-первых, нет способа узнать, объекты какого класса создаёт элемент перечисления, во-вторых, элемент и класс создаваемого объекта никак явно не связаны, только через код свича. Ну а ссылки на подпрограммы завезли только в восьмую жабу это вам не Ada 95, где просто статический массив под это дело фигачился: type Constructor is access function return Your_Object'Class; Create : constant array (Your_Enum_Type) of Constructor := ....
Я про enum с классами говорил — способ хороший и наглядный. Но мне не нравится сам метод создания нового объекта и количество исключений, которые при этом кидают Class.getDeclaredConstructor () и Constructor.newInstance ().