
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.96] |
![]() |
|
Страницы: (117) « Первая ... 56 57 [58] 59 60 ... 116 117 ( Перейти к последнему сообщению ) |
Сообщ.
#857
,
|
|
|
Цитата Smike @ - без вычисления их значений, но чтобы и не нагружать код дополнительными условными командами -без написания отдельных процедур, чтобы добавив новую функцию в парсер, мне не приходилось шерстить код синтаксического анализатора? недавно писал парсер для сложных вормул. код показать не могу ибо комерческий. Но именно там реализация самого парсера связана только с реализацией скоббок и простых операций типа +,-,/,* а функции реализовывались вообще отдельно и добавление их к персеру выглядит как .. CRSFormulaParser<CComVariant>::CreateCustomLexem<CRSCustomSUMLexem> ("SUM"); как видиш код парсера собсто не трогается для добавления новой функции. |
Сообщ.
#858
,
|
|
|
Опять не то.
Мне нужен был чисто синтаксический анализатор из арифметического парсера! Могу даже сказать зачем: для анализа пользовательских функций, чтобы на этапе загрузки проверять их корректность. Так вот, как мне это реализовать, не переписывая полностью парсер (как он реализован я писал) и не создавая новых функций? |
Сообщ.
#859
,
|
|
|
Smike, но ты ведь не написал, как конкретно ты его реализовавал.. Если, к примеру, отображать формулу в стек, используя инверсную польскую запись, то все ошибки выявятся ещо на этапе формирования стека. Никаких отдельных проверок просто не нужно.
|
Сообщ.
#860
,
|
|
|
Никаких стеков нет, выражение вычисляется на этапе анализа.
|
Сообщ.
#861
,
|
|
|
Цитата Smike @ Никаких стеков нет, выражение вычисляется на этапе анализа. Ну опятьже если вщять мой пример.. то непосредственное хранение значений и различные операции непосредственно со значениями делает первый шаблонный параметр.. CRSFormulaParser<CComVariant> фактически чтобы значения не вычислялись, а только лиш анализировался код мне нужно написать класс CMnePofigChtoSoMnoiDelayut которые ничего не делает с пустыми операторами и использовать CRSFormulaParser<CMnePofigChtoSoMnoiDelayut> |
Сообщ.
#862
,
|
|
|
Цитата Smike @ Мне нужен был чисто синтаксический анализатор из арифметического парсера! Могу даже сказать зачем: для анализа пользовательских функций, чтобы на этапе загрузки проверять их корректность. Так вот, как мне это реализовать, не переписывая полностью парсер (как он реализован я писал) и не создавая новых функций? Да, в принципе, не сложно. Парсер разделяется на два класса - собственно парсер выражений, и класс-вычислитель. Второй передается первому в качестве шаблонного параметра. И все это выглядит примерно так: ![]() ![]() class TagPlus {;} class TagMinus {;} class TagMul {;} class TagDiv {;} class TagNegate {;} class TagSin {;} class TagCos {;} class TagLg {;} class TagLn {;} class Evaluator { public: static template<typename Tag> T1 EvalUnary(const Tag& t, double arg); static template<typename Tag> T1 EvalBinary(const Tag& t, double arg1, double arg2); }; class DummyEvaluator { public: static template<typename Tag> T1 EvalUnary(const Tag& t, double arg) {return 0;} static template<typename Tag> T1 EvalBinary(const Tag& t, double arg1, double arg2) {return 0;} }; double Evaluator::EvalUnary(const TagNegate&, double arg) {return - arg;} double Evaluator::EvalUnary(const TagSin&, double arg) {return sin(arg);} // ... double Evaluator::EvalBinary(const TagPlus&, double arg1, double arg2) {return arg1 + arg2;} double Evaluator::EvalBinary(const TagMinus&, double arg1, double arg2) {return arg1 - arg2;} template<class Eval> class Parser { public: double ParseExpression( ... ) { //... case '+': result = Eval::EvalBinary(TagPlus(), arg1, arg2); break; case '-': result = Eval::EvalBinary(TagMinus(), arg1, arg2); break; }; }; //... // Синтаксический анализ try { Parser<DummyEvaluator> p("1 + 2"); p.ParseExpression(); } //... // Вычисление try { Parser<Evaluator> p("1 + 2"); std::cout << p.ParseExpression(); } |
Сообщ.
#863
,
|
|
|
Flex Ferrum
![]() ![]() |
Сообщ.
#864
,
|
|
|
Цитата Flex Ferrum @ Да, в принципе, не сложно. Парсер разделяется на два класса - собственно парсер выражений, и класс-вычислитель. Второй передается первому в качестве шаблонного параметра. И все это выглядит примерно так: Это вполне реальный вариант, в том числе и на Дельфи, но он требует написания дополнительного кода и заглушек. А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. |
Сообщ.
#865
,
|
|
|
Для расширения функционала парсера тебе здесь нужно всего лишь:
1. Добавить новый тег, который должен вычисляться (например, TagASin) 2. Добавить в парсер распознаватель соответствующего выражения. 3. Реализовать метод ![]() ![]() double Evaluator::EvalUnary(const TagASin&, double arg) {return asin(arg);} |
Сообщ.
#866
,
|
|
|
Цитата Smike @ А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. Элегантность твоего решения я не понял ибо делфи не знаю, но чем тебе плюсовый вариант не понравился тоже мне не ясно. Какой еще код заглушки. Просто пустой класс - это не код ![]() |
Сообщ.
#867
,
|
|
|
Цитата Smike @ А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. Гы гы гы... ![]() ![]() |
Сообщ.
#868
,
|
|
|
Цитата Smike @ А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. ![]() ![]() ![]() |
Сообщ.
#869
,
|
|
|
Цитата Smike @ А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. Осталось определиться с мерилом элегантности... ![]() |
![]() |
Сообщ.
#870
,
|
|
Цитата Smike @ Мне нужен был чисто синтаксический анализатор из арифметического парсера! Смайк, какая разница? ![]() Разбор либо заканчивается ошибкой в выражении, либо удачен, а вычисление выражения должно идти отдельным этапом. Цитата Smike @ А вот такого элегантного решения в C++, как я сделал в Delphi, пока не видно. Ты смеёшься? В чём элегантность? Макросы(и вообще препроцессор) - это элегантность? 0_о #if, #else, #ifdef, #ifndef, #endif, #define, #undef, #include тебе в помощь... |