Skip to content

Commit f7a488d

Browse files
committed
until
1 parent b072b09 commit f7a488d

File tree

6 files changed

+270
-123
lines changed

6 files changed

+270
-123
lines changed

example/index.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,49 @@
11
// deno-fmt-ignore-file
2+
// deno-lint-ignore-file
23

3-
import { Static, Runtime, Compile } from '@sinclair/parsebox'
4+
import { Static, Runtime } from '@sinclair/parsebox'
5+
import { Type as T } from 'npm:@sinclair/typebox'
46

5-
//
7+
const Type = Runtime.Union([
8+
Runtime.Const('string'),
9+
Runtime.Ref('TemplateLiteral')
10+
])
11+
const TemplateText = Runtime.Union([
12+
Runtime.Until('${'),
13+
Runtime.Until('`'),
14+
], value => T.Literal(value))
615

16+
const TemplateEnd = Runtime.Tuple([
17+
Runtime.Ref('TemplateText'),
18+
Runtime.Const('`')
19+
], value => value[0])
20+
21+
const TemplateInterpolate = Runtime.Tuple([
22+
Runtime.Const('${'),
23+
Runtime.Ref('Type'),
24+
Runtime.Const('}')
25+
], value => value[1])
26+
27+
const TemplateLiteralContent = Runtime.Union([
28+
Runtime.Tuple([Runtime.Ref('TemplateText'), Runtime.Ref('TemplateInterpolate'), Runtime.Ref('TemplateLiteralContent')]),
29+
Runtime.Ref('TemplateText'),
30+
])
31+
32+
const TemplateLiteral = Runtime.Tuple([
33+
Runtime.Const('`'),
34+
Runtime.Ref('TemplateLiteralContent'),
35+
Runtime.Const('`'),
36+
], value => value[1])
37+
38+
const Module = new Runtime.Module({
39+
TemplateLiteralContent,
40+
TemplateInterpolate,
41+
TemplateLiteral,
42+
TemplateText,
43+
TemplateEnd,
44+
Type
45+
})
46+
47+
const Result = Module.Parse('Type', '`hello ${string} world ${string} ${string}`')
48+
49+
console.log(Result)

src/runtime/guard.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*--------------------------------------------------------------------------
2+
3+
@sinclair/parsebox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2024-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
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+
export function IsEqual(left: unknown, right: unknown): boolean {
32+
return left === right
33+
}
34+
export function HasPropertyKey<Key extends PropertyKey>(value: Record<PropertyKey, unknown>, key: Key): value is Record<PropertyKey, unknown> & { [_ in Key]: unknown } {
35+
return key in value
36+
}
37+
export function IsObject(value: unknown): value is Record<PropertyKey, unknown> {
38+
return typeof value === 'object' && value !== null
39+
}
40+
export function IsArray(value: unknown): value is unknown[] {
41+
return globalThis.Array.isArray(value)
42+
}
43+
export function IsString(value: unknown): value is string {
44+
return typeof value === 'string'
45+
}

src/runtime/parse.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ THE SOFTWARE.
2929
// deno-fmt-ignore-file
3030
// deno-lint-ignore-file no-unused-vars no-explicit-any
3131

32+
import { Type } from "../../example/typebox/compiled/parser.ts"
3233
import { Guard } from '../guard/index.ts'
3334
import * as Token from './token.ts'
3435
import * as Types from './types.ts'
@@ -67,6 +68,12 @@ function ParseConst<Value extends string>(value: Value, code: string, context: u
6768
return Token.Const(value, code) as never
6869
}
6970
// ------------------------------------------------------------------
71+
// Until
72+
// ------------------------------------------------------------------
73+
function ParseUntil<Value extends string>(value: Value, code: string, context: unknown): [] | [Value, string] {
74+
return Token.Until(value, code) as never
75+
}
76+
// ------------------------------------------------------------------
7077
// Ident
7178
// ------------------------------------------------------------------
7279
function ParseIdent(code: string, _context: unknown): [] | [string, string] {
@@ -138,6 +145,7 @@ function ParseParser<Parser extends Types.IParser>(moduleProperties: Types.IModu
138145
Types.IsString(parser) ? ParseString(parser.options, code, context) :
139146
Types.IsTuple(parser) ? ParseTuple(moduleProperties, parser.parsers, code, context) :
140147
Types.IsUnion(parser) ? ParseUnion(moduleProperties, parser.parsers, code, context) :
148+
Types.IsUntil(parser) ? ParseUntil(parser.value, code, context) :
141149
[]
142150
)
143151
return (result.length === 2 ? [parser.mapping(result[0], context), result[1]] : result) as never

0 commit comments

Comments
 (0)