aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-08 21:12:20 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-08 21:12:20 +0530
commite246f2341ee13926f4273c6d634cef4fe07f040e (patch)
tree2dfcbdb24004b85c1a6ab2ed11c211621489c9a3 /src/parser
parent61bb1f0c8b109c66d48e678a4d2cf7cb29cf7efb (diff)
downloadelxr-e246f2341ee13926f4273c6d634cef4fe07f040e.tar.gz
elxr-e246f2341ee13926f4273c6d634cef4fe07f040e.zip
feat(parse): implements object property matching parser
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/index.ts51
-rw-r--r--src/parser/utils.ts6
2 files changed, 41 insertions, 16 deletions
diff --git a/src/parser/index.ts b/src/parser/index.ts
index 4ad3e7b..2f5781e 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -1,30 +1,36 @@
-import { pipe } from 'fp-ts/function'
-import { chain, orElse, right } from 'fp-ts/lib/Either'
+import { flow, pipe } from 'fp-ts/function'
+import { chain, left, orElse, right } from 'fp-ts/lib/Either'
import {
delimited,
+ many0,
many1,
mapTo,
+ oneOf,
optional,
or,
+ pair,
Parser,
ParserResult,
prefixed,
+ satifyChar,
+ suffixed,
symbol,
tuple3,
+ whitespaces0,
} from './utils'
import { Expr, ListExpr } from '../types'
-export const start = mapTo(symbol('^'), _ => Expr.Start(null))
-export const end = mapTo(symbol('$'), _ => Expr.End(null))
-export const anyItem = mapTo(symbol('.'), _ => Expr.AnyItem(null))
-export const nextItem = mapTo(symbol(','), _ => Expr.NextItem(null))
-export const anyString = mapTo(symbol('\\s'), _ => Expr.AnyString(null))
-export const anyNumber = mapTo(symbol('\\n'), _ => Expr.AnyNumber(null))
-export const anyBool = mapTo(symbol('\\b'), _ => Expr.AnyBool(null))
-export const truthy = mapTo(symbol('\\T'), _ => Expr.Truthy(null))
-export const falsey = mapTo(symbol('\\F'), _ => Expr.Falsey(null))
+const start = mapTo(symbol('^'), _ => Expr.Start(null))
+const end = mapTo(symbol('$'), _ => Expr.End(null))
+const anyItem = mapTo(symbol('.'), _ => Expr.AnyItem(null))
+const nextItem = mapTo(symbol(','), _ => Expr.NextItem(null))
+const anyString = mapTo(symbol('\\s'), _ => Expr.AnyString(null))
+const anyNumber = mapTo(symbol('\\n'), _ => Expr.AnyNumber(null))
+const anyBool = mapTo(symbol('\\b'), _ => Expr.AnyBool(null))
+const truthy = mapTo(symbol('\\T'), _ => Expr.Truthy(null))
+const falsey = mapTo(symbol('\\F'), _ => Expr.Falsey(null))
-export const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
+const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
chain(([expr, input]) =>
pipe(
input,
@@ -37,7 +43,7 @@ export const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
),
)
-export const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
+const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
([expr, input]) =>
pipe(
input,
@@ -48,13 +54,30 @@ export const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
),
)
-export const expressionP: Parser<Expr> = (input: string) =>
+const propRegex = /^[A-Za-z0-9_-]$/
+
+export const propertyName: Parser<string> = pipe(
+ satifyChar(c => propRegex.test(c)),
+ many1,
+ p => mapTo(p, xs => xs.join('')),
+ p => suffixed(p, whitespaces0),
+)
+
+const objectProperty = (input: string) => pipe(
+ input,
+ mapTo(delimited(symbol('['), pair(propertyName, many0(expressionP)), symbol(']')), ([name, exprs]) =>
+ Expr.PropertyMatch({ name, exprs }),
+ ),
+)
+
+const expressionP: Parser<Expr> = (input: string) =>
pipe(
input,
or([
mapTo(delimited(symbol('('), many1(expressionP), symbol(')')), exprs =>
Expr.Group({ exprs }),
),
+ objectProperty,
nextItem,
anyItem,
anyString,
diff --git a/src/parser/utils.ts b/src/parser/utils.ts
index debff22..9e05286 100644
--- a/src/parser/utils.ts
+++ b/src/parser/utils.ts
@@ -40,14 +40,14 @@ export const many0 = <T>(parser: Parser<T>): Parser<Array<T>> =>
)
export const many1 = <T>(parser: Parser<T>): Parser<Array<T>> =>
- flow(
+ recoverInput(flow(
many0(parser),
chain(([res, inp]) =>
res.length > 0
? right([res, inp])
: left([`many1 failed to parse at ${inp}`, inp]),
),
- )
+ ))
const recoverInput =
<T>(p: Parser<T>): Parser<T> =>
@@ -123,6 +123,8 @@ export const matchString =
? right([s, input.slice(s.length)])
: left([`Expected ${s} but got ${input.slice(0, 1)}`, input])
+export const oneOf = (xs: string[]): Parser<string> => or(xs.map(matchString))
+
export const symbol = (s: string): Parser<string> =>
delimited(whitespaces0, matchString(s), whitespaces0)