19 #define TECA_PARSER_ERROR(_descr, _expr, _pos) \
20 TECA_MESSAGE(std::cerr, "ERROR:", ANSI_RED, \
22 << "at position " << (_pos) << " in \"" \
23 << std::string(_expr, _expr+(_pos)) << END_HL \
24 << BEGIN_HL(ANSI_RED) << (_expr+(_pos))[0] << END_HL \
25 << BEGIN_HL(ANSI_WHITE) << std::string(_expr+(_pos)+1) << "\"")
27 #define TECA_SYNTAX_ERROR(_expr, _pos) \
28 TECA_PARSER_ERROR("Syntax error. ", _expr, _pos)
30 #define TECA_NAME_RESOLUTION_ERROR(_name, _expr, _pos) \
31 TECA_PARSER_ERROR("Name resolution error \"" \
32 << _name << "\". ", _expr, _pos)
34 #define TECA_INVALID_OPERATION_ERROR(_op, _expr, _pos) \
35 TECA_PARSER_ERROR("Invalid operation \"" \
36 << _op << "\". ", _expr, _pos)
38 #define TECA_OPERATION_FAILED_ERROR(_op, _expr, _pos) \
39 TECA_PARSER_ERROR("Operation \"" << _op \
40 << "\" failed. " , _expr, _pos)
42 #define TECA_NUM_OPERANDS_ERROR(_op, _nreq, _ngive, _expr, _pos) \
43 TECA_PARSER_ERROR("Operation \"" << _op \
44 << "\" requires " << _nreq << " operands, given " \
45 << _ngive << ". ", _expr, _pos)
59 static unsigned int get_open_group(
const char *s,
char *g);
60 static unsigned int get_close_group(
const char *s,
char *g);
61 static unsigned int get_constant_name(
const char *s,
char *c);
62 static unsigned int get_variable_name(
const char *s,
char *v);
63 static unsigned int get_unary_operator_name(
const char *expr,
char *op_name);
64 static unsigned int get_binary_operator_name(
const char *expr,
char *op_name);
65 static unsigned int get_ternary_operator_name(
const char *expr,
char *op_name);
66 static unsigned int get_operator_precedence(
char *op);
76 template<
typename tokenizer_t=teca_parser::tokenizer>
79 std::vector<char*> operator_stack;
80 std::vector<unsigned int> group_position;
82 const char *expr = iexpr;
83 unsigned int n = strlen(expr);
84 char *rexpr =
static_cast<char*
>(malloc(3*n));
85 char *rpnexpr = rexpr;
87 unsigned int token_len;
95 while(*expr && isspace(*expr)) ++expr;
98 else if ((token_len = tokenizer_t::get_open_group(expr, token)))
100 token[token_len-1] =
'\0';
102 char *tmp = infix_to_postfix<tokenizer_t>(token+1, variables);
103 unsigned int tmp_len = strlen(tmp);
105 memcpy(rexpr, tmp, tmp_len);
113 else if ((token_len = tokenizer_t::get_constant_name(expr, token)))
115 memcpy(rexpr, token, token_len);
122 else if ((token_len = tokenizer_t::get_variable_name(expr, token)))
125 variables->insert(token);
127 memcpy(rexpr, token, token_len);
134 else if ((token_len = tokenizer_t::get_ternary_operator_name(expr, token))
135 || (token_len = tokenizer_t::get_binary_operator_name(expr, token))
136 || (token_len = tokenizer_t::get_unary_operator_name(expr, token)))
140 unsigned int p1 = tokenizer_t::get_operator_precedence(token);
141 while (operator_stack.size() &&
142 (tokenizer_t::get_operator_precedence(operator_stack.back()) >= p1))
144 char *op_name = operator_stack.back();
145 unsigned int op_len = strlen(op_name);
147 operator_stack.pop_back();
149 memcpy(rexpr, op_name, op_len);
157 operator_stack.push_back(strdup(token));
163 TECA_SYNTAX_ERROR(iexpr, expr-iexpr)
169 if (group_position.size())
171 TECA_SYNTAX_ERROR(iexpr, group_position.back())
176 while (operator_stack.size())
178 char *op_name = operator_stack.back();
179 unsigned int op_len = strlen(op_name);
181 operator_stack.pop_back();
183 memcpy(rexpr, op_name, op_len);
204 template<
typename work_t,
typename arg_t,
typename operand_resolver_t,
207 const char *iexpr, operand_resolver_t &operands)
213 unsigned int token_len;
215 std::vector<arg_t> var_stack;
217 const char *expr = iexpr;
223 while(*expr && isspace(*expr)) ++expr;
226 else if ((token_len = tokenizer_t::get_constant_name(expr, token)))
229 if (operands.get_constant(token, var))
231 TECA_NAME_RESOLUTION_ERROR(token, iexpr, expr-iexpr)
234 var_stack.push_back(var);
238 else if ((token_len = tokenizer_t::get_variable_name(expr, token)))
241 if (operands.get_variable(token, var))
243 TECA_NAME_RESOLUTION_ERROR(token, iexpr, expr-iexpr)
246 var_stack.push_back(var);
250 else if ((token_len = tokenizer_t::get_ternary_operator_name(expr, token)))
253 unsigned int n_operands = var_stack.size();
256 TECA_NUM_OPERANDS_ERROR(token, 3, n_operands, iexpr, expr-iexpr)
261 arg_t arg3 = var_stack.back();
262 var_stack.pop_back();
264 arg_t arg2 = var_stack.back();
265 var_stack.pop_back();
267 arg_t arg1 = var_stack.back();
268 var_stack.pop_back();
273 if ((err_code = operator_resolver_t::invoke(token, result, arg1, arg2, arg3)))
277 TECA_INVALID_OPERATION_ERROR(token, iexpr, expr-iexpr)
279 else if (err_code == -2)
281 TECA_OPERATION_FAILED_ERROR(token, iexpr, expr-iexpr)
287 var_stack.push_back(result);
292 else if ((token_len = tokenizer_t::get_binary_operator_name(expr, token)))
295 unsigned int n_operands = var_stack.size();
298 TECA_NUM_OPERANDS_ERROR(token, 2, n_operands, iexpr, expr-iexpr)
303 arg_t right_arg = var_stack.back();
304 var_stack.pop_back();
306 arg_t left_arg = var_stack.back();
307 var_stack.pop_back();
312 if ((err_code = operator_resolver_t::invoke(token, result, left_arg, right_arg)))
316 TECA_INVALID_OPERATION_ERROR(token, iexpr, expr-iexpr)
318 else if (err_code == -2)
320 TECA_OPERATION_FAILED_ERROR(token, iexpr, expr-iexpr)
326 var_stack.push_back(result);
331 else if ((token_len = tokenizer_t::get_unary_operator_name(expr, token)))
334 unsigned int n_operands = var_stack.size();
337 TECA_NUM_OPERANDS_ERROR(token, 1, n_operands, iexpr, expr-iexpr)
342 arg_t arg = var_stack.back();
343 var_stack.pop_back();
348 if ((err_code = operator_resolver_t::invoke(token, result, arg)))
352 TECA_INVALID_OPERATION_ERROR(token, iexpr, expr-iexpr)
354 else if (err_code == -2)
356 TECA_OPERATION_FAILED_ERROR(token, iexpr, expr-iexpr)
362 var_stack.push_back(result);
371 TECA_SYNTAX_ERROR(iexpr, expr-iexpr)
378 if (var_stack.size() != 1)
380 TECA_SYNTAX_ERROR(iexpr, expr-iexpr)
383 iexpr_result = var_stack.back();
Definition: teca_parser.h:57
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
Codes dealing with expression parsing.
Definition: teca_parser.h:49
int eval_postfix(arg_t &iexpr_result, const char *iexpr, operand_resolver_t &operands)
Definition: teca_parser.h:206
char * infix_to_postfix(const char *iexpr, std::set< std::string > *variables)
Definition: teca_parser.h:77