All pastes #27353 Raw Edit

Mine

public cpp v1 · immutable
#27353 ·published 2005-11-01 23:04 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;}static char *get_token (const char **s){  const char *x = *s;  static char storage [1000];  // Skip spaces at the beginning  while (*x && isspace (*x))    x++;  // If at the end of string, return empty token  if (!*x)  {    storage [0] = 0;    return storage;  }  char quote;  bool has_quote = !!strchr (quotes, quote = *x);  if (has_quote)    x++;  const char *e = x;  if (has_quote)    while (*e && (*e != quote))      e++;  else    while (*e && isalnum (*e))      e++;  if (e >= x + sizeof (storage))    e = x + sizeof (storage) - 1;  memcpy (storage, x, e - x);  storage [e - x] = 0;  if (has_quote && *e)    e++;  *s = e;  return storage;}