Skip to content

Commit 76a0886

Browse files
committed
updates
1 parent f7a488d commit 76a0886

File tree

9 files changed

+255
-86
lines changed

9 files changed

+255
-86
lines changed

example/index.ts

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,25 @@
22
// deno-lint-ignore-file
33

44
import { Static, Runtime } from '@sinclair/parsebox'
5-
import { Type as T } from 'npm:@sinclair/typebox'
6-
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))
15-
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)
5+
import { Type as T, Static as S } from 'npm:@sinclair/typebox'
6+
7+
import { Module } from './typebox/interpreted/runtime.ts'
8+
import { Type } from './typebox/compiled/parser.ts'
9+
10+
// const Result = Module.Parse('Type',
11+
// 'Record<`${0|1}${0|1}${0|1}${0|1}${0|1}${0|1}${0|1}${0|1}`, { x: `hello${1|2}` }>'
12+
// )[0]
13+
14+
import { Syntax } from './typebox/interpreted/syntax.ts'
15+
16+
const K = Syntax('`${0|1}${0|1}${0|1}${0|1}${0|1}`')
17+
18+
const A = Syntax({ K }, `{ x: K }`)
19+
20+
function test(value: S<typeof A>) {
21+
22+
}
23+
24+
console.log(A)
25+
26+

