diff options
| author | Akshay Nair <phenax5@gmail.com> | 2022-01-08 21:12:20 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2022-01-08 21:12:20 +0530 |
| commit | e246f2341ee13926f4273c6d634cef4fe07f040e (patch) | |
| tree | 2dfcbdb24004b85c1a6ab2ed11c211621489c9a3 /src/parser | |
| parent | 61bb1f0c8b109c66d48e678a4d2cf7cb29cf7efb (diff) | |
| download | elxr-e246f2341ee13926f4273c6d634cef4fe07f040e.tar.gz elxr-e246f2341ee13926f4273c6d634cef4fe07f040e.zip | |
feat(parse): implements object property matching parser
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/index.ts | 51 | ||||
| -rw-r--r-- | src/parser/utils.ts | 6 |
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) |
