|
|
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
Рассмотрим такую задачу: нужно создать парсер для калькулятора с функциями (по умолчанию есть SUM(), SIN(), COS() к примеру); Набор поддерживаемых функций может меняться через конфигурационный файл (имя функции и класс реализации). каждая функция реализует интерфейс (pardon за ошибки) Код: java 1. Как эффективно написать парсер чтобы расширение функционала (поддержка новых функций) было в run time без компиляции нового парсера? PS Генераторы парсеров которые встречались ранее: ANTLR, JavaCC, SableCC. Помню давным давно делал грамматику, генерил парсеры для сборки / разборки выражений (простые калькуляторы и SQL). Будем считать что все позабыл и возможно что-то свежее появилось, думаю это будет полезное упражнение для всех. Js контейнеры типа Rhino или в новой Java использовать не планируется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2017, 20:13 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniqueJs контейнеры типа Rhino или в новой Java использовать не планируется.А как на счет Jython ? Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2017, 23:08 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid unique, не забывай про безопасность. Всё что вводит пользователь - нужно запускать в таком контексте чтобы не было возможности иметь прямой доступ к файловой системе или сети. Полностью согласен с другими ораторами по поводу интерпретаторов Python, JavaScript. Какой из них лучше - дело вкуса. P.S. Почему-то вспомнил золотую фразу Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.01.2017, 23:35 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
UsmanА как на счет Jython ? Спасибо за напоминание, забыл про него. Сталкивался в админ скриптах с ним но сам никогда не прикручивал. Для калькулятора слишком могучая (и тяжелая) штука, но для расширений самое то. Не уверен насчет многопоточности интерпретатора - не придется их плодить по одному для каждого потока (а они наверное требуют много памяти)? Нужен калькулятор с поддержкой функций, функции могут быть специфическими, к примеру залезть в базу, найти какой маппинг и тд и выдать результат который в свою очередь может обработаться другой бизнес функцией (в этом причина зачем нужна поддержка новых функций через конфиг), пример вычисления какой то надписи с заходом в базу и получением имя хоста (об имплементации этих фунций мы понятия не имеем, наше дело скормить им аргументы и получить результат): Код: xml 1. где GETUSERNAME кастомная функция задаваемая через конфигурацую (id "GETUSERNAME", class name "come.package.impl.GetUserName") и к примеру она лезет в какую то базу данных в одном случае а в другом это будет маппинг через файл (да что угодно), GETHOSTNAME это другая фукция и тд. Пользователь добавляет новые функции которые затем можно использовать в выражениях в конфигурации. или попроще пример: Код: xml 1. Это на пальцах объяснение, в спешке написано. Пока нашел старый пример калькулятора на JavaCC, JJTree класс позволяет делать обход дерева. Добавить стек, маппинг для переменных (имя в выражении / значение) и можно делать обход дерева и вычисления. http://www.j-paine.org/dobbs/jjtree.html http://www.idevelopment.info/data/Programming/java/JavaCC/SimpleCalc1.jj https://github.com/jameswu/code-search/blob/master/javacc-example/src/main/javacc/Calculator.jj https://www.ibm.com/developerworks/data/library/techarticle/dm-0401brereton/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 13:01 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
maytonuid unique, не забывай про безопасность. Всё что вводит пользователь - нужно запускать в таком контексте чтобы не было возможности иметь прямой доступ к файловой системе или сети. Да, это хорошая дыра - подключение поддержки скриптов в конфиге. Наверное можно локализовать доступ к ресурсам у интерпретаторов языков. По моему у Rhino была такая возможность (сделать песочницу без диступа во внешний мир). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 13:05 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniquemaytonuid unique, не забывай про безопасность. Всё что вводит пользователь - нужно запускать в таком контексте чтобы не было возможности иметь прямой доступ к файловой системе или сети. Да, это хорошая дыра - подключение поддержки скриптов в конфиге. Наверное можно локализовать доступ к ресурсам у интерпретаторов языков. По моему у Rhino была такая возможность (сделать песочницу без диступа во внешний мир). сначала сделать, а потом с этим бороться - очень современный тренд uid unique, если предполагается только работа с числами лучше ANTLR повторить и сделать простой калькулятор вида compile(Code) eval (CompiledCode, Map<varname, double>, Map<funcname, funcobj>) примеров в сети полно, будет быстрее и в разратке и в скорости выполнения по сравнению с универсальными языками ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 16:39 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)uid unique, если предполагается только работа с числами лучше ANTLR повторить и сделать простой калькулятор вида compile(Code) eval (CompiledCode, Map<varname, double>, Map<funcname, funcobj>) примеров в сети полно, будет быстрее и в разратке и в скорости выполнения по сравнению с универсальными языками Спасибо, сравню с тем что накопал по старинке из JavaCC. Смущает то что нужно писать грамматику, потом компилить ее и делать какие то пассы руками, было бы отлично компилить парсер на лету, модифицируя грамматику программным путем. Пример json парсеров на ANTLR и JavaCC: https://dzone.com/articles/antlr-and-javacc-parser-generators К слову нашел пример парсера для калькулятора с фунциями, который можно расширить, так что проблема в принципе решена старыми методами (что не удивительно). Наткнулся на интересный проект где парсер создается из кода а не компиляцией файла грамматики как в JavaCC / ANTLR, это может быть интересно: https://github.com/jparsec/jparsec https://github.com/jparsec/jparsec/wiki/Tutorial Пример калькулятора https://github.com/jparsec/jparsec/blob/master/jparsec-examples/src/main/java/org/jparsec/examples/calculator/Calculator.java Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. Пример SQL парсера: https://github.com/jparsec/jparsec/tree/master/jparsec-examples/src/main/java/org/jparsec/examples/sql Забавный проект, не находите? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 18:24 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
По статистике использований mvnrepository, ANTLR более распространен чем JavaCC. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 22:42 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniqueСмущает то что нужно писать грамматику, потом компилить ее и делать какие то пассы руками, было бы отлично компилить парсер на лету, модифицируя грамматику программным путем. Код предгенерации парсера может быть очень большим и трудозатратным для выполнения - даже лексер не так прост как кажется, так что это логично Гораздо больше людей смущают ошибки, которые выдают нагенерированные парсеры uid uniqueНаткнулся на интересный проект где парсер создается из кода а не компиляцией файла грамматики как в JavaCC / ANTLR, это может быть интересно: https://github.com/jparsec/jparsec https://github.com/jparsec/jparsec/wiki/Tutorial ... Забавный проект, не находите? Таких проектов - вагон и маленькая тележка Большинство из них страдают и по скорости работы (вплоть до O(exp(N)) ) и по трудозатратам на их поддержку Более-менее как-то можно приспособить вариации алгоритма сортировочная станция . Но в целом это выходит сложнее для понимания и расширения, чем код на EBNF ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.01.2017, 22:43 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
Apache felix жеж ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 02:18 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
no56892Apache felix жеж OSGi контейнер для динамически подключаемых/отключаемых сервисов но как это относится к парсеру. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 11:45 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)Более-менее как-то можно приспособить вариации алгоритма сортировочная станция . Но в целом это выходит сложнее для понимания и расширения, чем код на EBNF Самое простое получается сделать грамматику с токеном функции, потом сгенерить парсер на АNTRL или JavaCC, получить из выражения бинарное дерево и пройти его стековой машиной с нижнего правого листа до корня. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 12:03 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniqueno56892Apache felix жеж OSGi контейнер для динамически подключаемых/отключаемых сервисов но как это относится к парсеру. Добавляем бандл с новым оператором -> парсер в рантайме ловит это событие и записывает в свой мэп операторов. Бандл конечно нужно компилить и собирать это понятно, но вот перекомпилировать/перезапускать сам парсер не нужно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 15:48 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
no56892uid uniqueпропущено... OSGi контейнер для динамически подключаемых/отключаемых сервисов но как это относится к парсеру. Добавляем бандл с новым оператором -> парсер в рантайме ловит это событие и записывает в свой мэп операторов. Бандл конечно нужно компилить и собирать это понятно, но вот перекомпилировать/перезапускать сам парсер не нужно. Конечно можно и OSGi использовать, это почти что (веб) сервисы - сериализация, интерфейсы в блюпринтах, свои плюсы но и свои минусы. Самое печальное когда OSGi сервис в большом приложении тихо падает и понять что именно сдохло можно только через лог или OSGi консоль. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.01.2017, 19:47 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniquekealon(Ruslan)Более-менее как-то можно приспособить вариации алгоритма сортировочная станция . Но в целом это выходит сложнее для понимания и расширения, чем код на EBNF Самое простое получается сделать грамматику с токеном функции, потом сгенерить парсер на АNTRL или JavaCC, получить из выражения бинарное дерево и пройти его стековой машиной с нижнего правого листа до корня. не всегда, стопроцентно потребуется ленивый if(expr, v_if, v_else) - его так не сделать ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 10:26 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
uid uniqueДля калькулятора слишком могучая (и тяжелая) штукаЭт точно uid uniqueНужен калькулятор с поддержкой функций, функции могут быть специфическими, к примеру залезть в базу, найти какой маппинг и тд и выдать результат который в свою очередь может обработаться другой бизнес функцией (в этом причина зачем нужна поддержка новых функций через конфиг), пример вычисления какой то надписи с заходом в базу и получением имя хоста (об имплементации этих фунций мы понятия не имеем, наше дело скормить им аргументы и получить результат)SpEL - подходит под ваши требования: парсер выражений из коробки, имеется возможность вызова Java-функций: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 13:02 |
|
||
|
Расширяемый парсер для интерпретатора выражений (калькулятор с функциями)
|
|||
|---|---|---|---|
|
#18+
UsmanSpEL - подходит под ваши требования: парсер выражений из коробки, имеется возможность вызова Java-функций: Спасибо Usman за наводку, это "ядрен батон". присмотрюсь внимательнее так как спринг пробегает почти во всех проектах хотя бы косвенно (в виде зависимости): http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.01.2017, 17:54 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=77&tid=2123295]: |
0ms |
get settings: |
7ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
36ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
62ms |
get tp. blocked users: |
2ms |
| others: | 196ms |
| total: | 340ms |

| 0 / 0 |
