kuebiko/tests/primitives.test.js
2025-07-02 11:13:04 -04:00

82 lines
2 KiB
JavaScript

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())
})
})