Компьютер и человек — как сложно нам понять друг друга. По сути, процесс программирования — это объяснение машине то, что ты от неё хочешь на понятном ей языке.
В качестве введения
По своей работе, да и в качестве хобби, я связан с процессом написания кода, связанного с математическими вычислениями. Одной из последних задач было написание ПО, в котором пользователь имел бы возможность самостоятельно вводить и использовать при расчёте, визуализации данных и оптимизации некоторых математических выражений. А учитывая свою природную лень и нежелание постоянно дополнять библиотеку кода специальных математических функций пришла в голову мысль — а почему бы не реализовать бредовую студенческую идею, и не изобрести велосипед парсера математических выражений.
Конечно, прежде чем взяться за изобретательский процесс (опять же, в виду вселенской лени), было достаточно долгое изнасилование Яндекса и Гугла на предмет уже существующих реализаций. И их нашлось конечно же не мало. Но к сожалению того, чего хотелось добиться от конкретной реализации не нашлось. А критерии поиска были следующие:
- Парсер должен быть реализован под .NET не старше 4.0;
- Он должен обрабатывать все базовые математические операторы (+,-,*,/,^, и т.п.) с учётом их приоритетов и скобок разных видов;
- Он должен распознавать основные функции (вроде sin, cos), иметь возможность добавлять в созданный объект парсера свои функции с указанием делегатов методов, вычисляющих их значение (для любого количества входных переменных);
- Должна быть возможность использования известных парсеру констант, и добавления их с список, используемый при разборе выражения;
- Должен присутствовать механизм работы с параметрами и переменными. При этом требуются переменные разных типов: просто хранящие числовое значение, либо вызывающие событие, в котором внешний код определяет их значение на момент их вызова;
- Должен быть реализован механизм функционалов (минимум — интегрирование, сумма ряда и дифференцирование)
- Результат разбора строкового выражения должен быть представлен в объектной модели бинарного дерева;
- Самое главное — бинарное дерево должно иметь возможность отображения на дерево Linq.Expression с последующей компиляцией его в делегат, выполняющий вычисление на скорости самой платформы .NET.
Читать полностью »