|
|
@@ -12,44 +12,44 @@
|
|
|
|
|
|
#include "dice-roll/exception.h"
|
|
|
|
|
|
-static void advance_over_whitespace(std::istream & in, char const * also = "") {
|
|
|
- if (strchr(also, in.peek())) { in.get(); }
|
|
|
- while (isspace(in.peek())) {
|
|
|
- in.get();
|
|
|
+static void advance_over_whitespace(std::istream & is, char const * also = "") {
|
|
|
+ if (strchr(also, is.peek())) { is.get(); }
|
|
|
+ while (isspace(is.peek())) {
|
|
|
+ is.get();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
namespace dice {
|
|
|
|
|
|
void parser::parse_dN(sign s, int value) {
|
|
|
- advance_over_whitespace(in, "dD");
|
|
|
+ advance_over_whitespace(is_, "dD");
|
|
|
// Disallow 0dM, as that is not a real thing...
|
|
|
- d.of.push_back({s, std::max(value, 1), 0});
|
|
|
- if (!isnumber(in.peek())) {
|
|
|
- throw unexpected_token("Expected a number of sides", in.tellg());
|
|
|
+ dice_.of.push_back({s, std::max(value, 1), 0});
|
|
|
+ if (!isnumber(is_.peek())) {
|
|
|
+ throw unexpected_token("Expected a number of sides", is_.tellg());
|
|
|
}
|
|
|
- in >> d.of.back().sides;
|
|
|
+ is_ >> dice_.of.back().sides;
|
|
|
parse_impl(ZERO);
|
|
|
}
|
|
|
|
|
|
void parser::parse_const(sign s, int value) {
|
|
|
if (value) { // Zero is not a modifier we care about
|
|
|
- d.modifier.push_back({s, std::abs(value)});
|
|
|
+ dice_.modifier.push_back({s, std::abs(value)});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void parser::parse_impl(sign s) {
|
|
|
- advance_over_whitespace(in);
|
|
|
+ advance_over_whitespace(is_);
|
|
|
// By defaulting this to zero, we can write a more elegant handling of
|
|
|
// expressions like 1d4+1d6+5+1
|
|
|
int value = 0;
|
|
|
- if (isnumber(in.peek())) {
|
|
|
- in >> value;
|
|
|
- } else if (in.peek() == EOF && s != ZERO) {
|
|
|
+ if (isnumber(is_.peek())) {
|
|
|
+ is_ >> value;
|
|
|
+ } else if (is_.peek() == EOF && s != ZERO) {
|
|
|
throw unexpected_token("Unexpected EOF while parsing", -1);
|
|
|
}
|
|
|
- advance_over_whitespace(in);
|
|
|
- switch (in.peek()) {
|
|
|
+ advance_over_whitespace(is_);
|
|
|
+ switch (is_.peek()) {
|
|
|
case 'd':
|
|
|
case 'D':
|
|
|
return parse_dN(s, value);
|
|
|
@@ -58,7 +58,7 @@ void parser::parse_impl(sign s) {
|
|
|
// Handle 5+... cases
|
|
|
parse_const(s, value);
|
|
|
// Add another token
|
|
|
- parse_impl((in.get() == '+') ? PLUS : MINUS);
|
|
|
+ parse_impl((is_.get() == '+') ? PLUS : MINUS);
|
|
|
break;
|
|
|
default:
|
|
|
parse_const(s, value);
|
|
|
@@ -67,34 +67,34 @@ void parser::parse_impl(sign s) {
|
|
|
}
|
|
|
|
|
|
dice parser::parse() {
|
|
|
- d = {};
|
|
|
+ dice_ = {};
|
|
|
int value{1};
|
|
|
- advance_over_whitespace(in);
|
|
|
- if (isnumber(in.peek())) { in >> value; }
|
|
|
- advance_over_whitespace(in);
|
|
|
+ advance_over_whitespace(is_);
|
|
|
+ if (isnumber(is_.peek())) { is_ >> value; }
|
|
|
+ advance_over_whitespace(is_);
|
|
|
|
|
|
- switch (in.peek()) {
|
|
|
+ switch (is_.peek()) {
|
|
|
case 'd':
|
|
|
case 'D':
|
|
|
parse_impl(ZERO);
|
|
|
- d.of.front().num = value;
|
|
|
+ dice_.of.front().num = value;
|
|
|
break;
|
|
|
case '{':
|
|
|
- in.get();
|
|
|
- d.num = value;
|
|
|
+ is_.get();
|
|
|
+ dice_.num = value;
|
|
|
parse_impl(ZERO);
|
|
|
- if (in.get() != '}') {
|
|
|
+ if (is_.get() != '}') {
|
|
|
throw unexpected_token("Expected closing '}' in repeated roll",
|
|
|
- in.tellg());
|
|
|
+ is_.tellg());
|
|
|
}
|
|
|
break;
|
|
|
case EOF:
|
|
|
- throw unexpected_token("No dice in expression", in.tellg());
|
|
|
+ throw unexpected_token("No dice in expression", is_.tellg());
|
|
|
default:
|
|
|
- throw unexpected_token("Unexpected token", in.tellg());
|
|
|
+ throw unexpected_token("Unexpected token", is_.tellg());
|
|
|
}
|
|
|
|
|
|
- return d;
|
|
|
+ return dice_;
|
|
|
}
|
|
|
|
|
|
}
|