aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-07 14:26:00 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-07 14:26:00 +0530
commitad8983655dc35b5401e810a9d4b61e933d35b783 (patch)
tree62f494ff001d3ed55cb1eb55118e4e9d8cd2ae8d
parent20480cd42bbbe1685b9470063248ed5fc1f2506b (diff)
downloadelxr-ad8983655dc35b5401e810a9d4b61e933d35b783.tar.gz
elxr-ad8983655dc35b5401e810a9d4b61e933d35b783.zip
feat: basic parsing for expressions
Diffstat (limited to '')
-rw-r--r--src/index.ts49
-rw-r--r--src/parser.ts21
-rw-r--r--tests/basic.spec.ts16
3 files changed, 67 insertions, 19 deletions
diff --git a/src/index.ts b/src/index.ts
index 95a5411..75bc1af 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,19 +6,36 @@ import {
integer,
many1,
mapTo,
+ matchChar,
optional,
or,
pair,
+ Parser,
symbol,
+ tuple3,
} from './parser'
export const start = mapTo(symbol('^'), constant({ tag: 'Start' } as Expr))
export const end = mapTo(symbol('$'), constant({ tag: 'End' } as Expr))
-export const anyItem = mapTo(symbol(','), constant({ tag: 'AnyItem' } as Expr))
+export const anyItem = mapTo(symbol('.'), constant({ tag: 'AnyItem' } as Expr))
export const nextItem = mapTo(
symbol(','),
constant({ tag: 'NextItem' } as Expr)
)
+export const anyString = mapTo(
+ symbol('\\s'),
+ constant({ tag: 'AnyString' } as Expr)
+)
+export const anyNumber = mapTo(
+ symbol('\\n'),
+ constant({ tag: 'AnyNumber' } as Expr)
+)
+export const anyBool = mapTo(
+ symbol('\\b'),
+ constant({ tag: 'AnyBool' } as Expr)
+)
+export const truthy = mapTo(symbol('\\T'), constant({ tag: 'Truthy' } as Expr))
+export const falsey = mapTo(symbol('\\F'), constant({ tag: 'Falsey' } as Expr))
// export const optional = mapTo(symbol('?'), constant({ tag: 'Optional' } as Expr))
// export const zeroOrMore = mapTo(symbol('*'), constant({ tag: 'ZeroOrMore' } as Expr))
// export const oneOrMore = mapTo(symbol('+'), constant({ tag: 'OneOrMore' } as Expr))
@@ -32,18 +49,32 @@ type Expr =
| { tag: 'NextItem' }
| { tag: 'AnyItem' }
| { tag: 'Or' }
- | { tag: 'String' }
- | { tag: 'Number' }
- | { tag: 'Bool' }
+ | { tag: 'AnyString' }
+ | { tag: 'AnyNumber' }
+ | { tag: 'AnyBool' }
| { tag: 'Truthy' }
| { tag: 'Falsey' }
+ | { tag: 'Group'; exprs: Expr[] }
-export const expressionP = or([
- symbol('fuck'),
- mapTo(many1(digit), (j) => j.join('')),
-])
+export const expressionP: Parser<Expr> = (input: string) =>
+ pipe(
+ input,
+ or([
+ mapTo(
+ delimited(symbol('('), many1(expressionP), symbol(')')),
+ (exprs) => ({ tag: 'Group', exprs })
+ ),
+ nextItem,
+ anyItem,
+ anyString,
+ anyNumber,
+ anyBool,
+ truthy,
+ falsey,
+ ])
+ )
-export const parser = pair(pair(optional(start), expressionP), optional(end))
+export const parser = tuple3(optional(start), many1(expressionP), optional(end))
/*
diff --git a/src/parser.ts b/src/parser.ts
index 9baab8e..baa3e76 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -90,15 +90,12 @@ export const tab = matchChar('\t')
export const whitespace = or([space, newline, tab])
export const whitespaces0 = many0(whitespace)
-export const matchString = (s: string): Parser<string> =>
- s === ''
- ? constP('')
- : flow(
- matchChar(s.charAt(0)),
- chain(([c, inp]) =>
- pipe(inp, matchString(s.slice(1)), map(mapFst((s) => c + s)))
- )
- )
+export const matchString =
+ (s: string): Parser<string> =>
+ (input: string) =>
+ input.slice(0, s.length) === s
+ ? right([s, input.slice(s.length)])
+ : left([`Expected ${s} but got ${input.slice(0, 1)}`, input])
export const symbol = (s: string): Parser<string> =>
delimited(whitespaces0, matchString(s), whitespaces0)
@@ -131,3 +128,9 @@ export const pair = <A, B>(a: Parser<A>, b: Parser<B>): Parser<[A, B]> =>
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])
diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts
index 962f076..b0a4d50 100644
--- a/tests/basic.spec.ts
+++ b/tests/basic.spec.ts
@@ -12,6 +12,7 @@ import {
optional,
} from '../src/parser'
import { parser } from '../src'
+import {some} from 'fp-ts/lib/Option'
describe('Foobar', () => {
it('should do shit', () => {
@@ -30,6 +31,19 @@ describe('Foobar', () => {
})
it('should maybeshut', () => {
- console.log(JSON.stringify(parser('fuck'), null, 2))
+ expect(parser(/^ .\s(\n)\b \T $/.source)).toEqual(right([
+ [
+ some({ tag: 'Start' }),
+ [
+ { tag: 'AnyItem' },
+ { tag: 'AnyString' },
+ { tag: 'Group', exprs: [{ tag: 'AnyNumber' },] },
+ { tag: 'AnyBool' },
+ { tag: 'Truthy' },
+ ],
+ some({ tag: 'End' }),
+ ],
+ ''
+ ]))
})
})