Как стать автором
Обновить

Комментарии 18

В .NET есть Expressions — именно те деревья которые Вы рисовали нативно перекладываются на Expressions и можно компилировать в нативный код.
С интересом посмотрел бы на Вашу реализацию парсинга строк.

Иронично, есть парсинг ИЗ Expression, но В я что-то не догадался сделать). Интересная мысль, думаю, можно реализовать.

И, если не ошибаюсь, Expressions из коробки умеют предоставлять информацию о возможности упрощения этого самого Expression

Достаточно ли оно умное? Оно же не знает кастомные функции, и вообще, какие-то сложные вещи типа arcsin(x + 2) + arccos(x + 2) оно вряд ли сократит. Хотя я конечно обязательно проверю.

так как это экспршн, то можно сделать кастомный статический класс со всеми необходимыми функциями.
ну а упрощать он не умеет конечно ибо обычно это просто вызов функции, например: System.Math.Sqrt(a). можно по имени функции вообще парсить и вручную оптимизировать и не вызывать системные функции.

Так и есть (по имени парсинг), но зачем все это, если можно сделать более умное выражение, которое по скорости почти такое же (спойлер: во второй части будет кэш => в некоторых случаях быстрее системной функции)?

Для того, чтобы не переписывать код, а использовать уже реализованный со встроенными приколюхами, дополнив их своими. Для тех же Expression есть ExpressionVisitor, который можно наследовать и переопределить по надобности.

По поводу скорости, вместо кэширования, я бы предпочёл возможность компилировать готовые выражения в полноценные Func-делегаты на этапе инициализации. Дешево и сердито.

Собственно, спустя более чем полтора года я готов рассказать намного больше.


Сейчас в библиотеке используются Linq.Expression для компиляции в Func, я даже писал детальную статью по этой теме.


Но само математическое выражение не будет в виде дотнетовских экспрешнов, так как в этом нет никакого смысла — нам нужны конструкции, которых в сишарпе тупо нет (на основе синтаксиса которого эти linq.expression и работают). Да и работать с ними вряд ли было бы так же удобно, как с кастомными, которые теперь переписаны на рекорды.

НЛО прилетело и опубликовало эту надпись здесь

Ну конечно, ведь она в принципе не иллюстрирует как их писать, ты немного промазал тредом.

А как же их надо писать, если не секрет?

lex / yacc / bison / pccts / antlr
И это только то, чем в 90х пользовались. Кто-ж их руками разбирает-то?
Вы просто перечислили парсер-генераторы, из которых шарп поддерживает только antlr. Но все они генерируют AST, дальше все равно придется с ним работать в коде. Да и в принципе, судя по всему часть с парсингом опущена в статье, потому что сразу идёт работа с деревом выражений
Вообще то есть CsLex и Jay (CS-yacc)
А еще весь этот калькулятор(включая взятие производных и упрощение выражений) проще было написать на Prolog, было бы намного короче.

Идея была написать либу с нуля, но можно в принципе заменить парсинг на существующий, спасибо

Их и не надо писать. Когда мне на C# понадобился парсер, я взял pidgin. Вот пример как им не надо пользоваться :)


https://github.com/timeseries-ru/infered

Во время прочтения появилось ощущения дежавю — делал уже нечто подобное. После того как увидел ссылки на мою старую статью 2014 года стало все понятно. Был приятно удивлен, продолжайте разработку :) Свой код я уже перевел на ANTLR, ну и в целом неплохо было бы его переписать.

Хотелось бы добавить, что упрощение — это не всегда хорошо. На практике я сталкивался с тем, что после упрощения e-x превращался в ex, что сильно сужало диапазон численно вычисляемых значений.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории