All pastes #27352 Raw Edit

Unnamed

public cpp v1 · immutable
#27352 ·published 2005-11-01 23:01 UTC
rendered paste body
// Quick primitive expression evaluator// Operation priorities:// 0: ()// 1: + - | ^// 2: * / % &// 3: unary+ unary- ~// Expect to see a ')'#define PAREN_EXPECT	1// Eat the closing ')'#define PAREN_EAT	2static bool get_expression (const char **s, uint32 *v, int priority = 0, int flags = 0){  uint32 b;  char *x = get_token (s);  if (!*x)  {    // Got empty token, could be a unary operator or a parenthesis    switch (peek_char (s))    {      case '(':        (*s)++;        if (!get_expression (s, v, 0, PAREN_EAT | PAREN_EXPECT))          return false;        break;      case '+':        (*s)++;        if (!get_expression (s, v, 3, flags & ~PAREN_EAT))          return false;        break;      case '-':        (*s)++;        if (!get_expression (s, v, 3, flags & ~PAREN_EAT))          return false;        *v = (uint32)-(int32)*v;        break;      case '~':        (*s)++;        if (!get_expression (s, v, 3, flags & ~PAREN_EAT))          return false;        *v = ~*v;        break;      case 0:      case ',':        return false;      default:        Complain (C_ERROR ("line %d: Unexpected input '%hs'"), line, *s);        return false;    }  }  else  {    if (*x >= '0' && *x <= '9')    {      // We got a number      char *err;      *v = strtoul (x, &err, 0);      if (*err)      {        Complain (C_ERROR ("line %d: Expected a number, got %hs"), line, x);        return false;      }    }    // Look through variables    else if (!GetVar (x, s, v, ScriptVars, ScriptVarsCount)          && !GetVar (x, s, v, UserVars, UserVarsCount))    {      Complain (C_ERROR ("line %d: Unknown variable '%hs' in expression"),                line, x);      return false;    }  }  // Peek next char and see if it is a operator  bool unk_op = false;  while (!unk_op)  {    char op = peek_char (s);    switch (op)    {      case '+':      case '-':      case '|':      case '^':        if (priority > 1)          return true;        (*s)++;        if (!get_expression (s, &b, 1, flags & ~PAREN_EAT))          return false;        switch (op)        {          case '+': *v += b; break;          case '-': *v -= b; break;          case '|': *v |= b; break;          case '^': *v ^= b; break;        }        break;      case '*':      case '/':      case '%':      case '&':        if (priority > 2)          return true;        (*s)++;        if (!get_expression (s, &b, 2, flags & ~PAREN_EAT))          return false;        switch (op)        {          case '*': *v *= b; break;          case '/': *v /= b; break;          case '%': *v %= b; break;          case '&': *v &= b; break;        }        break;      case ')':        if (!(flags & PAREN_EXPECT))        {          Complain (C_ERROR ("line %d: Unexpected ')'"), line);          return false;        }        if (flags & PAREN_EAT)          (*s)++;        return true;      default:        unk_op = true;        break;    }  }  if (flags & PAREN_EXPECT)  {    Complain (C_ERROR ("line %d: No closing ')'"), line);    return false;  }  return true;}