Skip to content

refactor!: between #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions src/between-literals.test.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/between-literals.ts

This file was deleted.

41 changes: 37 additions & 4 deletions src/between.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,41 @@ import { test, expect } from '@jest/globals'
import * as P from './index.js'

test('between', () => {
const number = P.map(P.whileChars('0123456789'), parseFloat)
const between = P.between('(', ')', number)
const p = P.parser(P.trim()(between))
expect(p(' (123)\n')).toEqual(123)
const p = P.between('<!--', '-->')
expect(p(P.Reader.of('<!--abc-->'))).toEqual(
P.Result.ok(P.Reader.of('<!--abc-->', 10), 'abc')
)
})

test('between double quoted', () => {
const p = P.between('"')
expect(p(P.Reader.of('"abc"'))).toEqual(
P.Result.ok(P.Reader.of('"abc"', 5), 'abc')
)
})

test('between html attribute like', () => {

const id =
P.re(/\w+/)

const str =
P.either(
P.between('\''),
P.between('"')
)

const attr =
P.map(P.seq(id, '=', str), _ => [ _[0], _[2] ] as const)

const attrs =
P.map(P.sep1(P.ws1, attr), entries => Object.fromEntries(entries))

const parser =
P.parser(attrs)

expect(parser('foo="1" bar=\'2\'')).toEqual({
foo: '1',
bar: '2'
})
})
24 changes: 14 additions & 10 deletions src/between.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import map from './map.js'
import seq from './seq.js'
import type { Parser, Liftable } from './parser.js'
import * as Reader from './reader.js'
import * as Result from './result.js'

