m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--__tests__/lexer.test.js12
-rw-r--r--__tests__/parser.test.js12
-rw-r--r--index.js2
-rw-r--r--src/lexer.js1
-rw-r--r--src/parser.js14
5 files changed, 41 insertions, 0 deletions
diff --git a/__tests__/lexer.test.js b/__tests__/lexer.test.js
index 3003fb9..04a95e1 100644
--- a/__tests__/lexer.test.js
+++ b/__tests__/lexer.test.js
@@ -136,4 +136,16 @@ describe('lex', () => {
])
})
})
+
+ describe('keep', () => {
+ test('1K2d20', () => {
+ expect(lex('1K2d20')).toEqual([
+ { type: 'constant', value: 1 },
+ { type: 'K' },
+ { type: 'constant', value: 2 },
+ { type: 'd' },
+ { type: 'constant', value: 20 }
+ ])
+ })
+ })
})
diff --git a/__tests__/parser.test.js b/__tests__/parser.test.js
index 26febef..fb554f9 100644
--- a/__tests__/parser.test.js
+++ b/__tests__/parser.test.js
@@ -127,6 +127,18 @@ describe('parse', () => {
})
})
+ it('parses dice with keep', () => {
+ expect(parse('1K2d20')).toEqual({
+ type: 'K',
+ left: { type: 'constant', value: 1 },
+ right: {
+ type: 'd',
+ left: { type: 'constant', value: 2 },
+ right: { type: 'constant', value: 20 }
+ }
+ })
+ })
+
describe('parsing parentheses', () => {
test('(1d6)d6', () => {
expect(parse('(1d6)d6')).toEqual({
diff --git a/index.js b/index.js
index 3b858a2..4a58e4a 100644
--- a/index.js
+++ b/index.js
@@ -9,6 +9,8 @@ const interpret = tree => {
return D.d(interpret(tree.left), interpret(tree.right))
case 'E':
return D.explode(interpret(tree.left), interpret(tree.right))
+ case 'K':
+ return D.keepHigh(interpret(tree.left), interpret(tree.right))
case 'add':
return D.add(interpret(tree.left), interpret(tree.right))
case 'subtract':
diff --git a/src/lexer.js b/src/lexer.js
index 85579fb..fd0d0a3 100644
--- a/src/lexer.js
+++ b/src/lexer.js
@@ -25,6 +25,7 @@ newLexemeType('-', '-')
newLexemeType('(', '\\(')
newLexemeType(')', '\\)')
newLexemeType('E', 'E')
+newLexemeType('K', 'K')
newSkippableLexeme('whitespace', '\\s+')
const lex = (expressionString) => {
diff --git a/src/parser.js b/src/parser.js
index 9479abc..5e9960a 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -6,6 +6,8 @@ let throwSyntaxError = () => {
throw new Error('Syntax error: unexpected token')
}
+const dieBindingPower = 30
+
let newSymbol = (type, nud, lbp, led) => {
symbols[type] = {
type,
@@ -33,6 +35,16 @@ newSymbol('(', function(parser) {
newSymbol(')')
+const newDieOperation = (symbol, nud = null) => {
+ newSymbol(symbol, nud, dieBindingPower, (left, parser) => {
+ return {
+ type: symbol,
+ left: left,
+ right: parser.expression(dieBindingPower - 1)
+ }
+ })
+}
+
newSymbol('d', (parser) => {
return {
type: 'd',
@@ -55,6 +67,8 @@ newSymbol('E', null, 30, (left, parser) => {
}
})
+newDieOperation('K')
+
newSymbol('+', null, 20, (left, parser) => {
return {
type: 'add',