Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
},
"deno.enable": true,
"deno.lint": false,
}
}
8 changes: 6 additions & 2 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
// --------------------------------------------------------------
// ParseBox
// --------------------------------------------------------------
"@sinclair/parsebox": "./src/index.ts"
"@sinclair/parsebox": "./src/index.ts",
// --------------------------------------------------------------
// Mitata
// --------------------------------------------------------------
"mitata": "npm:mitata"
},
"fmt": {
"lineWidth": 240,
Expand All @@ -27,4 +31,4 @@
"compilerOptions": {
"strict": true
}
}
}
11 changes: 10 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 8 additions & 9 deletions src/token/bigint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,13 @@ type TTakeBigInt<Input extends string> = (
)
function TakeBigInt<Input extends string>(input: Input): TTakeBigInt<Input> {
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
Expand All @@ -63,4 +62,4 @@ export type TBigInt<Input extends string> = (
/** Matches if next is a Integer literal with trailing 'n'. Trailing 'n' is omitted in result. */
export function BigInt<Input extends string>(input: Input): TBigInt<Input> {
return TakeBigInt(input) as never
}
}
27 changes: 13 additions & 14 deletions src/token/ident.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ const Initial = [...Alpha, UnderScore, DollarSign]
type TTakeInitial<Input extends string> = (
TTake<TInitial, Input>
)
function TakeInitial<Input extends string>(input: Input): TTakeInitial<Input> {
return Take(Initial, input) as never
}
// ------------------------------------------------------------------
// TakeRemaining
// ------------------------------------------------------------------
Expand All @@ -61,7 +58,7 @@ type TTakeRemaining<Input extends string, Result extends string = ''> = (
: [Result, Input]
)
function TakeRemaining<Input extends string>(input: Input, result: string = ''): TTakeRemaining<Input> {
const remaining = Take(Remaining, input) as string[]
const remaining = Take(Remaining, input)
return (
IsResult(remaining)
? TakeRemaining(remaining[1], `${result}${remaining[0]}`)
Expand All @@ -79,15 +76,17 @@ type TTakeIdent<Input extends string> = (
: [] // fail: did not match Initial
)
function TakeIdent<Input extends string>(input: Input): TTakeIdent<Input> {
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
Expand All @@ -99,4 +98,4 @@ export type TIdent<Input extends string> = (
/** Matches if next is an Ident */
export function Ident<Input extends string>(input: Input): TIdent<Input> {
return TakeIdent(Trim(input)) as never
}
}
38 changes: 20 additions & 18 deletions src/token/integer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type TAllowedDigits = [...TDigit, TUnderScore]
const AllowedDigits = [...Digit, UnderScore] as TAllowedDigits
// ...
type TTakeDigits<Input extends string> = (
TMany<TAllowedDigits, [TUnderScore], Input>
TMany<TAllowedDigits, [TUnderScore], Input>
)
function TakeDigits<Input extends string>(input: Input): TTakeDigits<Input> {
return Many(AllowedDigits, [UnderScore], input) as never
Expand All @@ -86,22 +86,25 @@ type TTakeInteger<Input extends string> = (
)
function TakeInteger<Input extends string>(input: Input): TTakeInteger<Input> {
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
Expand All @@ -114,4 +117,3 @@ export type TInteger<Input extends string> = (
export function Integer<Input extends string>(input: Input): TInteger<Input> {
return TakeInteger(Trim(input)) as never
}

6 changes: 4 additions & 2 deletions src/token/internal/char.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -49,7 +51,7 @@ export type TAlpha = [
export const Alpha = [
...Range(97, 122), // Lowercase
...Range(65, 90) // Uppercase
] as TAlpha
] as TAlpha

// ------------------------------------------------------------------
// Digits
Expand Down
6 changes: 3 additions & 3 deletions src/token/internal/optional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export function Optional<Value extends string, Input extends string>
(value: Value, input: Input): TOptional<Value, Value> {
const result = Take([value], input)
return (
IsResult(result)
? result
IsResult(result)
? result
: ['', input]
) as never
}
}
6 changes: 3 additions & 3 deletions src/token/internal/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
28 changes: 14 additions & 14 deletions src/token/internal/take.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Variant extends string, Input extends string> = (
Input extends `${Variant}${infer Rest extends string}`
Input extends `${Variant}${infer Rest extends string}`
? [Variant, Rest]
: []
)
function TakeVariant<Variant extends string, Input extends string>(variant: Variant, input: Input): TTakeVariant<Variant, Input> {
return (
IsEqual(input.indexOf(variant), 0)
? [variant, input.slice(variant.length)]
IsEqual(input.indexOf(variant), 0)
? [variant, input.slice(variant.length)]
: []
) as never
}
Expand All @@ -51,20 +52,19 @@ function TakeVariant<Variant extends string, Input extends string>(variant: Vari
/** Takes one of the given variants or fail */
export type TTake<Variants extends string[], Input extends string> = (
Variants extends [infer ValueLeft extends string, ...infer ValueRight extends string[]]
? TTakeVariant<ValueLeft, Input> extends [infer Take extends string, infer Rest extends string]
? TTakeVariant<ValueLeft, Input> extends [infer Take extends string, infer Rest extends string]
? [Take, Rest]
: TTake<ValueRight, Input>
: []
)
/** Takes one of the given variants or fail */
export function Take<Variants extends string[], Input extends string>(variants: [...Variants], input: Input): TTake<Variants, Input> {
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
}
5 changes: 2 additions & 3 deletions src/token/internal/trim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ function DiscardMultilineComment<Input extends string>(input: Input): TDiscardMu
// DiscardLineComment
// ------------------------------------------------------------------
type TDiscardLineComment<Input extends string> = (
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 extends string>(input: Input): TDiscardLineComment<Input> {
Expand Down Expand Up @@ -121,4 +121,3 @@ export function Trim<Input extends string>(input: Input): TTrim<Input> {
trimmed
) as never
}

52 changes: 27 additions & 25 deletions src/token/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ type TTakeFractional<Input extends string> = (
function TakeFractional<Input extends string>(input: Input): TTakeFractional<Input> {
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
}
// ------------------------------------------------------------------
Expand All @@ -95,17 +93,19 @@ type TLeadingDot<Sign extends string, Input extends string> = (
: [] // fail: did not match Dot
)
function LeadingDot<Sign extends string, Input extends string>
(sign: Sign, input: Input):
(sign: Sign, input: Input):
TLeadingDot<Sign, Input> {
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
Expand All @@ -120,19 +120,21 @@ type TLeadingInteger<Sign extends string, Input extends string> = (
: [] // fail: did not match Integer
)
function LeadingInteger<Sign extends string, Input extends string>
(sign: Sign, input: Input):
(sign: Sign, input: Input):
TLeadingInteger<Sign, Input> {
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
}
// ------------------------------------------------------------------
Expand Down Expand Up @@ -165,4 +167,4 @@ export type TNumber<Input extends string> = (
/** Matches if next is a literal Number */
export function Number<Input extends string>(input: Input): TNumber<Input> {
return TakeNumber(Trim(input)) as never
}
}
Loading