/** @returns `a` parser sorrounded by `start` and `end`. */
export function between<A>(
start: Liftable,
end: Liftable,
parser: Parser<A>
): Parser<A> {
return map(seq(start, parser, end), _ => _[1])
/** @returns parser matching string between `start` and `end` literals. */
export function between(start: string, end = start) {
return function (reader: Reader.t) {
if (!Reader.startsWith(reader, start)) {
return Result.fail(reader, `expected start literal ${start}`)
}
const offset = Reader.offsetOf(reader, end, start.length)
if (offset === -1) {
return Result.fail(reader, `expected end literal ${end}`)
}
return Result.ok(reader, Reader.slice(reader, start.length, offset), offset + end.length)
}
}

export default between
10 changes: 0 additions & 10 deletions src/between1.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ export * as Rfc8259 from './rfc8259.js'
export * from './all.js'
export * from './any.js'
export * from './beg.js'
export * from './between-literals.js'
export * from './between.js'
export * from './between1.js'
export * from './bol.js'
export * from './char-range.js'
export * from './chars.js'
Expand Down
2 changes: 1 addition & 1 deletion src/lazy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('mutually recursive', () => {
P.lazy(() => P.map(P.seq(expr, '*', expr), _ => _[0] * _[2]))

const grouped =
P.lazy(() => P.between('(', ')', expr))
P.lazy(() => P.map(P.seq('(', expr, ')'), _ => _[1]))

const expr: P.t<number> =
P.lazy(() => P.longestReentrant(
Expand Down
6 changes: 3 additions & 3 deletions src/regexp.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test, expect } from '@jest/globals'
import * as P from './index.js'
import * as R from '@prelude/refute'
import * as $ from '@prelude/refute'

test('comment', () => {
const comment = P.re(/<!--(.*?)-->/, 1)
Expand All @@ -27,9 +27,9 @@ test('convoluted date', () => {
const digit0: P.t<number> =
P.map(P.re(/\d/), _ => parseInt(_, 10))
const dd2: P.t<number> =
P.refute(P.map(P.seq(digit0, digit0), ([ a, b ]) => (a * 10) + b), R.between(1, 31))
P.refute(P.map(P.seq(digit0, digit0), ([ a, b ]) => (a * 10) + b), $.between(1, 31))
const mm: P.t<number> =
P.refute(P.map(P.seq(digit0, digit0), ([ a, b ]) => (a * 10) + b - 1), R.between(0, 11))
P.refute(P.map(P.seq(digit0, digit0), ([ a, b ]) => (a * 10) + b - 1), $.between(0, 11))
function chars2(chars_: string, min = 1, max = Infinity): P.t<string> {
return function (reader) {
let i = 0
Expand Down
4 changes: 1 addition & 3 deletions src/rfc4180.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { test, expect } from '@jest/globals'
import * as Rfc4180 from './rfc4180.js'

test('basic', () => {
expect(Rfc4180.parse(`foo,bar,baz
1,2,"three"
`)).toEqual([
expect(Rfc4180.parse('foo,bar,baz\n1,2,"three"\n')).toEqual([
[ 'foo', 'bar', 'baz' ],
[ '1', '2', 'three' ],
[ '' ]
Expand Down
9 changes: 9 additions & 0 deletions src/rfc4180/escaped.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { test, expect } from '@jest/globals'
import escaped from './escaped.js'
import { parse } from '../parser.js'

test('escaped', () => {
expect(parse(escaped, '"foo"')).toEqual('foo')
expect(parse(escaped, '""')).toEqual('')
expect(parse(escaped, '"foo""bar"')).toEqual('foo"bar')
})
13 changes: 2 additions & 11 deletions src/rfc4180/escaped.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import comma from './comma.js'
import cr from './cr.js'
import dquote from './dquote.js'
import dquote2 from './dquote2.js'
import join from '../join.js'
import lf from './lf.js'
import re from '../regexp.js'
import map from '../map.js'
import between1 from '../between1.js'
import star from '../star.js'
import textdata from './textdata.js'
import first from '../first.js'

export const escaped =
between1(dquote, join(star(first(textdata, comma, cr, lf, map(dquote2, () => '"')))))
map(re(/^"((?:[^"]|"")*)"/, 1), _ => _.replaceAll('""', '"'))

export default escaped
5 changes: 3 additions & 2 deletions src/rfc8259/array.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import sep0 from '../sep0.js'
import between from '../between.js'
import trim from '../trim.js'
import type * as Parser from '../parser.js'
import valueSeparator from './value-separator.js'
import seq from '../seq.js'
import map from '../map.js'

export const beginArray =
trim()('[')
Expand All @@ -12,6 +13,6 @@ export const endArray =

export const array =
<T>(parser: Parser.t<T>): Parser.t<T[]> =>
between(beginArray, endArray, sep0(valueSeparator, parser))
map(seq(beginArray, sep0(valueSeparator, parser), endArray), _ => _[1])

export default array
3 changes: 1 addition & 2 deletions src/rfc8259/object.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import between from '../between.js'
import string_ from './string.js'
import trim from '../trim.js'
import type * as Parser from '../parser.js'
Expand All @@ -22,6 +21,6 @@ export const member =

export const object =
<T>(value: Parser.t<T>): Parser.t<Record<string, undefined | T>> =>
map(between(beginObject, endObject, sep0(valueSeparator, member(value))), _ => Object.fromEntries(_))
map(seq(beginObject, sep0(valueSeparator, member(value)), endObject), _ => Object.fromEntries(_[1]))

export default object
3 changes: 1 addition & 2 deletions src/rfc8259/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import lit from '../lit.js'
import map from '../map.js'
import right from '../right.js'
import seq from '../seq.js'
import between from '../between.js'
import star from '../star.js'
import times from '../times.js'
import chars from '../chars.js'
Expand All @@ -32,6 +31,6 @@ export const quotationMark =
lit('"')

export const string =
join(between(quotationMark, quotationMark, star(char)))
join(map(seq(quotationMark, star(char), quotationMark), _ => _[1]))

export default string
2 changes: 1 addition & 1 deletion src/sep.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import * as P from './index.js'

test('sep', () => {
const number = P.map(P.whileChars('0123456789'), parseFloat)
const p = P.parser(P.between('(', ')', P.sep0(P.ws1, number)))
const p = P.parser(P.map(P.seq('(', P.sep0(P.ws1, number), ')'), _ => _[1]))
expect(p('(1 23 456)')).toEqual([ 1, 23, 456 ])
})
5 changes: 3 additions & 2 deletions src/sexp.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as P from './parser.js'
import between from './between.js'
import charRange from './char-range.js'
import either from './either.js'
import join from './join.js'
import jsonString from './rfc8259/string.js'
import map from './map.js'
import sep0 from './sep0.js'
import seq from './seq.js'
import star from './star.js'
import trim from './trim.js'
import type * as Reader from './reader.js'
Expand All @@ -30,7 +31,7 @@ export const string: P.t<string> =
either(unquoted, jsonString)

export function sexp(reader: Reader.t): Result.t<Sexp> {
return between(lparen, rparen, sep0(ws1, either(string, sexp)))(reader)
return map(seq(lparen, sep0(ws1, either(string, sexp)), rparen), _ => _[1])(reader)
}

export const parser =
Expand Down
8 changes: 4 additions & 4 deletions src/switch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import * as P from './index.js'

test('switch', () => {
const id = P.whileNotChars(' /<>', 1)
const comment = P.map(P.betweenLiterals('<!--', '-->'), value => ({ type: 'comment' as const, value }))
const comment = P.map(P.between('<!--', '-->'), value => ({ type: 'comment' as const, value }))
const element = P.map(P.seq('<', id, '/>'), ([ , name ]) => ({ type: 'element' as const, name }))
const pi = P.map(P.betweenLiterals('<?', '?>'), value => ({ type: 'pi' as const, value }))
const decl = P.map(P.betweenLiterals('<!', '>'), value => ({ type: 'decl' as const, value }))
const cdata = P.map(P.betweenLiterals('<![CDATA[', ']]>'), value => ({ type: 'cdata' as const, value }))
const pi = P.map(P.between('<?', '?>'), value => ({ type: 'pi' as const, value }))
const decl = P.map(P.between('<!', '>'), value => ({ type: 'decl' as const, value }))
const cdata = P.map(P.between('<![CDATA[', ']]>'), value => ({ type: 'cdata' as const, value }))
const text = P.map(P.whileNotChars('<', 1), value => ({ type: 'text' as const, value }))
const misc = P.switch({
'<': element,
Expand Down
Loading