облегченный javascript для парсера javascript - PullRequest
16 голосов
/ 28 июля 2011

Как мне написать легковесный javascript для парсера javascript. Что-то простое, что может конвертировать некоторые фрагменты кода.

Я бы хотел сделать объекты внутренней области видимости в функциях общедоступными.

Так что-то вроде этого

var outer = 42;
window.addEventListener('load', function() {
   var inner = 42;
   function magic() {
       var in_magic = inner + outer;
       console.log(in_magic);
   }
   magic();
}, false);

будет компилироваться в

__Scope__.set('outer', 42);
__Scope__.set('console', console);
window.addEventListener('load', constructScopeWrapper(__Scope__, function(__Scope__) {
    __Scope__.set('inner', 42);
    __Scope__.set('magic',constructScopeWrapper(__Scope__, function _magic(__Scope__) {
        __Scope__.set('in_magic', __Scope__.get('inner') + __Scope__.get('outer'));
        __Scope__.get('console').log(__Scope__.get('in_magic'));
    }));
    __Scope__.get('magic')();
}), false);

Пример демонстрации

Мотивация - сериализация состояния функций и замыканий и их синхронизация на разных машинах (клиент, сервер, несколько серверов). Для этого мне понадобится представление [[Scope]]

Вопросы:

  1. Можно ли создать компилятор такого типа без написания полного JavaScript -> (немного другого) компилятора JavaScript?
  2. Как мне написать такой компилятор?
  3. Можно ли повторно использовать существующие компиляторы js -> js?

Ответы [ 5 ]

4 голосов
/ 01 августа 2011

Не думаю, что ваша задача проста или коротка, если вы хотите получить доступ и восстановить все состояние программы.Одна из проблем заключается в том, что вам может потребоваться зафиксировать состояние программы в любой момент во время вычислений, верно?Это означает, что приведенный пример не совсем верен;он фиксирует состояние перед выполнением этого кода (за исключением того, что вы предварительно вычислили сумму, которая инициализирует магию, и этого не произойдет, пока код не будет запущен для исходного JavaScript).Я предполагаю, что вы, возможно, захотите захватить состояние в любой момент во время выполнения.

То, как вы заявили о своей проблеме, это то, что вы хотите парсер JavaScript в JavaScript.Я предполагаю, что вы представляете, что ваш существующий JavaScript-код J включает в себя такой синтаксический анализатор JavaScript и все остальное, что необходимо для генерации результирующего кода G, и что при запуске J он передает свои копии в G, производя код сериализации S и каким-то образомзагружая это.(Я думаю, что G довольно большой и седой, если он может обрабатывать весь Javascript). Таким образом, ваше изображение JavaScript содержит J, большие G, S и выполняет дорогостоящую операцию (подача J в G) при запуске.

Я думаю, что вам лучше пригодится инструмент G, который обрабатывает ваш исходный код JavaScript J в автономном режиме и генерирует код сериализации состояния / закрытия программы S (для сохранения и восстановления этого состояния), который можно добавить в / заменитьJ для исполнения.J + S отправляются клиенту, который никогда не видит G или его выполнение.Это отделяет генерацию S от выполнения J времени выполнения, экономя время и пространство выполнения клиента.

В этом случае вам нужен инструмент, который сделает генерацию такого кода S проще всего.Парсер чистого JavaScript - это начало, но этого недостаточно;вам понадобится поддержка таблицы символов, чтобы узнать, к какому коду функции подключен вызов функции F (...) и какое определение переменной в какой области соответствует присваиванию или доступу к переменной V. Возможно, вам потребуется изменить исходный код.J для вставки точек доступа, где может быть зафиксировано состояние программы.Вам может понадобиться анализ потока, чтобы выяснить, куда пошли некоторые значения.Настаивая на том, что все это в JavaScript, вы сужаете диапазон своих решений.

Для этих задач вам, скорее всего, пригодится инструмент преобразования программ .Такие инструменты содержат синтаксические анализаторы для интересующего языка, создают AST, представляющие программу, позволяют создавать карты идентификатора-определения («таблицы символов»), могут выполнять модификации AST, представляющие вставку точек доступа, или синтез AST.представляющий ваш демонстрационный пример, а затем заново сгенерированный действительный код JavaScript, содержащий измененный J и дополнения S. Из всех известных мне систем преобразования программ (включая все те, которые есть на сайте Википедии) ни одна не реализована в JavaScript.

