From 38e82ade6fd207af21f2df6a3e98298338e85eb8 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Wed, 12 Jul 2017 22:54:33 -0400 Subject: Lex basic dice --- __tests__/lexer.test.js | 29 +++++++++++++++++++++++++++++ src/lexer.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 __tests__/lexer.test.js create mode 100644 src/lexer.js diff --git a/__tests__/lexer.test.js b/__tests__/lexer.test.js new file mode 100644 index 0000000..20d461f --- /dev/null +++ b/__tests__/lexer.test.js @@ -0,0 +1,29 @@ +const { lex } = require('../src/lexer.js') + +describe('lex', () => { + it('lexes the empty string', () => { + expect(lex('')).toEqual([]) + }) + + it('signals an error on unexpected input', () => { + expect(lex('q')).toBe('error') + }) + + describe('basic dice', () => { + it('1d6', () => { + expect(lex('1d6')).toEqual([ + { type: 'number', value: 1 }, + { type: 'd' }, + { type: 'number', value: 6 } + ]) + }) + + it('42d172', () => { + expect(lex('42d172')).toEqual([ + { type: 'number', value: 42 }, + { type: 'd' }, + { type: 'number', value: 172 } + ]) + }) + }) +}) diff --git a/src/lexer.js b/src/lexer.js new file mode 100644 index 0000000..ff7b0d4 --- /dev/null +++ b/src/lexer.js @@ -0,0 +1,44 @@ +const lexemeTypes = [] + +const newLexemeType = (type, regex, adder) => { + lexemeTypes.push({ + type, + regex: new RegExp(`^(${regex})(.*)$`), + adder: adder || (lexemes => { lexemes.push({ type }) }) + }) +} + +const newValueLexeme = (type, regex, converter = v => v) => { + newLexemeType(type, regex, (lexemes, value) => { + lexemes.push({ type, value: converter(value) }) + }) +} + +newValueLexeme('number', '\\d+', Number) +newLexemeType('d', 'd') + +const lex = (expressionString) => { + let lexemes = [] + + while (expressionString.length > 0) { + let matched = false + + lexemeTypes.forEach(lexemeType => { + let matches = lexemeType.regex.exec(expressionString) + + if (matches) { + matched = true + lexemeType.adder(lexemes, matches[1]) + expressionString = matches[2] + } + }) + + if (!matched) { + return 'error' + } + } + + return lexemes +} + +exports.lex = lex -- cgit v1.2.3