aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-08 18:14:59 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-08 18:16:48 +0530
commite8322ca988fc20baf7892915e6ccb069b11c608e (patch)
treeeaef108f21389268d42218eacde2256884a62f64
parente1092bfca260412ab716710d31c24c86d3a818e1 (diff)
downloadelxr-e8322ca988fc20baf7892915e6ccb069b11c608e.tar.gz
elxr-e8322ca988fc20baf7892915e6ccb069b11c608e.zip
feat(parser): implements or syntax
-rw-r--r--src/parser/index.ts14
-rw-r--r--src/parser/utils.ts13
-rw-r--r--src/types.ts20
-rw-r--r--tests/basic.spec.ts34
4 files changed, 60 insertions, 21 deletions
diff --git a/src/parser/index.ts b/src/parser/index.ts
index ec29099..b8e6764 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -8,6 +8,7 @@ import {
or,
Parser,
ParserResult,
+ prefixed,
symbol,
tuple3,
} from './utils'
@@ -36,6 +37,17 @@ export const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
),
)
+export const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
+ ([expr, input]) =>
+ pipe(
+ input,
+ mapTo(prefixed(symbol('|'), many1(expressionP)), rest =>
+ Expr.Or({ left: expr, right: rest }),
+ ),
+ orElse(_ => right([expr, input])),
+ ),
+)
+
export const expressionP: Parser<Expr> = (input: string) =>
pipe(
input,
@@ -52,6 +64,7 @@ export const expressionP: Parser<Expr> = (input: string) =>
falsey,
]),
wrapQuantifiers,
+ wrapAlt,
)
export const parser = tuple3(optional(start), many1(expressionP), optional(end))
@@ -62,7 +75,6 @@ export const parser = tuple3(optional(start), many1(expressionP), optional(end))
(> 5) => number greater than
(< 5) => number less than
[name x] => apply x on property `name`
-| => or
/x/ => match regular expression (string values in list)
*/
diff --git a/src/parser/utils.ts b/src/parser/utils.ts
index a06b6c9..debff22 100644
--- a/src/parser/utils.ts
+++ b/src/parser/utils.ts
@@ -78,7 +78,7 @@ export const delimited = <T>(
p: Parser<any>,
a: Parser<T>,
s: Parser<any>,
-): Parser<T> => suffixed(prefixed(p, a), s)
+): Parser<T> => recoverInput(suffixed(prefixed(p, a), s))
export const satifyChar =
(f: (c: char) => boolean): Parser<char> =>
@@ -150,13 +150,16 @@ export const optional = <T>(p: Parser<T>): Parser<Option<T>> =>
)
export const pair = <A, B>(a: Parser<A>, b: Parser<B>): Parser<[A, B]> =>
- pipe(
- a,
- andThen(ra => mapTo(b, rb => [ra, rb])),
+ recoverInput(
+ pipe(
+ a,
+ andThen(ra => mapTo(b, rb => [ra, rb])),
+ ),
)
export const tuple3 = <A, B, C>(
a: Parser<A>,
b: Parser<B>,
c: Parser<C>,
-): Parser<[A, B, C]> => mapTo(pair(pair(a, b), c), ([[a, b], c]) => [a, b, c])
+): Parser<[A, B, C]> =>
+ recoverInput(mapTo(pair(pair(a, b), c), ([[a, b], c]) => [a, b, c]))
diff --git a/src/types.ts b/src/types.ts
index 7863981..7f6546f 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,19 +1,19 @@
import { constructors, Union } from "./utils"
type ExprT = {
- Start: any,
- End: any,
+ Start: null,
+ End: null,
Optional: { expr: Expr },
OneOrMore: { expr: Expr },
ZeroOrMore: { expr: Expr },
- NextItem: any,
- AnyItem: any,
- Or: any,
- AnyString: any,
- AnyNumber: any,
- AnyBool: any,
- Truthy: any,
- Falsey: any,
+ NextItem: null,
+ AnyItem: null,
+ Or: { left: Expr, right: Expr[] },
+ AnyString: null,
+ AnyNumber: null,
+ AnyBool: null,
+ Truthy: null,
+ Falsey: null,
Group: { exprs: Expr[] },
}
diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts
index d443ce1..150966b 100644
--- a/tests/basic.spec.ts
+++ b/tests/basic.spec.ts
@@ -6,9 +6,11 @@ import {
delimited,
} from '../src/parser/utils'
import { parser } from '../src/parser'
-import { some } from 'fp-ts/Option'
+import { none, some } from 'fp-ts/Option'
import { Expr } from '../src/types'
+const plog = (x: any) => console.log(JSON.stringify(x, null, 2))
+
describe('Foobar', () => {
it('should do shit', () => {
expect(integer('12901')).toEqual(right([12901, '']))
@@ -18,10 +20,10 @@ describe('Foobar', () => {
expect(whitespace('a')).toEqual(left(['unable to match', 'a']))
expect(delimited(whitespaces0, integer, whitespaces0)(' 20 ')).toEqual(
- right([20, ''])
+ right([20, '']),
)
expect(delimited(whitespaces0, integer, whitespaces0)(' 2 0 ')).toEqual(
- right([2, '0 '])
+ right([2, '0 ']),
)
})
@@ -40,7 +42,7 @@ describe('Foobar', () => {
some(Expr.End(null)),
],
'',
- ])
+ ]),
)
expect(parser(/^ \s* \T? \n+ $/.source)).toEqual(
@@ -55,7 +57,29 @@ describe('Foobar', () => {
some(Expr.End(null)),
],
'',
- ])
+ ]),
+ )
+
+ expect(parser(/ \s|\b\T|\n /.source)).toEqual(
+ right([
+ [
+ none,
+ [
+ Expr.Or({
+ left: Expr.AnyString(null),
+ right: [
+ Expr.AnyBool(null),
+ Expr.Or({
+ left: Expr.Truthy(null),
+ right: [Expr.AnyNumber(null)],
+ }),
+ ],
+ }),
+ ],
+ none,
+ ],
+ '',
+ ]),
)
})
})