В целом, проблема такая — есть приложение которое хостит MS HTML (ну или ActiveScripting, на данный момент это неважно). Логика в нём реализована на JScript. Хотелось бы иметь возможность добавлять туда дебажные выражения, типа логов или ассёртов, при чём чтобы была возможность в релизе их полностью отключать. ИМХО самым ровным вариантом для этого было бы парсенье файлов перед исполнением (препроцессинг) с выкидыванием "лишнего". Хотелось бы для этого подключить JavaScript парсер, и естественно писАть его ручками нет ни желания, ни времени. Мне не нужна виртуальная машина, только генератор AST (с возможностью по AST вновь сформировать код, мне ж его надо будет ActiveScripting отдать).
Вопрос знатокам — посоветуйте плиз парсер, удовлетворяющий условиям:
1. Фришный для коммерческого использования
2. Без лишних зависимостей в рантайме
3. Написанный на C или С++
4. По возможности безбажный и обкатанный на других проектах
5. Желательно — с описанием грамматики в простом виде, допускающем модификацию
Здравствуйте, Left2, Вы писали:
С>>А зачем для всего этого нужен парсер яваскрипта?
L>Хочу вырезать, к примеру, вызов функции Log. Отсюда хочу вырезать: L>
L>Log("Debug info bla-bla-bla");
L>
L>а отсюда — нет: L>
L>"Пример использования:\
L>Log("Debug info bla-bla-bla");\
L>"
L>
L>Конечно если решения не найду то на последние два случая забью (потребую чтобы Log начинался с начала строки), но хочется всё делать честно...
На правах идеи (т.е. сам не использовал, немного посмотрел только что — может сработать). Можно сделать небольшой тул, который будет использовать уже имеющийся у Вас парсер (а именно jscript.dll). Создаем (или используем имеющийся) экземпляр jscript'ового движка, запрашиваем у него IActiveScriptDebug, и вызываем метод GetScriptTextAttributes последнего, куда передаем имеющийся исходник, а на выходе имеем массив "аттрибутов символов". На скорую руку сбацанный исходник выглядит так:
// Предполагается, что spScript - это IActiveScriptPtr или IActiveScriptParsePtr
CComQIPtr<IActiveScriptDebug> spScriptDebug( spScript );
ATLASSERT( spScriptDebug );
ULONG nStrLen = static_cast<ULONG>( ::_tcslen( pstrCode ) ); // pstrCode - строка с исходником
CAutoVectorPtr<SOURCE_TEXT_ATTR> arrSourceAttr( new SOURCE_TEXT_ATTR[nStrLen] );
if( SUCCEEDED( spScriptDebug->GetScriptTextAttributes(
pstrCode,
nStrLen,
pstrDelimiter, // например, "</SCRIPT>"
0x8101 /*GETATTRTYPE_DEPSCAN | GETATTRFLAG_THIS | GETATTRFLAG_HUMANTEXT*/,
arrSourceAttr ) )
{
// а теперь работаем, как описано ниже
}
Далее банально ищем в исходнике строку "Log" и смотрим на аттрибуты соответствующих символов — как показали простейшие опыты, в случае, если Log является вызовом функции / объектом, его символы будут отмечены флагом 0x01, если же это комментарий / строка — то 0x80 / 0x02 (тут надо бы посмотреть внимательнее).
Опять же, будет ли оно работать на самом деле — . Есть подозрение, что, покопав глубже в эту сторону, можно получить требуемый Вам функционал.
Идея интересная, большое спасибо.
Главный недостаток — не получится работать из MS HTML — из него вообще нельзя достучаться к ActiveScripting-овым интерфейсам
Здравствуйте, Left2, Вы писали:
L>Конечно если решения не найду то на последние два случая забью (потребую чтобы Log начинался с начала строки), но хочется всё делать честно...
Предлагаю рассмотреть препроцессор С.
Пишем вот такой код:
#ifndef NDEBUG
#define Log(x) alert(x)
#else
#define Log(x)
#endif
<html>
<script language="javascript">
// Пример использования:
function f() {
Log("Debug info bla-bla-bla");
var s = 'Пример использования:\
Log("Debug info bla-bla-bla");\
'
[1, 2, 3, 4].foreach(function(x) { y += x; Log(x); });
}
</script>
<body>
<a href="#" onclick="f()">LINK</a>
</body>
</html>
Потом для дебаг-варианта поступаем вот так:
Сергей@localhost [test]> cpp -P test.htmlx
<html>
<script language="javascript">
function f() {
alert("Debug info bla-bla-bla");
var s = 'Пример использования: Log("Debug info bla-bla-bla"); '
[1, 2, 3, 4].foreach(function(x) { y += x; alert(x); });
}
</script>
<body>
<a href="#" onclick="f()">LINK</a>
</body>
</html>
Для релиза вот так:
Сергей@localhost [test]> cpp -P -DNDEBUG test.htmlx
<html>
<script language="javascript">
function f() {
;
var s = 'Пример использования: Log("Debug info bla-bla-bla"); '
[1, 2, 3, 4].foreach(function(x) { y += x; ; });
}
</script>
<body>
<a href="#" onclick="f()">LINK</a>
</body>
</html>
Здравствуйте, Left2, Вы писали:
L>GPP идёт под GNU General Public Licence. Использовать его без изменений как бинарный файл (чтобы не погрешить против лицензии) — криво.
Не понимаю проблемы, честно говоря. Или ты чего-то с ним линковать собрался?
Ну, и если будешь вносить в него модификации — неужто они настолько ценны, что тебе будет жалко отдать код со своими изменениями?
Тем более, код ты обязан выдавать только тому, кому ты отдал саму модифицированную программу.
L>Но сама идея порыть не в сторону парсера JS, а в сторону препроцессоров интресна, спасибо.
Здравствуйте, Left2, Вы писали:
С>>Ну, и вместо CPP можно взять GPP.
L>GPP идёт под GNU General Public Licence. Использовать его без изменений как бинарный файл (чтобы не погрешить против лицензии) — криво.
L>Но сама идея порыть не в сторону парсера JS, а в сторону препроцессоров интресна, спасибо.
PERL а именно PCRE — не спасут отца русской демократии?
S>PERL а именно PCRE — не спасут отца русской демократии?
PCRE == Perl Compatible Regular Expressions?
А чем они мне помогут?
JavaScript конечно не С++, но даже его парсить регэкспами это черезчур...
Или я неправильно понял идею?
С>Не понимаю проблемы, честно говоря. Или ты чего-то с ним линковать собрался?
Конечно линковать. У меня standalone EXE файл, который во время работы грузит десятки JS-файлов. Если на каждый файл запускать какой-то процесс, то подтормаживание будет заметно. Я может не силён в ньюансах GPL — но разве я могу взять сорцы, модифицировать их и прилинковать к программе которую я распространяю на коммерческой основе и без исходных кодов?
Здравствуйте, Left2, Вы писали:
S>>PERL а именно PCRE — не спасут отца русской демократии? L>PCRE == Perl Compatible Regular Expressions? L>А чем они мне помогут? L>JavaScript конечно не С++, но даже его парсить регэкспами это черезчур... L>Или я неправильно понял идею?
Скорей извратил...
Парсить то не нужно, нужно убрать текст определенного формата, чем не работа для регэкспа (не обязательно PCRE)?
Ниже прочитал про рантайм — ИМХО регекспы подойдут
Здравствуйте, Left2, Вы писали:
С>>Не понимаю проблемы, честно говоря. Или ты чего-то с ним линковать собрался? L>Конечно линковать. У меня standalone EXE файл, который во время работы грузит десятки JS-файлов. Если на каждый файл запускать какой-то процесс, то подтормаживание будет заметно. Я может не силён в ньюансах GPL — но разве я могу взять сорцы, модифицировать их и прилинковать к программе которую я распространяю на коммерческой основе и без исходных кодов?
Нет, GPL, конечно, такое не позволяет.
А зачем в результирующий продукт включать препроцессор?
Я предлагаю фактически добавить в Makefile (не знаю, используешь ли ты именно make, но не в этом суть) этап сборки JS-файлов.
Т.е. ты пишешь JS-файлы, которые будут обрабатываться препроцессором. Потом собираешь проект — именно на этом этапе отрабатывает препроцессор и на выходе получаются JS-файлы, которые будут идти внутри конечного продукта. В отладочную сборку попадут JS-файлы с отладочным выводом, в релизе — этого не будет. Препроцессор JS-файлов в составе конечного продукта очевидно будет не нужен.
Такой вариант устраивает или преобразование JS-файлов необходимо именно в конечном продукте? Если так, то таки да — нужно искать другой препроцессор.
Здравствуйте, Left2, Вы писали:
L>GPP идёт под GNU General Public Licence. Использовать его без изменений как бинарный файл (чтобы не погрешить против лицензии) — криво.
Здравствуйте, Left2, Вы писали:
L>Добрый день, помогите советом кто может.
L>В целом, проблема такая — есть приложение которое хостит MS HTML (ну или ActiveScripting, на данный момент это неважно). Логика в нём реализована на JScript. Хотелось бы иметь возможность добавлять туда дебажные выражения, типа логов или ассёртов, при чём чтобы была возможность в релизе их полностью отключать. ИМХО самым ровным вариантом для этого было бы парсенье файлов перед исполнением (препроцессинг) с выкидыванием "лишнего". Хотелось бы для этого подключить JavaScript парсер, и естественно писАть его ручками нет ни желания, ни времени. Мне не нужна виртуальная машина, только генератор AST (с возможностью по AST вновь сформировать код, мне ж его надо будет ActiveScripting отдать).
С>Такой вариант устраивает или преобразование JS-файлов необходимо именно в конечном продукте? Если так, то таки да — нужно искать другой препроцессор.
Хотелось бы иметь галочку "включить отладочный режим" не заморачиваясь на дебаг-релиз версии. То есть, ИМХО оптимальный вариант — это одна версия со встроенным (отключаемым) препроцессором JS-файлов, который выкидывает лишнее во время загрузки скриптов. Самый близкий аналог — это ассерты в джаве, которые попадают в откомпилированный код, но выкидываются (если галочка выключена) JIT-компилятором.
причём если вместо "Something" функция которая производит какие-то тяжёлые вычисления — хочется чтобы её выкидывали на этапе препроцессинга и она не вызывалась вообще.
S>Парсить то не нужно, нужно убрать текст определенного формата, чем не работа для регэкспа (не обязательно PCRE)? S>Ниже прочитал про рантайм — ИМХО регекспы подойдут
Регэксп прийдётся делать с многострочным синтаксисом и довольно большой грамматикой дабы правильно обработать JS-овские комментарии и строки. ИМХО, тупиковый путь (вряд ли будет шустро работать + синтаксис регэкспов это сильно на любителя) — наверное проще будет иметь неполную грамматику (типа такой которой оперируют препроцессоры), которая будет отличать строки и комментарии, а всё остальное для неё будет просто набором токенов.
Здравствуйте, Left2, Вы писали:
S>>Парсить то не нужно, нужно убрать текст определенного формата, чем не работа для регэкспа (не обязательно PCRE)? S>>Ниже прочитал про рантайм — ИМХО регекспы подойдут
L>Регэксп прийдётся делать с многострочным синтаксисом и довольно большой грамматикой дабы правильно обработать JS-овские комментарии и строки. ИМХО, тупиковый путь (вряд ли будет шустро работать + синтаксис регэкспов это сильно на любителя) — наверное проще будет иметь неполную грамматику (типа такой которой оперируют препроцессоры), которая будет отличать строки и комментарии, а всё остальное для неё будет просто набором токенов.