Здравствуйте, bybor, Вы писали:
B>Надо написать парсер выражений. Язык программирования — C#. В выражении могут быть арифметические операции, предопределенные функции (MIN, MAX, ABS, ...), и в качестве переменных — названия полей таблиц базы данных. Парсер будет использоваться для "вычисляемых" полей в отчётах. Вычисление будет задаваться выражением, которое требуется разобрать (желательно на этапе ввода, чтобы не заниматься этим при отображении отчёта), подставить туда значения для текущего кортежа и вернуть результат.
B>Как я понимаю, задача сводится к обычному "калькулятору" с возможностью задания переменных.
Самый быстрый и реально работающий способ (не без недостатков, конечно) это тупо писать выражения на C#, а потом компилировать их в runtime и выполнять. Удобно для этого завести базовый класс с виртуальным методом типа Calculate, а динамический класс от него наследовать. В нём тогда можно наопределять protected методов Min, Max и всё, что угодно.
Плюсы — выражение будет вычисляться быстро и очень легко расширять дополнительными функциями.
Минус — на C# пользователь может написать больше, чем того хотелость, то есть тут потенцияльная дырка в секьюрити. Дырка закрывается дополнительной валидацией скомпилированного.
Надо написать парсер выражений. Язык программирования — C#. В выражении могут быть арифметические операции, предопределенные функции (MIN, MAX, ABS, ...), и в качестве переменных — названия полей таблиц базы данных. Парсер будет использоваться для "вычисляемых" полей в отчётах. Вычисление будет задаваться выражением, которое требуется разобрать (желательно на этапе ввода, чтобы не заниматься этим при отображении отчёта), подставить туда значения для текущего кортежа и вернуть результат.
Как я понимаю, задача сводится к обычному "калькулятору" с возможностью задания переменных.
Вопрос собственно по реализации. Можно всё это сделать самому или попробовать ANTLR (Coco/R ? ).
Опыта в этой области нет вообще. Если делать самому, то всё не очень страшно, но смущает дальнейшее расширение функциональности. Например, логические операции или ещё что-нить такое. В готовых примерах, на которые я натыкался — на том же CodeProject, почти весь код имеет некоторые ограничения — например поддержка унарных операторов или вложенные скобки в логических выражениях. Я не понимаю, являются ли эти задачи сложными для реализации, или они настолько тривиальны, что авторы не стали тратить на это время.
Может быть лучше будет построить грамматику и использовать ANTLR/CocoR для генерации кода парсера на C#? Насколько это будет трудоёмко для чайника? И насколько хорошо в эту грамматику лягут названия полей из базы данных?
Время на разработку как бы есть, но чем быстрее, тем лучше.
Здравствуйте, bybor, Вы писали:
B>Надо написать парсер выражений. Язык программирования — C#. В выражении могут быть арифметические операции, предопределенные функции (MIN, MAX, ABS, ...), и в качестве переменных — названия полей таблиц базы данных. Парсер будет использоваться для "вычисляемых" полей в отчётах. Вычисление будет задаваться выражением, которое требуется разобрать (желательно на этапе ввода, чтобы не заниматься этим при отображении отчёта), подставить туда значения для текущего кортежа и вернуть результат.
B>Как я понимаю, задача сводится к обычному "калькулятору" с возможностью задания переменных.
B>Вопрос собственно по реализации. Можно всё это сделать самому или попробовать ANTLR (Coco/R ? ). B>Опыта в этой области нет вообще. Если делать самому, то всё не очень страшно, но смущает дальнейшее расширение функциональности. Например, логические операции или ещё что-нить такое. В готовых примерах, на которые я натыкался — на том же CodeProject, почти весь код имеет некоторые ограничения — например поддержка унарных операторов или вложенные скобки в логических выражениях. Я не понимаю, являются ли эти задачи сложными для реализации, или они настолько тривиальны, что авторы не стали тратить на это время.
B>Может быть лучше будет построить грамматику и использовать ANTLR/CocoR для генерации кода парсера на C#? Насколько это будет трудоёмко для чайника? И насколько хорошо в эту грамматику лягут названия полей из базы данных?
B>Время на разработку как бы есть, но чем быстрее, тем лучше.
B>Спасибо.
Бери генератор аля Yacc Bison + Lex( Flex ) , ну или похожие инструменты,
потратишь время на то, чтобы разобраться и долетишь за 5 мин,
плюс дальше времени на изменения в синтаксисе или функционале будут занимать минимум времени.
Я в свое время только на lex, сделал парсер wiki синтаксиса.
Хотя руками это тоже не страшно, строишь дерево по выражению, ну с глубины начинаешь считать результат.
Если надо потом будет часто что-то добавлять то однозначно генератор.
Если редко то тоже генератор
Здравствуйте, fortuna, Вы писали:
F>Бери генератор аля Yacc Bison + Lex( Flex ) , ну или похожие инструменты, F>потратишь время на то, чтобы разобраться и долетишь за 5 мин,
Т.к. у меня C#, то соответственно — ANTLR и Coco.
F>плюс дальше времени на изменения в синтаксисе или функционале будут занимать минимум времени. F>Я в свое время только на lex, сделал парсер wiki синтаксиса.
Передача значений в моём случае — это будут переменные в грамматике?
Здравствуйте, vmpire, Вы писали:
V>Самый быстрый и реально работающий способ (не без недостатков, конечно) это тупо писать выражения на C#, а потом компилировать их в runtime и выполнять. Удобно для этого завести базовый класс с виртуальным методом типа Calculate, а динамический класс от него наследовать. В нём тогда можно наопределять protected методов Min, Max и всё, что угодно.
Мне всё равно придётся парсить каким-то образом введённый текст. Хотя бы для выделения имён переменных (полей таблицы). В случае ошибки ввода — будет сложнее сказать пользователю что не так. Отдавать ему сообщения компилятора как-то не катит. Одно дело генерить код на C# на основе ввода, а другое — рассматривать ввод как готовый код. ИМХО, конечно.
V>Плюсы — выражение будет вычисляться быстро и очень легко расширять дополнительными функциями. V>Минус — на C# пользователь может написать больше, чем того хотелость, то есть тут потенцияльная дырка в секьюрити. Дырка закрывается дополнительной валидацией скомпилированного.
Ага, принцип понял. Спасибо.
Здравствуйте, vmpire, Вы писали:
V>Самый быстрый и реально работающий способ (не без недостатков, конечно) это тупо писать выражения на C#, а потом компилировать их в runtime и выполнять.
При таком способе в силу отдельных ньюнсов при развитии кода может встать необходимость в парсере, который бы понимал весь C#.
Здравствуйте, Mystic, Вы писали:
V>>Самый быстрый и реально работающий способ (не без недостатков, конечно) это тупо писать выражения на C#, а потом компилировать их в runtime и выполнять.
M>При таком способе в силу отдельных ньюнсов при развитии кода может встать необходимость в парсере, который бы понимал весь C#.
Зачем?
Здравствуйте, bybor, Вы писали:
B>Здравствуйте, fortuna, Вы писали:
F>>Бери генератор аля Yacc Bison + Lex( Flex ) , ну или похожие инструменты, F>>потратишь время на то, чтобы разобраться и долетишь за 5 мин, B>Т.к. у меня C#, то соответственно — ANTLR и Coco.
F>>плюс дальше времени на изменения в синтаксисе или функционале будут занимать минимум времени. F>>Я в свое время только на lex, сделал парсер wiki синтаксиса. B>Передача значений в моём случае — это будут переменные в грамматике?
Ну как ты это назовешь тем это и будет, суть разбора сводится к построению дерева выражения и его вычисления.
т.е это скорее будут лексемы
MIN( (a+b), (b+10), f(c+d) )
получится как нечто такое
(MIN
(+ (a b ))
(+ (b 10 ))
(f
(+ ( c d ))
)
)
начинаем c глубины т.е c
+ ( c d ) далее f от результата, т.к. выражения MIN на одном уровне их вычисляем в любом порядке,
и вычисляем MIN для них.
я бы посоветовал для начала почитать немного теории.