Наш инструментарий реинжиниринга программного обеспечения DMS - это такая система преобразования программ, предлагающая все функции, которые я только что описал.(Да, он большой и седой; он должен справляться со сложностями реальных компьютерных языков).Он имеет интерфейс JavaScript , который содержит полный синтаксический анализатор JavaScript для AST и механизм восстановления кода JavaScript из модифицированных или синтезированных AST.(Также большой и седой; хорошо, что седой + седой все еще просто седой).Если это будет полезно, DMS также предоставляет поддержку для управления зданием и анализа потока данных.

3 голосов
/ 03 августа 2011

Существует проблема с переписыванием, описанным выше, вы не поднимаете инициализацию magic до верхней части области.

Существует ряд проектов, которые анализируют JavaScript.

  1. Анализатор Crock's Pratt , который хорошо работает на JavaScript, который вписывается в "хорошие части", и менее хорошо работает на других JS.
  2. es-lab синтаксический анализатороснованный на омете, которая обрабатывает полную грамматику, включая множество угловых случаев, которые пропускает парсер Крока.Это может не работать так же хорошо, как у Крока.
  3. narcissus Анализатор и анализатор.У меня нет особого опыта в этом.

Существует также ряд высококачественных лексеров для JavaScript, которые позволяют вам манипулировать JS на уровне токенов.Это может быть сложнее, чем кажется, поскольку JavaScript не является лексически регулярным, и предсказать вставку точки с запятой сложно без полного разбора.

My es5-lexer - тщательно сконструированный и эффективный лексер дляEcmaScript 5, который предоставляет возможность токенизировать JavaScript.Это эвристика, когда грамматика JavaScript не является лексически регулярной, но эвристика очень хороша, и она предоставляет средство для преобразования потока токенов, чтобы интерпретатор гарантированно интерпретировал его так, как лексер интерпретировал токены, так что если вы не доверяете своемуНа входе вы все еще можете быть уверены, что интерпретация, лежащая в основе преобразований безопасности, является правильной, даже если она неверна в соответствии со спецификацией для некоторых странных входных данных.

3 голосов
/ 01 августа 2011

Если вам нужно что-то с простым интерфейсом, вы можете попробовать node-burrito: https://github.com/substack/node-burrito

. Он генерирует AST с использованием анализатора uglify-js и затем рекурсивно обходит узлы.Все, что вам нужно сделать, это дать один обратный вызов, который проверяет каждый узел.Вы можете изменить те, которые вам нужно изменить, и он выведет полученный код.

3 голосов
/ 28 июля 2011

Я бы попытался найти существующий парсер для изменения. Возможно, вы могли бы адаптировать JSLint / JSHint?

0 голосов
/ 06 августа 2011

Ваша проблема находится в той же группе проблем, что и проблемы, решаемые с помощью JS Opfuscators и JS Compressors - они так же, как и вы, должны иметь возможность анализировать и переформатировать JS в эквивалентный сценарий;1002 * Здесь было хорошее обсуждение обфускаторов , и возможное решение вашей проблемы могло бы заключаться в использовании части синтаксического анализа и генератора из одной из версий FOSS.

Один вызов, ваш примерВ коде не учитываются области действия переменных, которые вы хотите установить / получить, и это в конечном итоге станет проблемой, которую вам придется решить.

Добавление

Учитывая проблему области действия для определенных функций замыкания, вы, вероятно, вряд ли сможете решить эту проблему как статическую проблему синтаксического анализа, поскольку переменные области действия вне замыкания придется импортировать / экспортировать для разрешения / сохранения и повторного создания области действия.Следовательно, вам, возможно, придется покопаться в самом механизме оценки и, возможно, получить движок V8 и взломать сам интерпретатор - при условии, что вам не нужно, чтобы это было универсальным для всех скриптовых движков и что вы можете связать еговплоть до одной реализации, которой вы управляете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...