add sequence parsers

This commit is contained in:
Rowan 2025-04-18 05:59:15 -05:00
parent fa822ea3ac
commit 0ae5676c63
6 changed files with 36 additions and 12 deletions

View file

@ -2,6 +2,7 @@ import { chain, curry } from 'izuna'
import { ok } from 'kojima' import { ok } from 'kojima'
import { clone, diff, fail, succeed } from './fn.js' import { clone, diff, fail, succeed } from './fn.js'
import { state as State } from './state.js' import { state as State } from './state.js'
import { skip } from './cond.js'
/** @import { ParserState } from './state.js' */ /** @import { ParserState } from './state.js' */
@ -62,3 +63,9 @@ export const map = curry(
}) })
}) })
export const delimited = curry((first, second, third, state) => seq(skip(first), second, skip(third))(state))
export const preceded = curry((first, second, state) => seq(skip(first), second)(state))
export const terminated = curry((first, second, state) => seq(first, skip(second))(state))
export const separatedPair = curry((first, delimiter, second, state) => seq(first, skip(delimiter), second)(state))

View file

@ -50,5 +50,6 @@ export const verify = curry((parser, predicate, state) => {
}) })
export const skip = curry((parser, state) => { export const skip = curry((parser, state) => {
return chain(_ => succeed([], state), parser(state))
}) })

View file

@ -2,18 +2,7 @@ import { it, assert, assertEq } from 'folktest'
import { char, charNoCase, noneOf, oneOf, parse, tag, tagNoCase, take, takeWhile } from '../../src/index.js' import { char, charNoCase, noneOf, oneOf, parse, tag, tagNoCase, take, takeWhile } from '../../src/index.js'
import { Alphanumeric } from '../../src/const.js' import { Alphanumeric } from '../../src/const.js'
import { chain, curry, map } from 'izuna' import { chain, curry, map } from 'izuna'
import { assertState, parseEq } from './common.js'
const assertState = expected => state => {
assertEq(expected, state[0])
}
const parseEq = curry((parser, input, expected) =>
chain(assertState(expected), parse(parser, input))
)
const parseErr = curry((parser, input) =>
assert(parse(parser, input).isErr(), `expected an error but "${input}" parsed successfully`)
)
export const Byte = [ export const Byte = [
it('char', () => { it('char', () => {

15
tests/units/common.js Normal file
View file

@ -0,0 +1,15 @@
import { chain, curry } from 'izuna'
import { parse } from '../../src/index.js'
export const assertState = curry((expected, state) => {
assertEq(expected, state[0])
})
export const parseEq = curry((parser, input, expected) =>
chain(assertState(expected), parse(parser, input))
)
export const parseErr = curry((parser, input) =>
assert(parse(parser, input).isErr(), `expected an error but '${input}' parsed successfully`)
)

11
tests/units/cond.js Normal file
View file

@ -0,0 +1,11 @@
import { it, assertEq } from 'folktest'
import { anyChar, parse } from '../../src/index.js'
import { skip } from '../../src/cond.js'
import { parseEq } from './common.js'
export const Conditionals = [
it('skip', () => {
parseEq(skip(anyChar), 'test', [])
})
]

View file

@ -1,3 +1,4 @@
export * from './bytes.js' export * from './bytes.js'
export * from './iter.js' export * from './iter.js'
export * from './cond.js'