diff options
| author | Akshay Nair <phenax5@gmail.com> | 2022-01-07 14:26:00 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2022-01-07 14:26:00 +0530 |
| commit | ad8983655dc35b5401e810a9d4b61e933d35b783 (patch) | |
| tree | 62f494ff001d3ed55cb1eb55118e4e9d8cd2ae8d /src | |
| parent | 20480cd42bbbe1685b9470063248ed5fc1f2506b (diff) | |
| download | elxr-ad8983655dc35b5401e810a9d4b61e933d35b783.tar.gz elxr-ad8983655dc35b5401e810a9d4b61e933d35b783.zip | |
feat: basic parsing for expressions
Diffstat (limited to '')
| -rw-r--r-- | src/index.ts | 49 | ||||
| -rw-r--r-- | src/parser.ts | 21 |
2 files changed, 52 insertions, 18 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]) |