example/typebox/compiled/module.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,40 @@ const GenericReference = Runtime.Tuple([
9999
// Reference
100100
// ------------------------------------------------------------------
101101
const Reference = Runtime.Ident()
102-
102+
// ------------------------------------------------------------------
103+
// TemplateText
104+
// ------------------------------------------------------------------
105+
const TemplateText = Runtime.Union([
106+
Runtime.Until('${'),
107+
Runtime.Until('`'),
108+
])
109+
// ------------------------------------------------------------------
110+
// TemplateInterpolate
111+
// ------------------------------------------------------------------
112+
const TemplateInterpolate = Runtime.Tuple([
113+
Runtime.Const('${'),
114+
Runtime.Ref('Type'),
115+
Runtime.Const('}')
116+
])
117+
// ------------------------------------------------------------------
118+
// TemplateBody
119+
// ------------------------------------------------------------------
120+
const TemplateBody = Runtime.Union([
121+
Runtime.Tuple([Runtime.Ref('TemplateText'), Runtime.Ref('TemplateInterpolate'), Runtime.Ref('TemplateBody')]),
122+
Runtime.Tuple([Runtime.Ref('TemplateText')]),
123+
])
124+
// ------------------------------------------------------------------
125+
// TemplateLiteral
126+
// ------------------------------------------------------------------
127+
const TemplateLiteral = Runtime.Tuple([
128+
Runtime.Const('`'),
129+
Runtime.Ref('TemplateBody'),
130+
Runtime.Const('`'),
131+
])
103132
// ------------------------------------------------------------------
104133
// Literal
105134
// ------------------------------------------------------------------
106-
const LiteralString = Runtime.String([SingleQuote, DoubleQuote, Tilde])
135+
const LiteralString = Runtime.String([SingleQuote, DoubleQuote])
107136
const LiteralNumber = Runtime.Number()
108137
const LiteralBoolean = Runtime.Union([Runtime.Const('true'), Runtime.Const('false')])
109138
const Literal = Runtime.Union([
@@ -177,6 +206,7 @@ const Base = Runtime.Union([
177206
Runtime.Ref('Object'),
178207
Runtime.Ref('Tuple'),
179208
Runtime.Ref('Literal'),
209+
Runtime.Ref('TemplateLiteral'),
180210
Runtime.Ref('Constructor'),
181211
Runtime.Ref('Function'),
182212
Runtime.Ref('Mapped'),
@@ -589,6 +619,10 @@ export const SyntaxModule = new Runtime.Module({
589619
KeywordSymbol,
590620
KeywordVoid,
591621
Keyword,
622+
TemplateInterpolate,
623+
TemplateBody,
624+
TemplateText,
625+
TemplateLiteral,
592626
LiteralString,
593627
LiteralNumber,
594628
LiteralBoolean,

example/typebox/interpreted/runtime.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,60 @@ function ReferenceMapping(result: string, context: T.TProperties) {
133133
return target
134134
}
135135
const Reference = Runtime.Ident((result, context) => ReferenceMapping(result, context))
136+
// ------------------------------------------------------------------
137+
// TemplateText
138+
// ------------------------------------------------------------------
139+
function TemplateTextMapping(input: string) {
140+
return T.Literal(input)
141+
}
142+
const TemplateText = Runtime.Union([
143+
Runtime.Until('${'),
144+
Runtime.Until('`'),
145+
], TemplateTextMapping)
146+
// ------------------------------------------------------------------
147+
// TemplateInterpolate
148+
// ------------------------------------------------------------------
149+
function TemplateInterpolateMapping(input: [unknown, unknown, unknown]) {
150+
return input[1]
151+
}
152+
const TemplateInterpolate = Runtime.Tuple([
153+
Runtime.Const('${'),
154+
Runtime.Ref('Type'),
155+
Runtime.Const('}')
156+
], TemplateInterpolateMapping)
157+
// ------------------------------------------------------------------
158+
// TemplateBody
159+
// ------------------------------------------------------------------
160+
function TemplateBodyMapping(input: [unknown] | [unknown, unknown, unknown]) {
161+
return (
162+
input.length === 3
163+
? [input[0], input[1], ...input[2] as unknown[]]
164+
: [input[0]]
165+
)
166+
}
167+
const TemplateBody = Runtime.Union([
168+
Runtime.Tuple([Runtime.Ref('TemplateText'), Runtime.Ref('TemplateInterpolate'), Runtime.Ref('TemplateBody')]),
169+
Runtime.Tuple([Runtime.Ref('TemplateText')]),
170+
], TemplateBodyMapping)
171+
// ------------------------------------------------------------------
172+
// TemplateLiteral
173+
// ------------------------------------------------------------------
174+
function TemplateLiteralMapping(input: [unknown, unknown, unknown]) {
175+
return T.TemplateLiteral(input[1] as T.TTemplateLiteralKind[])
176+
}
177+
const TemplateLiteral = Runtime.Tuple([
178+
Runtime.Const('`'),
179+
Runtime.Ref('TemplateBody'),
180+
Runtime.Const('`'),
181+
], TemplateLiteralMapping)
182+
136183
// ------------------------------------------------------------------
137184
// Literal
138185
// ------------------------------------------------------------------
139186
const Literal = Runtime.Union([
140187
Runtime.Union([Runtime.Const('true'), Runtime.Const('false')], value => T.Literal(value === 'true')),
141188
Runtime.Number(value => T.Literal(parseFloat(value))),
142-
Runtime.String([SingleQuote, DoubleQuote, Tilde], value => T.Literal(value))
189+
Runtime.String([SingleQuote, DoubleQuote], value => T.Literal(value))
143190
])
144191
// ------------------------------------------------------------------
145192
// Keyword
@@ -208,6 +255,7 @@ const Base = Runtime.Union([
208255
Runtime.Ref('Object'),
209256
Runtime.Ref('Tuple'),
210257
Runtime.Ref('Literal'),
258+
Runtime.Ref('TemplateLiteral'),
211259
Runtime.Ref('Constructor'),
212260
Runtime.Ref('Function'),
213261
Runtime.Ref('Mapped'),
@@ -630,12 +678,17 @@ const Date = Runtime.Const('Date', Runtime.As(T.Date()))
630678
// Uint8Array
631679
// ------------------------------------------------------------------
632680
const Uint8Array = Runtime.Const('Uint8Array', Runtime.As(T.Uint8Array()))
681+
633682
// ------------------------------------------------------------------
634683
// Module
635684
// ------------------------------------------------------------------
636685
export const Module = new Runtime.Module({
637686
GenericArgumentsList,
638687
GenericArguments,
688+
TemplateInterpolate,
689+
TemplateBody,
690+
TemplateText,
691+
TemplateLiteral,
639692
Literal,
640693
Keyword,
641694
KeyOf,

example/typebox/interpreted/static.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,56 @@ type Dereference<Context extends T.TProperties, Ref extends string> = (
9191
Ref extends keyof Context ? Context[Ref] : T.TRef<Ref>
9292
)
9393
// ------------------------------------------------------------------
94+
// TemplateText
95+
// ------------------------------------------------------------------
96+
interface TemplateTextMapping extends Static.IMapping {
97+
output: this['input'] extends string ? T.TLiteral<this['input']> : never
98+
}
99+
type TemplateText = Static.Union<[
100+
Static.Until<'${'>,
101+
Static.Until<'`'>,
102+
], TemplateTextMapping>
103+
// ------------------------------------------------------------------
104+
// TemplateInterpolate
105+
// ------------------------------------------------------------------
106+
interface TemplateInterpolateMapping extends Static.IMapping {
107+
output: this['input'] extends ['${', infer Type extends T.TSchema, '}']
108+
? Type
109+
: never
110+
}
111+
type TemplateInterpolate = Static.Tuple<[
112+
Static.Const<'${'>,
113+
Type,
114+
Static.Const<'}'>
115+
], TemplateInterpolateMapping>
116+
// ------------------------------------------------------------------
117+
// TemplateBody
118+
// ------------------------------------------------------------------
119+
interface TemplateBodyMapping extends Static.IMapping {
120+
output: (
121+
this['input'] extends [infer Text extends T.TSchema, infer Type extends T.TSchema, infer Rest extends T.TSchema[]] ? [Text, Type, ...Rest] :
122+
this['input'] extends [infer Text extends T.TSchema] ? [Text] :
123+
[]
124+
)
125+
}
126+
type TemplateBody = Static.Union<[
127+
Static.Tuple<[TemplateText, TemplateInterpolate, TemplateBody]>,
128+
Static.Tuple<[TemplateText]>,
129+
], TemplateBodyMapping>
130+
// ------------------------------------------------------------------
131+
// TemplateLiteral
132+
// ------------------------------------------------------------------
133+
interface TemplateLiteralMapping extends Static.IMapping {
134+
output: this['input'] extends ['`', infer Types extends T.TTemplateLiteralKind[], '`']
135+
? T.TTemplateLiteral<Types>
136+
: never
137+
}
138+
type TemplateLiteral = Static.Tuple<[
139+
Static.Const<'`'>,
140+
TemplateBody,
141+
Static.Const<'`'>,
142+
], TemplateLiteralMapping>
143+
// ------------------------------------------------------------------
94144
// GenericArguments
95145
// ------------------------------------------------------------------
96146
type GenericArgumentsContext<Args extends string[], Context extends T.TProperties, Result extends T.TProperties = {}> = (
@@ -154,7 +204,7 @@ interface LiteralStringMapping extends Static.IMapping {
154204
type Literal = Static.Union<[
155205
Static.Union<[Static.Const<'true'>, Static.Const<'false'>], LiteralBooleanMapping>,
156206
Static.Number<LiteralNumberMapping>,
157-
Static.String<[DoubleQuote, SingleQuote, Tilde], LiteralStringMapping>,
207+
Static.String<[DoubleQuote, SingleQuote], LiteralStringMapping>,
158208
]>
159209
// ------------------------------------------------------------------
160210
// Keyword
@@ -230,6 +280,7 @@ type Base = Static.Union<[
230280
Object,
231281
Tuple,
232282
Literal,
283+
TemplateLiteral,
233284
Function,
234285
Constructor,
235286
Mapped,

readme.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ License: MIT
6666
6767
- [Combinators](#Combinators)
6868
- [Const](#Const)
69+
- [Until](#Until)
6970
- [Tuple](#Tuple)
7071
- [Union](#Union)
7172
- [Array](#Array)
@@ -106,6 +107,28 @@ const T = Runtime.Const('X') // const T = {
106107
const R = Runtime.Parse(T, 'X Y Z') // const R = ['X', ' Y Z']
107108
```
108109

110+
111+
### Until
112+
113+
The Until combinator parses all characters up unto the specified string. This parser parser will leave the specified string unconsumed. If the specified string is not found, this parser will fail.
114+
115+
**BNF**
116+
117+
```bnf
118+
<T> ::= ? any character until 'Z' ?
119+
```
120+
121+
**TypeScript**
122+
123+
```typescript
124+
const T = Runtime.Until('Z') // const T = {
125+
// type: 'Until',
126+
// value: 'X'
127+
// }
128+
129+
const R = Runtime.Parse(T, 'X Y Z') // const R = ['X Y ', 'Z']
130+
```
131+
109132
### Tuple
110133

111134
The Tuple parser matches a sequence of parsers, with an empty tuple representing Epsilon (the empty production).

src/compile/func/func.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ function FromConst(options: Options, name: string, value: string): string {
8383
return `Runtime.Token.Const('${Escape(value)}', input)`
8484
}
8585
// ------------------------------------------------------------------
86+
// Const
87+
// ------------------------------------------------------------------
88+
function FromUntil(options: Options, name: string, value: string): string {
89+
return `Runtime.Token.Until('${Escape(value)}', input)`
90+
}
91+
// ------------------------------------------------------------------
8692
// Ident
8793
// ------------------------------------------------------------------
8894
function FromIdent(options: Options, name: string): string {
@@ -119,6 +125,7 @@ function FromParser(options: Options, name: string, parser: Runtime.IParser): st
119125
Runtime.IsOptional(parser) ? FromOptional(options, name, parser) :
120126
Runtime.IsString(parser) ? FromString(options, name, parser.options) :
121127
Runtime.IsConst(parser) ? FromConst(options, name, parser.value) :
128+
Runtime.IsUntil(parser) ? FromUntil(options, name, parser.value) :
122129
Runtime.IsRef(parser) ? FromRef(options, name, parser.ref) :
123130
Runtime.IsIdent(parser) ? FromIdent(options, name) :
124131
Runtime.IsNumber(parser) ? FromNumber(options, name) :

src/compile/type/type.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ function FromConst(options: Options, name: string, value: string): string {
8585
return `Static.Token.Const<'${Escape(value)}', Input>`
8686
}
8787
// ------------------------------------------------------------------
88+
// Until
89+
// ------------------------------------------------------------------
90+
function FromUntil(options: Options, name: string, value: string): string {
91+
return `Static.Token.Until<'${Escape(value)}', Input>`
92+
}
93+
// ------------------------------------------------------------------
8894
// Ident
8995
// ------------------------------------------------------------------
9096
function FromIdent(options: Options, name: string): string {
@@ -121,6 +127,7 @@ function FromParser(options: Options, name: string, parser: Runtime.IParser): st
121127
Runtime.IsOptional(parser) ? FromOptional(options, name, parser) :
122128
Runtime.IsString(parser) ? FromString(options, name, parser.options) :
123129
Runtime.IsConst(parser) ? FromConst(options, name, parser.value) :
130+
Runtime.IsUntil(parser) ? FromUntil(options, name, parser.value) :
124131
Runtime.IsRef(parser) ? FromRef(options, name, parser.ref) :
125132
Runtime.IsIdent(parser) ? FromIdent(options, name) :
126133
Runtime.IsNumber(parser) ? FromNumber(options, name) :

0 commit comments

Comments
 (0)