aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser.ts11
-rw-r--r--src/utils/parser-comb.ts8
-rw-r--r--tests/parser.spec.ts51
3 files changed, 70 insertions, 0 deletions
diff --git a/src/parser.ts b/src/parser.ts
index 1c5c08f..8230825 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -1,11 +1,14 @@
import { Enum, constructors, match } from './utils/adt'
import * as P from './utils/parser-comb'
+type Unit = '' | 's' | 'ms'
+
export type Expr = Enum<{
Call: { name: string; args: Expr[] }
Identifier: string
VarIdentifier: string
LiteralString: string
+ LiteralNumber: { value: number, unit: Unit }
}>
export const Expr = constructors<Expr>()
@@ -41,9 +44,17 @@ const stringLiteralParser: P.Parser<Expr> = P.map(
Expr.LiteralString
)
+const numberParser = P.regex(/^[-+]?((\d*\.\d+)|\d+)/)
+
+const numberExprParser: P.Parser<Expr> = P.map(
+ P.zip2(numberParser, P.optional(P.regex(/^(s|ms)/i))),
+ ([value, unit]) => Expr.LiteralNumber({ value: Number(value), unit: (unit ?? '') as Unit }),
+)
+
const exprParser: P.Parser<Expr> = P.or([
stringLiteralParser,
varIdentifierExprParser,
+ numberExprParser,
callExprParser,
identifierExprParser,
])
diff --git a/src/utils/parser-comb.ts b/src/utils/parser-comb.ts
index e0665f6..f682068 100644
--- a/src/utils/parser-comb.ts
+++ b/src/utils/parser-comb.ts
@@ -73,3 +73,11 @@ export const sepBy = <A>(parser: Parser<A>, sepP: Parser<any>): Parser<Array<A>>
Err: _ => Result.Ok({ value: [], input: originalInput }),
})
+export const optional = <A>(parser: Parser<A>): Parser<undefined | A> => input => {
+ const result = parser(input)
+ return match(result, {
+ Ok: _ => result,
+ Err: _ => Result.Ok({ value: undefined, input })
+ })
+}
+
diff --git a/tests/parser.spec.ts b/tests/parser.spec.ts
index 48c398c..f2893b8 100644
--- a/tests/parser.spec.ts
+++ b/tests/parser.spec.ts
@@ -72,5 +72,56 @@ describe('parser', () => {
],
}),
])
+
+ expect(parse(`update(state-container, --count, var(--count))`)).toEqual([
+ Expr.Call({
+ name: 'update',
+ args: [
+ Expr.Identifier('state-container'),
+ Expr.VarIdentifier('--count'),
+ Expr.Call({
+ name: 'var',
+ args: [Expr.VarIdentifier('--count')],
+ }),
+ ],
+ }),
+ ])
+ })
+
+ it('should parse number and css units', () => {
+ expect(parse(`100`)).toEqual([Expr.LiteralNumber({ value: 100, unit: '' })])
+ expect(parse(`100s`)).toEqual([
+ Expr.LiteralNumber({ value: 100, unit: 's' }),
+ ])
+ expect(parse(`100ms`)).toEqual([
+ Expr.LiteralNumber({ value: 100, unit: 'ms' }),
+ ])
+ expect(parse(`3.82`)).toEqual([
+ Expr.LiteralNumber({ value: 3.82, unit: '' }),
+ ])
+ expect(parse(`3.82s`)).toEqual([
+ Expr.LiteralNumber({ value: 3.82, unit: 's' }),
+ ])
+ expect(parse(`3.82ms`)).toEqual([
+ Expr.LiteralNumber({ value: 3.82, unit: 'ms' }),
+ ])
+ expect(parse(`-100`)).toEqual([
+ Expr.LiteralNumber({ value: -100, unit: '' }),
+ ])
+ expect(parse(`-100s`)).toEqual([
+ Expr.LiteralNumber({ value: -100, unit: 's' }),
+ ])
+ expect(parse(`-100ms`)).toEqual([
+ Expr.LiteralNumber({ value: -100, unit: 'ms' }),
+ ])
+ expect(parse(`-3.82`)).toEqual([
+ Expr.LiteralNumber({ value: -3.82, unit: '' }),
+ ])
+ expect(parse(`-3.82s`)).toEqual([
+ Expr.LiteralNumber({ value: -3.82, unit: 's' }),
+ ])
+ expect(parse(`-3.82ms`)).toEqual([
+ Expr.LiteralNumber({ value: -3.82, unit: 'ms' }),
+ ])
})
})