@popov654
Специалист в области веб-технологий

Как грамотно написать интерпретатор?

Здравствуйте,

Я хочу в качестве экспериментальной работы написать на Java базовый интерпретатор JavaScript кода. Без JIT компиляции, без всяких сложных API, самый минимум. Встроенные объекты Math, String, Date, поддержка прототипов, вызов функций, области видимости, основные операторы, работа с переменными, вывод в консоль и алерты.

Но я не идеально знаю Java, и ещё меньше у меня знаний в области проектирования ПО. Прошу подсказать, как грамотно реализовать всё вышеизложенное. Основные вопросы:

1. Как в рантайме правильнее разграничить вызов нативных (реализованных на Java) функций и вызов функций на JavaScript (это весьма разные сущности)?
2. Как оптимальнее хранить scopes? Через Hashtable/HashMap в виде вектора (имитация стека) - нормальное решение?
3. Как правильно организовать поиск функций в цепочке прототипов объекта? Например, мы ищем функцию; она находится в прототипе, ссылку на который мы храним. Но при вызове такая функция должна работать с полями данных исходного объекта, а не прототипа, или прототипа прототипа и т.д. В JavaScript всё будет в такой ситуации работать корректно, а как такое грамотно эмулировать?
4. Эффективный алгоритм разбора выражений тоже не помешал бы. Как быстро разобрать строку, зная приоритеты операторов, корректно выделить все круглые скобки, которые могут быть вложены друг в друга, и т.д. Ссылки на любую литературу, в том числе англоязычную, приветствуются.

Заранее спасибо за советы.
  • Вопрос задан
  • 543 просмотра
Решения вопроса 1
1. Как в рантайме правильнее разграничить вызов нативных (реализованных на Java) функций и вызов функций на JavaScript (это весьма разные сущности)?

Ну сделай разные классы для разных функций. JS динамически типизированный, так что в основном ты все равно будешь работать с каким-нибудь базовым абстрактным JsValue, от него и унаследуй классы функций. У класса JsValue сделай метод

JsValue call(scope: JsScope, context: JsValue, args: ArrayList<JsValue>)

который кидает TypeError: бла-бла-бла is not a function, а в классах функций (JsNativeFunction и JsFunction) переопредели его чтобы возвращал что-то.

2. Как оптимальнее хранить scopes? Через Hashtable/HashMap в виде вектора (имитация стека) - нормальное решение?

Я не эксперт, но я делал скоуп в виде хешмапа со ссылкой на родительский скоуп (и так по ссылкам можно было соответственно дойти до глобального скоупа), вроде нормальный вариант.

3. Как правильно организовать поиск функций в цепочке прототипов объекта? Например, мы ищем функцию; она находится в прототипе, ссылку на который мы храним. Но при вызове такая функция должна работать с полями данных исходного объекта, а не прототипа, или прототипа прототипа и т.д. В JavaScript всё будет в такой ситуации работать корректно, а как такое грамотно эмулировать?

Не вижу проблемы. x.foo(42) разворачивается во что-то типа этого:

JsObject xVar = scope.getVar("x");
xVar
    .attr("foo")    // ищет атрибут в объекте или в прототипе
    .call(scope, xVar, Arrays.asList(JsInt(42)));

Второй параметр метода call - это и есть контекст, то есть объект у которого вызывается метод.

4. Эффективный алгоритм разбора выражений тоже не помешал бы. Как быстро разобрать строку, зная приоритеты операторов, корректно выделить все круглые скобки, которые могут быть вложены друг в друга, и т.д. Ссылки на любую литературу, в том числе англоязычную, приветствуются.

Тут вряд ли что-то толковое подскажу, кроме как посмотреть в сторону ANTLR и аналогов.

P. S.
Немного литературы по теме
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Собственно классика - Книга красного дракона
Ответ написан
Комментировать
jamakasi666
@jamakasi666 Куратор тега Java
Просто IT'шник.
Открывай исходники штатного (nashorn, rhino) интерпретатора js в яве и читай\смотри как сделано. Кроме того в самой яве есть полноценный апи для сторонних скриптовых языков а кним и примеры.
Ответ написан
ignat_one
@ignat_one
web-developer
Могу по 4 пункту подсказать: один из эффективных способов разбора строки с операторами является обратная польская запись
Ответ написан
solotony
@solotony
покоряю пик Балмера
>> 4. Эффективный алгоритм разбора выражений

ищи варианты lex и yacc для java

а вообще тема построения компиляторов/интерпритаторов стара как мир
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы