From 3854a42db888a58f0452bfb23b6e17df5bf8ad39 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Thu, 10 Aug 2023 21:27:42 +0530 Subject: feat: multi expression parser done --- src/parse-expr.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src/parse-expr.ts') diff --git a/src/parse-expr.ts b/src/parse-expr.ts index dbad1a1..ec387d6 100644 --- a/src/parse-expr.ts +++ b/src/parse-expr.ts @@ -5,6 +5,7 @@ export type Expr = Enum<{ Call: { name: string, args: Expr[] } Var: { name: string, defaultValue: Expr } Identifier: string + Chain: { exprs: Expr[] } LiteralString: string }> @@ -12,24 +13,33 @@ export const Expr = constructors() const whitespace = P.regex(/\s*/) const consumeWhitespace = (p: P.Parser): P.Parser => P.between(whitespace, p, whitespace) +const comma = consumeWhitespace(P.string(',')) +const parens = (p: P.Parser): P.Parser => P.between(P.string('('), p, P.string(')')) +const identifierParser = P.regex(/^[a-z][a-z0-9_-]*/i) -const identifierParser = P.regex(/^[a-z][a-z0-9]+/i) const identifierExprParser = P.map(identifierParser, ident => Expr.Identifier(ident)) -const callParser = P.map(P.zip2( +const callExprParser = (input: string) => P.map(P.zip2( consumeWhitespace(identifierParser), - P.between(P.string('('), consumeWhitespace(identifierParser), P.string(')')), -), ([name, rest]) => Expr.Call({ name, args: [Expr.Identifier(rest)] })) + parens(consumeWhitespace(P.sepBy(exprParser, comma))), +), ([name, args]) => Expr.Call({ name, args }))(input) const exprParser: P.Parser = P.or([ - callParser, + callExprParser, identifierExprParser, ]) -export const parse = (input: string): Expr => { - const res = exprParser(input.trim()); +const multiExpr = P.many1(exprParser) + +export const parse = (input: string): Array => { + const res = multiExpr(input.trim()); return match(res, { - Ok: ({ value }) => value, + Ok: ({ value, input }) => { + if (input) { + throw new Error(`Input not consumed completely here brosky: "${input}"`) + } + return value + }, Err: ({ error, input }) => { throw new Error(`${error}.\n Left input: ${input.slice(0, 20)}...`) }, -- cgit v1.3.1