This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// dice-parser.js
|
||||
// DiceParser.js
|
||||
|
||||
function roll(sides) {
|
||||
return Math.floor(Math.random() * sides) + 1;
|
||||
@@ -27,10 +27,9 @@ export function parse(expr) {
|
||||
const tokens = tokenize(expr);
|
||||
if (!tokens.length) throw new Error('Empty expression');
|
||||
let pos = 0;
|
||||
const rolls = [];
|
||||
|
||||
function peek() { return tokens[pos]; }
|
||||
function consume() { return tokens[pos++]; }
|
||||
const peek = () => tokens[pos];
|
||||
const consume = () => tokens[pos++];
|
||||
|
||||
function parseExpr() { return parseAddSub(); }
|
||||
|
||||
@@ -41,7 +40,7 @@ export function parse(expr) {
|
||||
const right = parseMulDiv();
|
||||
left = {
|
||||
value: op === '+' ? left.value + right.value : left.value - right.value,
|
||||
rolls: [...left.rolls, ...right.rolls],
|
||||
steps: [...left.steps, { type: 'op', op }, ...right.steps],
|
||||
};
|
||||
}
|
||||
return left;
|
||||
@@ -55,7 +54,7 @@ export function parse(expr) {
|
||||
if (op === '/' && right.value === 0) throw new Error('Division by zero');
|
||||
left = {
|
||||
value: op === '*' ? left.value * right.value : Math.floor(left.value / right.value),
|
||||
rolls: [...left.rolls, ...right.rolls],
|
||||
steps: [...left.steps, { type: 'op', op }, ...right.steps],
|
||||
};
|
||||
}
|
||||
return left;
|
||||
@@ -65,7 +64,7 @@ export function parse(expr) {
|
||||
if (peek() === '-') {
|
||||
consume();
|
||||
const r = parsePrimary();
|
||||
return { value: -r.value, rolls: r.rolls };
|
||||
return { value: -r.value, steps: [{ type: 'op', op: '-' }, ...r.steps] };
|
||||
}
|
||||
return parsePrimary();
|
||||
}
|
||||
@@ -79,7 +78,10 @@ export function parse(expr) {
|
||||
const inner = parseExpr();
|
||||
if (peek() !== ')') throw new Error('Missing closing )');
|
||||
consume();
|
||||
return inner;
|
||||
return {
|
||||
value: inner.value,
|
||||
steps: [{ type: 'op', op: '(' }, ...inner.steps, { type: 'op', op: ')' }],
|
||||
};
|
||||
}
|
||||
|
||||
const diceInfo = parseDiceToken(tok);
|
||||
@@ -90,7 +92,8 @@ export function parse(expr) {
|
||||
|
||||
if (/^\d+$/.test(tok)) {
|
||||
consume();
|
||||
return { value: parseInt(tok), rolls: [] };
|
||||
const v = parseInt(tok);
|
||||
return { value: v, steps: [{ type: 'const', value: v }] };
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected token: ${tok}`);
|
||||
@@ -119,12 +122,13 @@ export function parse(expr) {
|
||||
}
|
||||
|
||||
const entry = { sides, rawRolls, kept, mod, value: kept.reduce((a, b) => a + b, 0) };
|
||||
rolls.push(entry);
|
||||
return { value: entry.value, rolls: [entry] };
|
||||
return {
|
||||
value: entry.value,
|
||||
steps: [{ type: 'dice', entry }],
|
||||
};
|
||||
}
|
||||
|
||||
const result = parseExpr();
|
||||
if (pos < tokens.length) throw new Error(`Unexpected token: ${tokens[pos]}`);
|
||||
|
||||
return { total: result.value, rolls: result.rolls };
|
||||
return { total: result.value, steps: result.steps };
|
||||
}
|
||||
Reference in New Issue
Block a user