48 lines
1 KiB
JavaScript
48 lines
1 KiB
JavaScript
import { ok } from 'kojima'
|
|
import { curry, } from 'izuna'
|
|
import { clone } from './fn.js'
|
|
import { verify } from './cond.js'
|
|
import { anyChar } from './byte.js'
|
|
|
|
/** @import { ParseError, ParserState } from './state.js' */
|
|
/** @import { Result } from '../vendor/kojima/src/index.js' */
|
|
|
|
export const takeWhile = curry((predicate, state) => {
|
|
let result = ok(state)
|
|
|
|
while (result.isOk()) {
|
|
result = verify(anyChar, predicate, state)
|
|
}
|
|
|
|
return result
|
|
})
|
|
|
|
export const takeUntil = curry((parser, state) => not(takeWhile(parser, state)))
|
|
|
|
export const skip = curry((parser, state) => {
|
|
const tokens = state[0]
|
|
const result = parser(state)
|
|
if (result.isOk()) {
|
|
return result.map(other => [tokens, other[1]])
|
|
} else {
|
|
return result
|
|
}
|
|
})
|
|
|
|
export const many = curry((parser, state) => {
|
|
let result = ok(state)
|
|
|
|
while (true) {
|
|
const res = parser(clone(state))
|
|
if (res.isOk()) {
|
|
result = res
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return result
|
|
})
|
|
|
|
export const many1 = parser => seq(parser, many(parser))
|
|
|