61 double r =
static_cast<double> (std::rand () % RAND_MAX) / (
static_cast<double> (RAND_MAX) + 1.0);
66 const int roll (
const int howmany,
const int die)
71 for (count = 0; count < howmany; ++count)
92 static int initRandom ()
96 srand48 (time (NULL));
102 static int someNumber = initRandom ();
198 return getrandom (
static_cast <int> (arg));
203 if (
percent (
static_cast <int> (arg)))
209 const double DoMin (
const double arg1,
const double arg2)
211 return (arg1 < arg2 ? arg1 : arg2);
214 const double DoMax (
const double arg1,
const double arg2)
216 return (arg1 > arg2 ? arg1 : arg2);
219 const double DoFmod (
const double arg1,
const double arg2)
222 throw std::runtime_error (
"Divide by zero in mod");
224 return fmod (arg1, arg2);
227 const double DoPow (
const double arg1,
const double arg2)
229 return pow (arg1, arg2);
232 const double DoRoll (
const double arg1,
const double arg2)
234 return roll (
static_cast <int> (arg1),
static_cast <int> (arg2));
237 const double DoIf (
const double arg1,
const double arg2,
const double arg3)
247 typedef const double (*
ThreeArgFunction) (
const double arg1,
const double arg2,
const double arg3);
250 static std::map<std::string, OneArgFunction> OneArgumentFunctions;
251 static std::map<std::string, TwoArgFunction> TwoArgumentFunctions;
252 static std::map<std::string, ThreeArgFunction> ThreeArgumentFunctions;
255 #define STD_FUNCTION(arg) OneArgumentFunctions [#arg] = arg
257 static int LoadOneArgumentFunctions ()
259 OneArgumentFunctions [
"abs"] = fabs;
280 OneArgumentFunctions [
"int"] =
DoInt;
281 OneArgumentFunctions [
"rand"] =
DoRandom;
282 OneArgumentFunctions [
"rand"] =
DoRandom;
283 OneArgumentFunctions [
"percent"] =
DoPercent;
287 static int LoadTwoArgumentFunctions ()
289 TwoArgumentFunctions [
"min"] =
DoMin;
290 TwoArgumentFunctions [
"max"] =
DoMax;
291 TwoArgumentFunctions [
"mod"] =
DoFmod;
292 TwoArgumentFunctions [
"pow"] =
DoPow;
293 TwoArgumentFunctions [
"roll"] =
DoRoll;
297 static int LoadThreeArgumentFunctions ()
299 ThreeArgumentFunctions [
"if"] =
DoIf;
305 word_.erase (0, std::string::npos);
308 while (*pWord_ && isspace (*pWord_))
311 pWordStart_ = pWord_;
316 throw std::runtime_error (
"Unexpected end of expression.");
318 unsigned char cFirstCharacter = *pWord_;
320 if (cFirstCharacter == 0)
322 word_ =
"<end of expression>";
326 unsigned char cNextCharacter = *(pWord_ + 1);
334 (cFirstCharacter ==
'+' || cFirstCharacter ==
'-') &&
335 (isdigit (cNextCharacter) || cNextCharacter ==
'.')
337 || isdigit (cFirstCharacter)
340 || (cFirstCharacter ==
'.' && isdigit (cNextCharacter)) )
343 if ((cFirstCharacter ==
'+' || cFirstCharacter ==
'-'))
345 while (isdigit (*pWord_) || *pWord_ ==
'.')
349 if (*pWord_ ==
'e' || *pWord_ ==
'E')
352 if ((*pWord_ ==
'+' || *pWord_ ==
'-'))
354 while (isdigit (*pWord_))
358 word_ = std::string (pWordStart_, pWord_ - pWordStart_);
360 std::istringstream is (word_);
364 if (is.fail () && !is.eof ())
365 throw std::runtime_error (
"Bad numeric literal: " + word_);
371 if (cNextCharacter ==
'=')
373 switch (cFirstCharacter)
376 case '=': type_ =
EQ;
break;
377 case '<': type_ =
LE;
break;
378 case '>': type_ =
GE;
break;
379 case '!': type_ =
NE;
break;
386 default: type_ =
NONE;
break;
391 word_ = std::string (pWordStart_, 2);
397 switch (cFirstCharacter)
399 case '&':
if (cNextCharacter ==
'&')
401 word_ = std::string (pWordStart_, 2);
406 case '|':
if (cNextCharacter ==
'|')
408 word_ = std::string (pWordStart_, 2);
425 word_ = std::string (pWordStart_, 1);
427 return type_ =
TokenType (cFirstCharacter);
430 if (!isalpha (cFirstCharacter))
432 if (cFirstCharacter <
' ')
434 std::ostringstream s;
435 s <<
"Unexpected character (decimal " << int (cFirstCharacter) <<
")";
436 throw std::runtime_error (s.str ());
439 throw std::runtime_error (
"Unexpected character: " + std::string (1, cFirstCharacter));
443 while (isalnum (*pWord_) || *pWord_ ==
'_')
446 word_ = std::string (pWordStart_, pWord_ - pWordStart_);
451 static int doLoadOneArgumentFunctions = LoadOneArgumentFunctions ();
452 static int doLoadTwoArgumentFunctions = LoadTwoArgumentFunctions ();
453 static int doLoadThreeArgumentFunctions = LoadThreeArgumentFunctions ();
455 const double Parser::Primary (
const bool get)
472 std::string word = word_;
477 std::map<std::string, OneArgFunction>::const_iterator si;
478 si = OneArgumentFunctions.find (word);
479 if (si != OneArgumentFunctions.end ())
481 double v = Expression (
true);
484 return si->second (v);
488 std::map<std::string, TwoArgFunction>::const_iterator di;
489 di = TwoArgumentFunctions.find (word);
490 if (di != TwoArgumentFunctions.end ())
492 double v1 = Expression (
true);
494 double v2 = Expression (
true);
497 return di->second (v1, v2);
501 std::map<std::string, ThreeArgFunction>::const_iterator ti;
502 ti = ThreeArgumentFunctions.find (word);
503 if (ti != ThreeArgumentFunctions.end ())
505 double v1 = Expression (
true);
507 double v2 = Expression (
true);
509 double v3 = Expression (
true);
512 return ti->second (v1, v2, v3);
515 throw std::runtime_error (
"Function '" + word +
"' not implemented.");
524 case ASSIGN: v = Expression (
true);
break;
525 case ASSIGN_ADD: v += Expression (
true);
break;
526 case ASSIGN_SUB: v -= Expression (
true);
break;
527 case ASSIGN_MUL: v *= Expression (
true);
break;
530 double d = Expression (
true);
532 throw std::runtime_error (
"Divide by zero");
542 return - Primary (
true);
545 return (Primary (
true) == 0.0) ? 1.0 : 0.0;;
549 double v = CommaList (
true);
556 throw std::runtime_error (
"Unexpected token: " + word_);
562 const double Parser::Term (
const bool get)
564 double left = Primary (get);
570 left *= Primary (
true);
break;
573 double d = Primary (
true);
575 throw std::runtime_error (
"Divide by zero");
579 default:
return left;
584 const double Parser::AddSubtract (
const bool get)
586 double left = Term (get);
591 case PLUS: left += Term (
true);
break;
592 case MINUS: left -= Term (
true);
break;
593 default:
return left;
598 const double Parser::Comparison (
const bool get)
600 double left = AddSubtract (get);
605 case LT: left = left < AddSubtract (
true) ? 1.0 : 0.0;
break;
606 case GT: left = left > AddSubtract (
true) ? 1.0 : 0.0;
break;
607 case LE: left = left <= AddSubtract (
true) ? 1.0 : 0.0;
break;
608 case GE: left = left >= AddSubtract (
true) ? 1.0 : 0.0;
break;
609 case EQ: left = left == AddSubtract (
true) ? 1.0 : 0.0;
break;
610 case NE: left = left != AddSubtract (
true) ? 1.0 : 0.0;
break;
611 default:
return left;
616 const double Parser::Expression (
const bool get)
618 double left = Comparison (get);
625 double d = Comparison (
true);
626 left = (left != 0.0) && (d != 0.0);
631 double d = Comparison (
true);
632 left = (left != 0.0) || (d != 0.0);
635 default:
return left;
640 const double Parser::CommaList (
const bool get)
642 double left = Expression (get);
647 case COMMA: left = Expression (
true);
break;
648 default:
return left;
655 pWord_ = program_.c_str ();
657 double v = CommaList (
true);
659 throw std::runtime_error (
"Unexpected text at end of expression: " + std::string (pWordStart_));
std::map< std::string, double > symbols_
Symbol table mapping variable names to values. Can be accessed directly.
TokenType
Token types used by the expression lexer.
@ LHPAREN
Left parenthesis.
@ NE
Not equal comparison (!=)
@ RHPAREN
Right parenthesis.
@ NOT
Logical NOT operator.
@ EQ
Equal comparison (==)
@ ASSIGN_DIV
Compound assignment (/=)
@ DIVIDE
Division operator.
@ MULTIPLY
Multiplication operator.
@ GE
Greater than or equal (>=)
@ NAME
Identifier or variable name.
@ LT
Less than comparison.
@ ASSIGN_MUL
Compound assignment (*=)
@ ASSIGN_SUB
Compound assignment (-=)
@ LE
Less than or equal (<=)
@ NONE
No token (error state)
@ GT
Greater than comparison.
@ MINUS
Subtraction operator.
@ ASSIGN_ADD
Compound assignment (+=)
@ ASSIGN
Assignment operator.
const double Evaluate()
Evaluate the stored expression using current symbol values.
const double(* ThreeArgFunction)(const double arg1, const double arg2, const double arg3)
const bool percent(const int prob)
const double DoRoll(const double arg1, const double arg2)
const double DoIf(const double arg1, const double arg2, const double arg3)
const int getrandom(const int x)
const int roll(const int howmany, const int die)
double DoRandom(double arg)
double DoPercent(double arg)
const double DoMin(const double arg1, const double arg2)
const double DoPow(const double arg1, const double arg2)
double(* OneArgFunction)(double arg)
const double DoFmod(const double arg1, const double arg2)
const double(* TwoArgFunction)(const double arg1, const double arg2)
const double DoMax(const double arg1, const double arg2)
#define STD_FUNCTION(arg)
Mathematical expression parser for arithmetic and conditional evaluation.