diff --git a/.vscode/settings.json b/.vscode/settings.json
index fd4665b..2f13220 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -6,4 +6,4 @@
},
"deno.enable": true,
"deno.lint": false,
-}
\ No newline at end of file
+}
diff --git a/deno.jsonc b/deno.jsonc
index f0db3c0..0af3cfb 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -17,7 +17,11 @@
// --------------------------------------------------------------
// ParseBox
// --------------------------------------------------------------
- "@sinclair/parsebox": "./src/index.ts"
+ "@sinclair/parsebox": "./src/index.ts",
+ // --------------------------------------------------------------
+ // Mitata
+ // --------------------------------------------------------------
+ "mitata": "npm:mitata"
},
"fmt": {
"lineWidth": 240,
@@ -27,4 +31,4 @@
"compilerOptions": {
"strict": true
}
-}
\ No newline at end of file
+}
diff --git a/deno.lock b/deno.lock
index a77b2cd..fb4e16e 100644
--- a/deno.lock
+++ b/deno.lock
@@ -5,7 +5,8 @@
"jsr:@std/internal@^1.0.6": "1.0.6",
"jsr:@std/path@1.0.8": "1.0.8",
"npm:@sinclair/typebox@*": "0.34.33",
- "npm:@types/node@*": "22.15.15"
+ "npm:@types/node@*": "22.15.15",
+ "npm:mitata@*": "1.0.34"
},
"jsr": {
"@std/assert@1.0.12": {
@@ -31,6 +32,9 @@
"undici-types"
]
},
+ "mitata@1.0.34": {
+ "integrity": "sha512-Mc3zrtNBKIMeHSCQ0XqRLo1vbdIx1wvFV9c8NJAiyho6AjNfMY8bVhbS12bwciUdd1t4rj8099CH3N3NFahaUA=="
+ },
"undici-types@6.21.0": {
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
}
@@ -170,5 +174,10 @@
"https://raw.githubusercontent.com/sinclairzx81/tasksmith/0.8.5/src/test/test.ts": "894650a3af2f7c0c8e4e4f0930d6f3e7bfc5187c5c66ce869c0429b942a51c2d",
"https://raw.githubusercontent.com/sinclairzx81/tasksmith/0.8.5/src/tsc/index.ts": "ef3fd7538b1f3d85e102f4b6317ad92e2f1dc007df6d7d7cceb283913e71117d",
"https://raw.githubusercontent.com/sinclairzx81/tasksmith/0.8.5/src/tsc/tsc.ts": "2d84d6b8bf155811eec128a03095dbad9f15feb7602c7fc3c6a9e0c36dc38602"
+ },
+ "workspace": {
+ "dependencies": [
+ "npm:mitata@*"
+ ]
}
}
diff --git a/src/token/bigint.ts b/src/token/bigint.ts
index c397d3c..d4b3549 100644
--- a/src/token/bigint.ts
+++ b/src/token/bigint.ts
@@ -44,14 +44,13 @@ type TTakeBigInt = (
)
function TakeBigInt(input: Input): TTakeBigInt {
const integer = Integer(input)
- return (
- IsResult(integer) ? (() => {
- const n = Take(['n'], integer[1])
- return IsResult(n)
- ? [`${integer[0]}`, n[1]]
- : [] // fail: did not match 'n'
- })() : [] // fail: did not match Integer
- ) as never
+ if (IsResult(integer)) {
+ const n = Take(['n'], integer[1])
+ if (IsResult(n))
+ return [integer[0], n[1]] as never
+ }
+
+ return [] as never
}
// ------------------------------------------------------------------
// BigInt
@@ -63,4 +62,4 @@ export type TBigInt = (
/** Matches if next is a Integer literal with trailing 'n'. Trailing 'n' is omitted in result. */
export function BigInt(input: Input): TBigInt {
return TakeBigInt(input) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/ident.ts b/src/token/ident.ts
index eedc472..f0b98ae 100644
--- a/src/token/ident.ts
+++ b/src/token/ident.ts
@@ -46,9 +46,6 @@ const Initial = [...Alpha, UnderScore, DollarSign]
type TTakeInitial = (
TTake
)
-function TakeInitial(input: Input): TTakeInitial {
- return Take(Initial, input) as never
-}
// ------------------------------------------------------------------
// TakeRemaining
// ------------------------------------------------------------------
@@ -61,7 +58,7 @@ type TTakeRemaining = (
: [Result, Input]
)
function TakeRemaining(input: Input, result: string = ''): TTakeRemaining {
- const remaining = Take(Remaining, input) as string[]
+ const remaining = Take(Remaining, input)
return (
IsResult(remaining)
? TakeRemaining(remaining[1], `${result}${remaining[0]}`)
@@ -79,15 +76,17 @@ type TTakeIdent = (
: [] // fail: did not match Initial
)
function TakeIdent(input: Input): TTakeIdent {
- const initial = TakeInitial(input) as string[]
- return (
- IsResult(initial) ? (() => {
- const remaining = TakeRemaining(initial[1])
- return IsResult(remaining)
- ? [`${initial[0]}${remaining[0]}`, remaining[1]]
- : [] // fail: did not match Remaining
- })() : [] // fail: did not match Initial
- ) as never
+ const initial = Take(Initial, input) as [string, string] | []
+ if (IsResult(initial)) {
+ const remaining = TakeRemaining(initial[1])
+ if (IsResult(remaining))
+ return [initial[0] + remaining[0], remaining[1]] as never
+
+ // fail: did not match Remaining
+ }
+
+ // fail: did not match Initial
+ return [] as never;
}
// ------------------------------------------------------------------
// Ident
@@ -99,4 +98,4 @@ export type TIdent = (
/** Matches if next is an Ident */
export function Ident(input: Input): TIdent {
return TakeIdent(Trim(input)) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/integer.ts b/src/token/integer.ts
index 008c4dd..565c2f2 100644
--- a/src/token/integer.ts
+++ b/src/token/integer.ts
@@ -65,7 +65,7 @@ type TAllowedDigits = [...TDigit, TUnderScore]
const AllowedDigits = [...Digit, UnderScore] as TAllowedDigits
// ...
type TTakeDigits = (
- TMany
+ TMany
)
function TakeDigits(input: Input): TTakeDigits {
return Many(AllowedDigits, [UnderScore], input) as never
@@ -86,22 +86,25 @@ type TTakeInteger = (
)
function TakeInteger(input: Input): TTakeInteger {
const sign = TakeSign(input)
- return (
- IsResult(sign) ? (() => {
- const zero = Take([Zero], sign[1])
- return IsResult(zero)
- ? [`${sign[0]}${zero[0]}`, zero[1]]
- : (() => {
- const nonZero = TakeNonZero(sign[1])
- return IsResult(nonZero) ? (() => {
- const digits = TakeDigits(nonZero[1])
- return IsResult(digits)
- ? [`${sign[0]}${nonZero[0]}${digits[0]}`, digits[1]]
- : [] // fail: did not match Digits
- })() : [] // fail: did not match NonZero
- })()
- })() : [] // fail: did not match Sign
- ) as never
+ if (IsResult(sign)) {
+ const zero = Take([Zero], sign[1])
+ if (IsResult(zero))
+ return [sign[0] + zero[0], zero[1]] as never
+
+ const nonZero = TakeNonZero(sign[1])
+ if (IsResult(nonZero)) {
+ const digits = TakeDigits(nonZero[1])
+ if (IsResult(digits))
+ return [sign[0] + nonZero[0] + digits[0], digits[1]] as never
+
+ // fail: did not match Digits
+ }
+
+ // fail: did not match NonZero
+ }
+
+ // fail: did not match Sign
+ return [] as never
}
// ------------------------------------------------------------------
// Integer
@@ -114,4 +117,3 @@ export type TInteger = (
export function Integer(input: Input): TInteger {
return TakeInteger(Trim(input)) as never
}
-
diff --git a/src/token/internal/char.ts b/src/token/internal/char.ts
index 791d96c..46d6898 100644
--- a/src/token/internal/char.ts
+++ b/src/token/internal/char.ts
@@ -32,7 +32,9 @@ THE SOFTWARE.
// Range
// ------------------------------------------------------------------
function Range(start: number, end: number): string[] {
- return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i))
+ return new Array(end - start + 1)
+ .fill(start)
+ .map((start, i) => String.fromCharCode(start + i))
}
// ------------------------------------------------------------------
// Alphas
@@ -49,7 +51,7 @@ export type TAlpha = [
export const Alpha = [
...Range(97, 122), // Lowercase
...Range(65, 90) // Uppercase
-] as TAlpha
+] as TAlpha
// ------------------------------------------------------------------
// Digits
diff --git a/src/token/internal/optional.ts b/src/token/internal/optional.ts
index 2f019c0..2756f64 100644
--- a/src/token/internal/optional.ts
+++ b/src/token/internal/optional.ts
@@ -42,8 +42,8 @@ export function Optional
(value: Value, input: Input): TOptional {
const result = Take([value], input)
return (
- IsResult(result)
- ? result
+ IsResult(result)
+ ? result
: ['', input]
) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/internal/result.ts b/src/token/internal/result.ts
index 4b9a3b8..777e1be 100644
--- a/src/token/internal/result.ts
+++ b/src/token/internal/result.ts
@@ -26,9 +26,9 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
-import { IsArray, IsEqual } from './guard.ts'
+import { IsEqual } from './guard.ts'
/** Checks the value is a Tuple-2 [string, string] result */
-export function IsResult(value: unknown): value is [string, string] {
- return IsArray(value) && IsEqual(value.length, 2)
+export function IsResult(value: [] | [string, string]): value is [string, string] {
+ return IsEqual(value.length, 2)
}
diff --git a/src/token/internal/take.ts b/src/token/internal/take.ts
index f55d389..d72c029 100644
--- a/src/token/internal/take.ts
+++ b/src/token/internal/take.ts
@@ -28,20 +28,21 @@ THE SOFTWARE.
// deno-fmt-ignore-file
-import { IsEqual, IsString } from './guard.ts'
+import { IsEqual } from './guard.ts'
+import { IsResult } from './result.ts'
// ------------------------------------------------------------------
// TakeString
// ------------------------------------------------------------------
type TTakeVariant = (
- Input extends `${Variant}${infer Rest extends string}`
+ Input extends `${Variant}${infer Rest extends string}`
? [Variant, Rest]
: []
)
function TakeVariant(variant: Variant, input: Input): TTakeVariant {
return (
- IsEqual(input.indexOf(variant), 0)
- ? [variant, input.slice(variant.length)]
+ IsEqual(input.indexOf(variant), 0)
+ ? [variant, input.slice(variant.length)]
: []
) as never
}
@@ -51,20 +52,19 @@ function TakeVariant(variant: Vari
/** Takes one of the given variants or fail */
export type TTake = (
Variants extends [infer ValueLeft extends string, ...infer ValueRight extends string[]]
- ? TTakeVariant extends [infer Take extends string, infer Rest extends string]
+ ? TTakeVariant extends [infer Take extends string, infer Rest extends string]
? [Take, Rest]
: TTake
: []
)
/** Takes one of the given variants or fail */
export function Take(variants: [...Variants], input: Input): TTake {
- const [left, ...right] = variants
- return (
- IsString(left)
- ? (() => {
- const result = TakeVariant(left, input)
- return IsEqual(result.length, 2) ? result : Take(right, input)
- })()
- : []
- ) as never
+ for (let i = 0; i < variants.length; i++) {
+ const result = TakeVariant(variants[i], input) as [] | [string, string]
+ if (IsResult(result)) {
+ return result as never
+ }
+ }
+
+ return [] as never
}
diff --git a/src/token/internal/trim.ts b/src/token/internal/trim.ts
index cf278f9..e4d7d25 100644
--- a/src/token/internal/trim.ts
+++ b/src/token/internal/trim.ts
@@ -58,8 +58,8 @@ function DiscardMultilineComment(input: Input): TDiscardMu
// DiscardLineComment
// ------------------------------------------------------------------
type TDiscardLineComment = (
- Input extends `${string}${Char.TNewLine}${infer Rest extends string}`
- ? TTrimWhitespace<`${Char.TNewLine}${Rest}`>
+ Input extends `${string}${Char.TNewLine}${infer Rest extends string}`
+ ? TTrimWhitespace<`${Char.TNewLine}${Rest}`>
: ''
)
function DiscardLineComment(input: Input): TDiscardLineComment {
@@ -121,4 +121,3 @@ export function Trim(input: Input): TTrim {
trimmed
) as never
}
-
diff --git a/src/token/number.ts b/src/token/number.ts
index 2de08df..6bc22a9 100644
--- a/src/token/number.ts
+++ b/src/token/number.ts
@@ -77,11 +77,9 @@ type TTakeFractional = (
function TakeFractional(input: Input): TTakeFractional {
const digits = Many(AllowedDigits, [UnderScore], input)
return (
- IsResult(digits)
- ? IsEqual(digits[0], '')
- ? [] // fail: no Digits
- : [digits[0], digits[1]]
- : [] // fail: did not match Digits
+ IsResult(digits) && !IsEqual(digits[0], '')
+ ? [digits[0], digits[1]]
+ : [] // fail: did not match Digits or no Digits
) as never
}
// ------------------------------------------------------------------
@@ -95,17 +93,19 @@ type TLeadingDot = (
: [] // fail: did not match Dot
)
function LeadingDot
- (sign: Sign, input: Input):
+ (sign: Sign, input: Input):
TLeadingDot {
const dot = Take([Dot], input)
- return (
- IsResult(dot) ? (() => {
- const fractional = TakeFractional(dot[1])
- return IsResult(fractional)
- ? [`${sign}0${dot[0]}${fractional[0]}`, fractional[1]]
- : [] // fail: did not match Fractional
- })() : [] // fail: did not match Dot
- ) as never
+ if (IsResult(dot)) {
+ const fractional = TakeFractional(dot[1])
+ if (IsResult(fractional))
+ return [sign + '0' + dot[0] + fractional[0], fractional[1]] as never
+
+ // fail: did not match Fractional
+ }
+
+ // fail: did not match Dot
+ return [] as never
}
// ------------------------------------------------------------------
// TakeLeadingInteger
@@ -120,19 +120,21 @@ type TLeadingInteger = (
: [] // fail: did not match Integer
)
function LeadingInteger
- (sign: Sign, input: Input):
+ (sign: Sign, input: Input):
TLeadingInteger {
const integer = Integer(input)
+ if (!IsResult(integer))
+ return [] as never // fail: did not match Integer
+
+ const dot = Take([Dot], integer[1])
+ if (!IsResult(dot))
+ return [sign + integer[0], integer[1]] as never // fail: did not match Dot, use Integer
+
+ const fractional = TakeFractional(dot[1])
return (
- IsResult(integer) ? (() => {
- const dot = Take([Dot], integer[1])
- return IsResult(dot) ? (() => {
- const fractional = TakeFractional(dot[1])
- return IsResult(fractional)
- ? [`${sign}${integer[0]}${dot[0]}${fractional[0]}`, fractional[1]]
- : [`${sign}${integer[0]}`, dot[1]] // fail: did not match Fractional, use Integer
- })() : [`${sign}${integer[0]}`, integer[1]] // fail: did not match Dot, use Integer
- })() : [] // fail: did not match Integer
+ IsResult(fractional)
+ ? [sign + integer[0] + dot[0] + fractional[0], fractional[1]]
+ : [sign + integer[0], dot[1]] // fail: did not match Fractional, use Integer
) as never
}
// ------------------------------------------------------------------
@@ -165,4 +167,4 @@ export type TNumber = (
/** Matches if next is a literal Number */
export function Number(input: Input): TNumber {
return TakeNumber(Trim(input)) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/span.ts b/src/token/span.ts
index 6dc7470..cc88508 100644
--- a/src/token/span.ts
+++ b/src/token/span.ts
@@ -46,18 +46,18 @@ type TMultiLine
: [] // fail: did not match Start
)
function MultiLine
- (start: Start, end: End, input: Input):
+ (start: Start, end: End, input: Input):
TMultiLine {
- return (
- input.startsWith(start) ? (() => {
- const until = Until([end], input.slice(start.length))
- return IsResult(until) ? (() => {
- return until[1].startsWith(end)
- ? [`${until[0]}`, until[1].slice(end.length)]
- : [] // fail: did not match End
- })() : [] // fail: did not match Until
- })() : [] // fail: did not match Start
- ) as never
+ if (input.startsWith(start)) {
+ const until = Until([end], input.slice(start.length))
+ if (IsResult(until) && until[1].startsWith(end))
+ return [until[0], until[1].slice(end.length)] as never
+
+ // fail: did not match End or Until
+ }
+
+ // fail: did not match Start
+ return [] as never
}
// ------------------------------------------------------------------
// SingleLine
@@ -72,18 +72,18 @@ type TSingleLine
: [] // fail: not match Start
)
function SingleLine
- (start: Start, end: End, input: Input):
+ (start: Start, end: End, input: Input):
TSingleLine {
- return (
- input.startsWith(start) ? (() => {
- const until = Until([NewLine, end], input.slice(start.length))
- return IsResult(until) ? (() => {
- return until[1].startsWith(end)
- ? [`${until[0]}`, until[1].slice(end.length)]
- : [] // fail: did not match End
- })() : [] // fail: did not match Until
- })() : [] // fail: not match Start
- ) as never
+ if (input.startsWith(start)) {
+ const until = Until([NewLine, end], input.slice(start.length))
+ if (IsResult(until) && until[1].startsWith(end))
+ return [until[0], until[1].slice(end.length)] as never
+
+ // fail: did not match End or Until
+ }
+
+ // fail: not match Start
+ return [] as never
}
// ------------------------------------------------------------------
// Span
@@ -96,11 +96,11 @@ export type TSpan
- (start: Start, end: End, multiLine: MultiLine, input: Input):
+ (start: Start, end: End, multiLine: MultiLine, input: Input):
TSpan {
return (
multiLine
? MultiLine(start, end, Trim(input))
: SingleLine(start, end, Trim(input))
) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/string.ts b/src/token/string.ts
index 848d513..6a2fcd8 100644
--- a/src/token/string.ts
+++ b/src/token/string.ts
@@ -60,10 +60,10 @@ type TTakeString = (
: [] // fail: did not match Initial
)
function TakeString(quotes: [...Quotes], input: Input): TTakeString {
- const initial = TakeInitial(quotes, input) as [string, string]
+ const initial = TakeInitial(quotes, input)
return (
IsResult(initial)
- ? TakeSpan(initial[0], `${initial[0]}${initial[1]}`)
+ ? TakeSpan(initial[0], initial[0] + initial[1])
: [] // fail: did not match Initial
) as never
}
@@ -74,4 +74,4 @@ export type TString = (
/** Matches a literal String with the given quotes */
export function String(quotes: [...Quotes], input: Input): TString {
return TakeString(quotes, Trim(input)) as never
-}
\ No newline at end of file
+}
diff --git a/src/token/until.ts b/src/token/until.ts
index f3431c0..fda200c 100644
--- a/src/token/until.ts
+++ b/src/token/until.ts
@@ -28,29 +28,27 @@ THE SOFTWARE.
// deno-fmt-ignore-file
-import { IsEqual, IsString } from './internal/guard.ts'
+import { IsEqual } from './internal/guard.ts'
// ------------------------------------------------------------------
// IsEnd
// ------------------------------------------------------------------
type TIsEnd = (
- End extends [infer Left extends string, ...infer Right extends string[]]
- ? Input extends `${Left}${string}`
+ End extends [infer Left extends string, ...infer Right extends string[]]
+ ? Input extends `${Left}${string}`
? true
: TIsEnd
: false
)
function IsEnd
- (end: [...End], input: Input):
+ (end: [...End], input: Input):
TIsEnd {
- const [left, ...right] = end
- return (
- IsString(left)
- ? input.startsWith(left)
- ? true
- : IsEnd(right, input)
- : false
- ) as never
+ for (let i = 0; i < end.length; i++) {
+ if (input.startsWith(end[i]))
+ return true as never;
+ }
+
+ return false as never;
}
// ------------------------------------------------------------------
// Until
@@ -59,21 +57,22 @@ function IsEnd
export type TUntil = (
Input extends ``
? [] // fail: Input is empty
- : TIsEnd extends true
+ : TIsEnd extends true
? [Result, Input]
- : Input extends `${infer Left extends string}${infer Right extends string}`
+ : Input extends `${infer Left extends string}${infer Right extends string}`
? TUntil
: []
)
/** Match Input until but not including End. No match if End not found. */
export function Until
(end: [...End], input: Input, result: string = ''): TUntil {
- return (
- IsEqual(input, '')
- ? [] // fail: Input is empty
- : IsEnd(end, input) ? [result, input] : (() => {
- const [left, right] = [input.slice(0, 1), input.slice(1)]
- return Until(end, right, `${result}${left}`)
- })()
- ) as never
+ if (IsEqual(input, ''))
+ return [] as never // fail: Input is empty
+
+ if (IsEnd(end, input))
+ return [result, input] as never
+
+ const left = input.slice(0, 1),
+ right = input.slice(1)
+ return Until(end, right, result + left) as never
}
diff --git a/src/token/until_1.ts b/src/token/until_1.ts
index e95514c..d9bf9e3 100644
--- a/src/token/until_1.ts
+++ b/src/token/until_1.ts
@@ -37,22 +37,20 @@ import { type TUntil, Until } from './until.ts'
// ------------------------------------------------------------------
/** Match Input until but not including End. No match if End not found or match is zero-length. */
export type TUntil_1 = (
- TUntil extends [infer Until extends string, infer UntilRest extends string]
- ? Until extends ''
+ TUntil extends [infer Until extends string, infer UntilRest extends string]
+ ? Until extends ''
? [] // fail: match has no characters
: [Until, UntilRest]
: [] // fail: did not match Until
)
/** Match Input until but not including End. No match if End not found or match is zero-length. */
export function Until_1
- (end: [...End], input: Input):
+ (end: [...End], input: Input):
TUntil_1 {
const until = Until(end, input)
return (
- IsResult(until)
- ? IsEqual(until[0], '')
- ? [] // fail: match has no characters
- : until
- : [] // fail: did not match Until
+ IsResult(until) && !IsEqual(until[0], '')
+ ? until
+ : [] // fail: match has no characters or did not match Until
) as never
}