48 lines
1.2 KiB
JavaScript
48 lines
1.2 KiB
JavaScript
import { ParseError } from './state.js'
|
|
import { clone, fail, fork, succeed } from './fn.js'
|
|
import { anyChar } from './char.js'
|
|
import { ok } from '../vendor/kojima/src/index.js'
|
|
import { curry, pipe } from '../vendor/izuna/src/index.js'
|
|
|
|
/** @import { Result } from '../vendor/kojima/src/index.js' */
|
|
/** @import { ParserState } from './state.js' */
|
|
|
|
export const maybe = curry(
|
|
/**
|
|
* @param {(...args: any[]) => Result<ParserState, ParseError>} parser
|
|
* @param {ParserState} state
|
|
*/
|
|
(parser, state) => {
|
|
const result = parser(clone(state))
|
|
return result.isOk() ? result : succeed([], state)
|
|
})
|
|
|
|
export const not = curry((parser, state) => {
|
|
const result = parser(clone(state))
|
|
|
|
if (result.isOk()) {
|
|
return fail(`'not' parser failed for ${parser.name}`, state)
|
|
} else {
|
|
return succeed([], state)
|
|
}
|
|
})
|
|
|
|
export const until = curry((parser, state) => {
|
|
let result = ok(state)
|
|
|
|
while (result.isOk()) {
|
|
console.log(parser.name, state)
|
|
result = result.chain(pipe(clone, parser))
|
|
if (result.isOk()) {
|
|
break
|
|
} else {
|
|
result = anyChar(state)
|
|
}
|
|
}
|
|
|
|
return result
|
|
})
|
|
|
|
export const skip = curry((parser, state) => {
|
|
})
|
|
|