diff --git a/src/internal/parsers/letter.ts b/src/internal/parsers/letter.ts new file mode 100644 index 0000000..0587bba --- /dev/null +++ b/src/internal/parsers/letter.ts @@ -0,0 +1,14 @@ +import { Parser } from '../state' + +import { regexp } from './regexp' + +const LETTER_RE = /\p{Letter}/gu +const LETTERS_RE = /\p{Letter}+/gu + +export function letter(): Parser { + return regexp(LETTER_RE, 'letter') +} + +export function letters(): Parser { + return regexp(LETTERS_RE, 'letters') +} diff --git a/src/parsers.ts b/src/parsers.ts index d813e3b..1f3d9ee 100644 --- a/src/parsers.ts +++ b/src/parsers.ts @@ -3,6 +3,7 @@ export * from './internal/parsers/eof' export * from './internal/parsers/float' export * from './internal/parsers/integer' export * from './internal/parsers/lazy' +export * from './internal/parsers/letter' export * from './internal/parsers/nothing' export * from './internal/parsers/regexp' export * from './internal/parsers/rest' diff --git a/tests/internal/parsers/letter.spec.ts b/tests/internal/parsers/letter.spec.ts new file mode 100644 index 0000000..cdfc519 --- /dev/null +++ b/tests/internal/parsers/letter.spec.ts @@ -0,0 +1,65 @@ +import { letter, letters } from '@lib/internal/parsers/letter' + +import { run, result, should } from '@tests/@helpers' + +describe(letter, () => { + it('should succeed with an ASCII letter', () => { + const actual = run(letter(), 'A') + const expected = result('success', 'A') + + should.matchState(actual, expected) + }) + + it('should succeed with a Unicode letter', () => { + const actual = run(letter(), 'Â') + const expected = result('success', 'Â') + + should.matchState(actual, expected) + }) + + it('should fail if given something other than a letter', () => { + ;['1', '+', '~', '`', ':', `'`].forEach((tcase) => { + const actual = run(letter(), tcase) + const expected = result('failure', 'letter') + + should.matchState(actual, expected) + }) + }) +}) + +describe(letters, () => { + it('should succeed with an ASCII letter if given input with a single ASCII letter', () => { + const actual = run(letters(), 'A') + const expected = result('success', 'A') + + should.matchState(actual, expected) + }) + + it('should succeed with a Unicode letter if given input with a single Unicode letter', () => { + const actual = run(letters(), 'Â') + const expected = result('success', 'Â') + + should.matchState(actual, expected) + }) + + it('should succeed with letters if given input with letters', () => { + const actual = run(letters(), 'Âne') + const expected = result('success', 'Âne') + + should.matchState(actual, expected) + }) + + it('should succeed with letters if given input with letters and other symbols', () => { + const actual = run(letters(), 'Âne+9000') + const expected = result('success', 'Âne') + + should.matchState(actual, expected) + }) + + it('should fail if given something other than letters', () => { + const actual = run(letters(), '9000+Âne') + const expected = result('failure', 'letters') + + should.matchState(actual, expected) + }) +}) diff --git a/tests/parsers.spec.ts b/tests/parsers.spec.ts index c408ed4..57a362c 100644 --- a/tests/parsers.spec.ts +++ b/tests/parsers.spec.ts @@ -11,6 +11,8 @@ it('should expose parsers', () => { 'integer', 'int', 'lazy', + 'letter', + 'letters', 'nothing', 'nil', 'regexp',