summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-14 21:15:29 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-14 21:15:29 +0530
commit950faa740b86af5f264717898f24ae8fb65c036d (patch)
tree86b3e226f8efa9b0004b31a0edf9b852716a59db /src
parent3b0e7428441f85de5e76a59abbb09931bcf2387b (diff)
downloadelxr-950faa740b86af5f264717898f24ae8fb65c036d.tar.gz
elxr-950faa740b86af5f264717898f24ae8fb65c036d.zip
feat: implements string literal parser
Diffstat (limited to 'src')
-rw-r--r--src/parser/index.ts22
-rw-r--r--src/parser/utils.ts17
2 files changed, 29 insertions, 10 deletions
diff --git a/src/parser/index.ts b/src/parser/index.ts
index a2276bb..2db91a4 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -5,15 +5,18 @@ import {
digits,
many0,
many1,
+ manyTill,
mapTo,
matchChar,
+ matchString,
oneOf,
optional,
or,
pair,
Parser,
ParserResult,
- satifyChar,
+ prefixed,
+ satisfyChar,
sepBy1,
suffixed,
symbol,
@@ -49,7 +52,7 @@ const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
const propRegex = /^[A-Za-z0-9_-]$/
export const propertyName: Parser<string> = pipe(
- satifyChar(c => propRegex.test(c)),
+ satisfyChar(c => propRegex.test(c)),
many1,
p => mapTo(p, xs => xs.join('')),
p => suffixed(p, whitespaces0),
@@ -94,9 +97,22 @@ const booleanLiteral: Parser<Literal> = mapTo(oneOf(['true', 'false']), b =>
Literal.Boolean(b === 'true' ? true : false),
)
+const stringDelimiter = matchChar('"')
+
+const stringLiteral: Parser<Literal> = mapTo(
+ prefixed(
+ stringDelimiter,
+ manyTill(
+ satisfyChar(_ => true),
+ stringDelimiter,
+ ),
+ ),
+ s => Literal.String(s.join('')),
+)
+
const literalP: Parser<Literal> = delimited(
whitespaces0,
- or([booleanLiteral, numberLiteral]),
+ or([booleanLiteral, numberLiteral, stringLiteral]),
whitespaces0,
)
diff --git a/src/parser/utils.ts b/src/parser/utils.ts
index 4e2c9d6..564d97c 100644
--- a/src/parser/utils.ts
+++ b/src/parser/utils.ts
@@ -29,18 +29,20 @@ export const sepBy1 = <T>(sep: Parser<any>, parser: Parser<T>): Parser<T[]> =>
),
)
-export const not = (parser: Parser<any>): Parser<null> => (input: string) =>
+export const not = (parser: Parser<any>): Parser<never> => (input: string) =>
pipe(
input,
parser,
Either.fold(
- ([_left, inp]) => Either.right([null, inp]),
+ ([_left, inp]) => Either.right([null as never, inp]),
([_right, inp]) => Either.left(['`not` parser failed. Match found', inp])
),
)
-export const manyTill = <T>(parser: Parser<T>, end: Parser<any>): Parser<T[]> =>
- mapTo(pair(many0(suffixed(parser, not(end))), parser), ([xs, l]) => xs.concat([l]))
+export const manyTill = <T>(parser: Parser<T>, end: Parser<any>): Parser<T[]> => {
+ const p = pair(many0(suffixed(parser, not(end))), suffixed(parser, end))
+ return mapTo(p, ([xs, l]) => xs.concat([l]))
+}
export const many0 = <T>(parser: Parser<T>): Parser<Array<T>> =>
flow(
@@ -94,15 +96,16 @@ export const delimited = <T>(
s: Parser<any>,
): Parser<T> => suffixed(prefixed(p, a), s)
-export const satifyChar =
+export const satisfyChar =
(f: (c: char) => boolean): Parser<char> =>
(input: string) => {
+ if (input.length === 0) return Either.left(['Unexpected end of input', input])
const c = input.charAt(0)
if (f(c)) return Either.right([c, input.slice(1)])
return Either.left([`Expected to satisfy ${f}, got "${c}"`, input])
}
-export const digit = satifyChar(c => /^[0-9]$/g.test(c))
+export const digit = satisfyChar(c => /^[0-9]$/g.test(c))
export const digits: Parser<string> = flow(
many1(digit),
@@ -121,7 +124,7 @@ export const or = <T>(parsers: Parser<T>[]): Parser<T> => {
: (inp: string) => Either.left(['unable to match', inp])
}
-export const matchChar = (ch: char): Parser<char> => satifyChar(eq(ch))
+export const matchChar = (ch: char): Parser<char> => satisfyChar(eq(ch))
export const matchString =
(s: string): Parser<string> =>