diff options
Diffstat (limited to 'src/parse-expr.ts')
| -rw-r--r-- | src/parse-expr.ts | 26 |
1 files changed, 18 insertions, 8 deletions
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<Expr>() const whitespace = P.regex(/\s*/) const consumeWhitespace = <A>(p: P.Parser<A>): P.Parser<A> => P.between(whitespace, p, whitespace) +const comma = consumeWhitespace(P.string(',')) +const parens = <A>(p: P.Parser<A>): P.Parser<A> => 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<Expr> = 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<Expr> => { + 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)}...`) }, |
