Разрешение неизвестной переменной ExprTK в зависимости от типа выражения

Я пытаюсь создать парсер для логических выражений. Символы внутри выражения считываются из XML-подобной структуры данных.

Это просто реализовать парсер для чего-то вроде

a.b == 'some value'

используя ExprTK с помощью «неизвестного преобразователя символов», который разрешает a.b как строку, возвращая строковое значение <a><b>some value</b></a>,

Но теперь рассмотрим XML <a><b>5</b></a>

Есть ли способ написать неизвестный преобразователь символов, который позволяет оценить как a.b == 5 а также a.b == '5'?

3

Решение

Первоначально в ExprTk переменная (определенная пользователем или локальное выражение) может быть только одного типа (скаляр, строка или вектор скаляров). Так что, если ваше выражение:

"a.b == 5 and a.b == '5'"

Тогда это недопустимое выражение, поскольку переменная a.b может иметь только один тип — либо скаляр, либо строку, но не оба.

Однако, если вы хотите иметь два отдельных выражения, которые используют одно и то же имя переменной, но в разных контекстах, вот так:

  • a.b == 5
  • a.b == '5'

затем да, ExprTk’s USR (Неизвестный символ Resolver) функциональность предоставляет одно из средств для определения типа неизвестного символа во время вызова USR обратный вызов, позволяющий правильно скомпилировать выражение.


В качестве примера, давайте предположим, что мы хотели бы определить USR, который будет разрешать только неизвестные символы с префиксами «Var_» а также «Str_» с типами Scalar и String соответственно.

Примеры выражений могут выглядеть следующим образом:

var_x := 2; var_x + 7

str_y := 'abc';  str_y + '123' == 'abc123'

Ниже приведен пример USR, использующий механизм расширенного обратного вызова, который разрешает переменные в указанном выше формате и, кроме того, добавляет их в таблицу первичных символов анализируемого выражения:

typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::parser<double>             parser_t;

template <typename T>
struct my_usr : public parser_t::unknown_symbol_resolver
{
typedef typename parser_t::unknown_symbol_resolver usr_t;

my_usr()
: usr_t(usr_t::e_usrmode_extended)
{}

virtual bool process(const std::string& unknown_symbol,
symbol_table_t&      symbol_table,
std::string&        error_message)
{
bool result = false;

//Is this unknown symbol in the format var_xyz ?
if (0 == unknown_symbol.find("var_"))
{
const T default_scalar = T(0);
result = symbol_table.create_variable(unknown_symbol, default_scalar);
if (!result)
{
error_message =
"Failed to create variable(" + unknown_symbol + ") in primary symbol table";
}
}
//Is this unknown symbol in the format str_xyz ?
else if (0 == unknown_symbol.find("str_"))
{
const std::string default_string = "N/A";
result = symbol_table.create_stringvar(unknown_symbol,default_string)
if (!result)
{
error_message =
"Failed to create string variable(" + unknown_symbol + ") in primary symbol table";
}
}
else
error_message = "Indeterminable symbol type.";

return result;
}
};

Остальной код такой же: один регистрирует экземпляр USR с помощью синтаксического анализатора, а затем переходит к компиляции их выражения с помощью указанного синтаксического анализатора.

Для получения дополнительной информации есть обзор Раздел 18 — Неизвестный Неизвестный

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]