Skip to content

Commit 6e218c3

Browse files
committed
Unsigned | Match
1 parent 92d265f commit 6e218c3

4 files changed

Lines changed: 161 additions & 101 deletions

File tree

src/token/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,7 @@ export * from './number.ts'
3434
export * from './rest.ts'
3535
export * from './span.ts'
3636
export * from './string.ts'
37+
export * from './unsigned_integer.ts'
38+
export * from './unsigned_number.ts'
3739
export * from './until_1.ts'
3840
export * from './until.ts'

src/token/integer.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ function TakeSign<Input extends string>(input: Input): TTakeSign<Input> {
4545
return Optional(Hyphen, input) as never
4646
}
4747
// ------------------------------------------------------------------
48-
// TakeInteger
48+
// TakeSignedInteger
4949
// ------------------------------------------------------------------
50-
type TTakeInteger<Input extends string> = (
50+
type TTakeSignedInteger<Input extends string> = (
5151
TTakeSign<Input> extends [infer Sign extends string, infer SignRest extends string]
5252
? TUnsignedInteger<SignRest> extends [infer UnsignedInteger extends string, infer UnsignedIntegerRest extends string]
5353
? [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest]
5454
: [] // fail: did not match unsigned integer
5555
: [] // fail: did not match Sign
5656
)
57-
function TakeInteger<Input extends string>(input: Input): TTakeInteger<Input> {
57+
function TakeSignedInteger<Input extends string>(input: Input): TTakeSignedInteger<Input> {
5858
return Match(TakeSign(input), (Sign, SignRest) =>
5959
Match(UnsignedInteger(SignRest), (UnsignedInteger, UnsignedIntegerRest) =>
6060
[`${Sign}${UnsignedInteger}`, UnsignedIntegerRest],
@@ -64,12 +64,11 @@ function TakeInteger<Input extends string>(input: Input): TTakeInteger<Input> {
6464
// ------------------------------------------------------------------
6565
// Integer
6666
// ------------------------------------------------------------------
67-
/** Matches if next is a Integer */
67+
/** Matches if next is a signed or unsigned Integer */
6868
export type TInteger<Input extends string> = (
69-
TTakeInteger<TTrim<Input>>
69+
TTakeSignedInteger<TTrim<Input>>
7070
)
71-
/** Matches if next is a Integer */
71+
/** Matches if next is a signed or unsigned Integer */
7272
export function Integer<Input extends string>(input: Input): TInteger<Input> {
73-
return TakeInteger(Trim(input)) as never
74-
}
75-
console.log(Integer('0'))
73+
return TakeSignedInteger(Trim(input)) as never
74+
}

src/token/number.ts

Lines changed: 17 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,12 @@ THE SOFTWARE.
2828

2929
// deno-fmt-ignore-file
3030

31-
import { IsEqual } from './internal/guard.ts'
32-
import { IsMatch, Match } from './internal/match.ts'
31+
import { Match } from './internal/match.ts'
3332
import { type TTrim, Trim } from './internal/trim.ts'
34-
import { type TTake, Take } from './internal/take.ts'
35-
import { type TMany, Many } from './internal/many.ts'
3633
import { type TOptional, Optional } from './internal/optional.ts'
37-
38-
import { type TDigit, Digit, TUnderScore, UnderScore } from './internal/char.ts'
39-
import { type TDot, Dot } from './internal/char.ts'
4034
import { type THyphen, Hyphen } from './internal/char.ts'
41-
import { type TInteger, Integer } from './integer.ts'
4235

43-
// ------------------------------------------------------------------
44-
// AllowedDigits
45-
// ------------------------------------------------------------------
46-
type TAllowedDigits = [...TDigit, TUnderScore]
47-
const AllowedDigits = [...Digit, UnderScore] as TAllowedDigits
36+
import { type TUnsignedNumber, UnsignedNumber } from './unsigned_number.ts'
4837

4938
// ------------------------------------------------------------------
5039
// TakeSign
@@ -56,94 +45,30 @@ function TakeSign<Input extends string>(input: Input): TTakeSign<Input> {
5645
return Optional(Hyphen, input) as never
5746
}
5847
// ------------------------------------------------------------------
59-
// IsLeadingDot
60-
// ------------------------------------------------------------------
61-
type TIsLeadingDot<Input extends string> = (
62-
TTake<[TDot], Input> extends [string, string] ? true : false
63-
)
64-
function IsLeadingDot<Input extends string>(input: Input): TIsLeadingDot<Input> {
65-
return IsMatch(Take([Dot], input)) as never
66-
}
67-
// ------------------------------------------------------------------
68-
// TakeFractional
69-
// ------------------------------------------------------------------
70-
type TTakeFractional<Input extends string> = (
71-
TMany<TAllowedDigits, [TUnderScore], Input> extends [infer Digits extends string, infer DigitsRest extends string]
72-
? Digits extends ''
73-
? [] // fail: no Digits
74-
: [Digits, DigitsRest]
75-
: [] // fail: did not match Digits
76-
)
77-
function TakeFractional<Input extends string>(input: Input): TTakeFractional<Input> {
78-
return Match(Many(AllowedDigits, [UnderScore], input), (Digits, DigitsRest) =>
79-
IsEqual(Digits, '')
80-
? [] // fail: no Digits
81-
: [Digits, DigitsRest]
82-
, () => []) as never // fail: did not match Digits
83-
}
84-
// ------------------------------------------------------------------
85-
// LeadingDot
86-
// ------------------------------------------------------------------
87-
type TLeadingDot<Sign extends string, Input extends string> = (
88-
TTake<[TDot], Input> extends [infer Dot extends string, infer DotRest extends string]
89-
? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string]
90-
? [`${Sign}0${Dot}${Fractional}`, FractionalRest]
91-
: [] // fail: did not match Fractional
92-
: [] // fail: did not match Dot
93-
)
94-
function LeadingDot<Sign extends string, Input extends string>(sign: Sign, input: Input): TLeadingDot<Sign, Input> {
95-
return Match(Take([Dot], input), (Dot, DotRest) =>
96-
Match(TakeFractional(DotRest), (Fractional, FractionalRest) =>
97-
[`${sign}0${Dot}${Fractional}`, FractionalRest],
98-
() => []), // fail: did not match Fractional
99-
() => []) as never // fail: did not match Dot
100-
}
101-
// ------------------------------------------------------------------
102-
// TakeLeadingInteger
103-
// ------------------------------------------------------------------
104-
type TLeadingInteger<Sign extends string, Input extends string> = (
105-
TInteger<Input> extends [infer Integer extends string, infer IntegerRest extends string]
106-
? TTake<[TDot], IntegerRest> extends [infer Dot extends string, infer DotRest extends string]
107-
? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string]
108-
? [`${Sign}${Integer}${Dot}${Fractional}`, FractionalRest]
109-
: [`${Sign}${Integer}`, DotRest] // fail: did not match Fractional, use Integer
110-
: [`${Sign}${Integer}`, IntegerRest] // fail: did not match Dot, use Integer
111-
: [] // fail: did not match Integer
112-
)
113-
function LeadingInteger<Sign extends string, Input extends string>(sign: Sign, input: Input): TLeadingInteger<Sign, Input> {
114-
return Match(Integer(input), (Integer, IntegerRest) =>
115-
Match(Take([Dot], IntegerRest), (Dot, DotRest) =>
116-
Match(TakeFractional(DotRest), (Fractional, FractionalRest) =>
117-
[`${sign}${Integer}${Dot}${Fractional}`, FractionalRest],
118-
() => [`${sign}${Integer}`, DotRest]), // fail: did not match Fractional, use Integer
119-
() => [`${sign}${Integer}`, IntegerRest]), // fail: did not match Dot, use Integer
120-
() => []) as never // fail: did not match Integer
121-
}
122-
// ------------------------------------------------------------------
123-
// TakeNumber
48+
// TakeSignedNumber
12449
// ------------------------------------------------------------------
125-
type TTakeNumber<Input extends string> = (
50+
type TTakeSignedNumber<Input extends string> = (
12651
TTakeSign<Input> extends [infer Sign extends string, infer SignRest extends string]
127-
? TIsLeadingDot<SignRest> extends true
128-
? TLeadingDot<Sign, SignRest>
129-
: TLeadingInteger<Sign, SignRest>
52+
? TUnsignedNumber<SignRest> extends [infer UnsignedInteger extends string, infer UnsignedIntegerRest extends string]
53+
? [`${Sign}${UnsignedInteger}`, UnsignedIntegerRest]
54+
: [] // fail: did not match unsigned integer
13055
: [] // fail: did not match Sign
13156
)
132-
function TakeNumber<Input extends string>(input: Input): TTakeNumber<Input> {
57+
function TakeSignedNumber<Input extends string>(input: Input): TTakeSignedNumber<Input> {
13358
return Match(TakeSign(input), (Sign, SignRest) =>
134-
IsLeadingDot(SignRest)
135-
? LeadingDot(Sign, SignRest)
136-
: LeadingInteger(Sign, SignRest)
137-
, () => []) as never // fail: did not match Sign
59+
Match(UnsignedNumber(SignRest), (UnsignedInteger, UnsignedIntegerRest) =>
60+
[`${Sign}${UnsignedInteger}`, UnsignedIntegerRest],
61+
() => []), // fail: did not match unsigned integer
62+
() => []) as never // fail: did not match Sign
13863
}
13964
// ------------------------------------------------------------------
140-
// Number
65+
// Integer
14166
// ------------------------------------------------------------------
142-
/** Matches if next is a literal Number */
67+
/** Matches if next is a signed or unsigned Number */
14368
export type TNumber<Input extends string> = (
144-
TTakeNumber<TTrim<Input>>
69+
TTakeSignedNumber<TTrim<Input>>
14570
)
146-
/** Matches if next is a literal Number */
71+
/** Matches if next is a signed or unsigned Number */
14772
export function Number<Input extends string>(input: Input): TNumber<Input> {
148-
return TakeNumber(Trim(input)) as never
73+
return TakeSignedNumber(Trim(input)) as never
14974
}

src/token/unsigned_number.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*--------------------------------------------------------------------------
2+
3+
ParseBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2024-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
// deno-fmt-ignore-file
30+
31+
import { IsEqual } from './internal/guard.ts'
32+
import { IsMatch, Match } from './internal/match.ts'
33+
import { type TTrim, Trim } from './internal/trim.ts'
34+
import { type TTake, Take } from './internal/take.ts'
35+
import { type TMany, Many } from './internal/many.ts'
36+
import { type TDigit, type TUnderScore, Digit, UnderScore } from './internal/char.ts'
37+
import { type TDot, Dot } from './internal/char.ts'
38+
39+
import { type TUnsignedInteger, UnsignedInteger } from './unsigned_integer.ts'
40+
41+
// ------------------------------------------------------------------
42+
// AllowedDigits
43+
// ------------------------------------------------------------------
44+
type TAllowedDigits = [...TDigit, TUnderScore]
45+
const AllowedDigits = [...Digit, UnderScore] as TAllowedDigits
46+
47+
// ------------------------------------------------------------------
48+
// IsLeadingDot
49+
// ------------------------------------------------------------------
50+
type TIsLeadingDot<Input extends string> = (
51+
TTake<[TDot], Input> extends [string, string] ? true : false
52+
)
53+
function IsLeadingDot<Input extends string>(input: Input): TIsLeadingDot<Input> {
54+
return IsMatch(Take([Dot], input)) as never
55+
}
56+
// ------------------------------------------------------------------
57+
// TakeFractional
58+
// ------------------------------------------------------------------
59+
type TTakeFractional<Input extends string> = (
60+
TMany<TAllowedDigits, [TUnderScore], Input> extends [infer Digits extends string, infer DigitsRest extends string]
61+
? Digits extends ''
62+
? [] // fail: no Digits
63+
: [Digits, DigitsRest]
64+
: [] // fail: did not match Digits
65+
)
66+
function TakeFractional<Input extends string>(input: Input): TTakeFractional<Input> {
67+
return Match(Many(AllowedDigits, [UnderScore], input), (Digits, DigitsRest) =>
68+
IsEqual(Digits, '')
69+
? [] // fail: no Digits
70+
: [Digits, DigitsRest]
71+
, () => []) as never // fail: did not match Digits
72+
}
73+
// ------------------------------------------------------------------
74+
// LeadingDot
75+
// ------------------------------------------------------------------
76+
type TLeadingDot<Input extends string> = (
77+
TTake<[TDot], Input> extends [infer Dot extends string, infer DotRest extends string]
78+
? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string]
79+
? [`0${Dot}${Fractional}`, FractionalRest]
80+
: [] // fail: did not match Fractional
81+
: [] // fail: did not match Dot
82+
)
83+
function LeadingDot<Input extends string>(input: Input): TLeadingDot<Input> {
84+
return Match(Take([Dot], input), (Dot, DotRest) =>
85+
Match(TakeFractional(DotRest), (Fractional, FractionalRest) =>
86+
[`0${Dot}${Fractional}`, FractionalRest],
87+
() => []), // fail: did not match Fractional
88+
() => []) as never // fail: did not match Dot
89+
}
90+
// ------------------------------------------------------------------
91+
// TakeLeadingInteger
92+
// ------------------------------------------------------------------
93+
type TLeadingInteger<Input extends string> = (
94+
TUnsignedInteger<Input> extends [infer Integer extends string, infer IntegerRest extends string]
95+
? TTake<[TDot], IntegerRest> extends [infer Dot extends string, infer DotRest extends string]
96+
? TTakeFractional<DotRest> extends [infer Fractional extends string, infer FractionalRest extends string]
97+
? [`${Integer}${Dot}${Fractional}`, FractionalRest]
98+
: [`${Integer}`, DotRest] // fail: did not match Fractional, use Integer
99+
: [`${Integer}`, IntegerRest] // fail: did not match Dot, use Integer
100+
: [] // fail: did not match Integer
101+
)
102+
function LeadingInteger<Input extends string>(input: Input): TLeadingInteger<Input> {
103+
return Match(UnsignedInteger(input), (Integer, IntegerRest) =>
104+
Match(Take([Dot], IntegerRest), (Dot, DotRest) =>
105+
Match(TakeFractional(DotRest), (Fractional, FractionalRest) =>
106+
[`${Integer}${Dot}${Fractional}`, FractionalRest],
107+
() => [`${Integer}`, DotRest]), // fail: did not match Fractional, use Integer
108+
() => [`${Integer}`, IntegerRest]), // fail: did not match Dot, use Integer
109+
() => []) as never // fail: did not match Integer
110+
}
111+
// ------------------------------------------------------------------
112+
// TakeUnsignedNumber
113+
// ------------------------------------------------------------------
114+
type TTakeUnsignedNumber<Input extends string> = (
115+
TIsLeadingDot<Input> extends true
116+
? TLeadingDot<Input>
117+
: TLeadingInteger<Input>
118+
)
119+
function TakeUnsignedNumber<Input extends string>(input: Input): TTakeUnsignedNumber<Input> {
120+
return (IsLeadingDot(input)
121+
? LeadingDot(input)
122+
: LeadingInteger(input)) as never
123+
}
124+
// ------------------------------------------------------------------
125+
// UnsignedNumber
126+
// ------------------------------------------------------------------
127+
/** Matches if next is a literal Number */
128+
export type TUnsignedNumber<Input extends string> = (
129+
TTakeUnsignedNumber<TTrim<Input>>
130+
)
131+
/** Matches if next is a literal Number */
132+
export function UnsignedNumber<Input extends string>(input: Input): TUnsignedNumber<Input> {
133+
return TakeUnsignedNumber(Trim(input)) as never
134+
}

0 commit comments

Comments
 (0)