import { pure, fail, anyItem, satisfy, literal, parse, parseSome, ParseError, EofError } from '../src/parser.js' import { Err, Result } from '../src/result.js' import { describe, it } from 'node:test' import assert from 'node:assert/strict' const eq = (a, b) => assert.deepStrictEqual(a, b) const parseErr = (i, desc) => new Err(new ParseError(i, desc)) const eof = (i = 0) => new Err(new EofError(i)) const streamState = stream => { return [stream.index, Array.from(stream.clone())] } describe('Primitive parsers', () => { it('pure', () => { const result = parseSome(pure(123), 'abc') const [value, stream] = result.unwrap() eq(value, 123) eq(streamState(stream), [0, ['a', 'b', 'c']]) const empty = parse(pure(123), []) eq(empty, Result.ok(123)) }) it('fail', () => { const msg = 'Expected failure' const parser = fail(msg) const expected = parseErr(0, msg) eq(parse(parser, 'abc'), expected) eq(parse(parser, ''), expected) }) it('anyItem', () => { const parser = anyItem() eq(parse(parser, 'a'), Result.ok('a')) const many = parseSome(parser, 'abc') assert(many.isOk()) const [value, rest] = many.unwrap() eq(value, 'a') eq(streamState(rest), [1, ['b', 'c']]) eq(parse(parser, ''), eof()) }) it('satisfy', () => { const pa = satisfy(x => x === 'a') const result = parseSome(pa, 'abc') assert(result.isOk()) const [value, rest] = result.unwrap() eq(value, 'a') eq(streamState(rest), [1, ['b', 'c']]) const err = parse(pa, 'cba') eq(err, parseErr(0, 'Value did not match predicate: c')) const eofErr = parse(pa, '') eq(eofErr, eof()) }) it('literal', () => { const px = literal('x') const result = parseSome(px, 'xyz') assert(result.isOk()) const [value, rest] = result.unwrap() eq(value, 'x') eq(streamState(rest), [1, ['y', 'z']]) const err = parse(px, 'yz') eq(err, parseErr(0, 'Value did not match predicate: y')) const eofErr = parse(px, '') eq(eofErr, eof()) }) })