diff --git a/example/typebox/interpreted/runtime.ts b/example/typebox/interpreted/runtime.ts index 3d9ab01..18344db 100644 --- a/example/typebox/interpreted/runtime.ts +++ b/example/typebox/interpreted/runtime.ts @@ -139,10 +139,7 @@ const Reference = Runtime.Ident((result, context) => ReferenceMapping(result, co function TemplateTextMapping(input: string) { return T.Literal(input) } -const TemplateText = Runtime.Union([ - Runtime.Until('${'), - Runtime.Until('`'), -], TemplateTextMapping) +const TemplateText = Runtime.Until(['`', '${'], TemplateTextMapping) // ------------------------------------------------------------------ // TemplateInterpolate // ------------------------------------------------------------------ diff --git a/readme.md b/readme.md index 8addabd..d76109b 100644 --- a/readme.md +++ b/readme.md @@ -189,20 +189,20 @@ const R3 = Runtime.Parse(T, 'Y Z') // const R3 = [[], 'Y Z'] ### Until -The Until combinator parses all characters up to (but not including) the specified string. The specified string remains unconsumed in the input. If the string is not found, parsing fails. +The Until combinator will parse characters up to (but not including) one of the specified sentinel string values. If a sentinel value is not found, parsing fails. **BNF** ```bnf - ::= ? any character until 'Z' ? + ::= ? any character until ['Z'] ? ``` **TypeScript** ```typescript -const T = Runtime.Until('Z') // const T = { +const T = Runtime.Until(['Z']) // const T = { // type: 'Until', - // value: 'Z' + // values: ['Z'] // } const R = Runtime.Parse(T, 'X Y Z') // const R = ['X Y ', 'Z'] diff --git a/src/compile/func/func.ts b/src/compile/func/func.ts index 34dd056..d252fe0 100644 --- a/src/compile/func/func.ts +++ b/src/compile/func/func.ts @@ -85,8 +85,9 @@ function FromConst(options: Options, name: string, value: string): string { // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ -function FromUntil(options: Options, name: string, value: string): string { - return `Runtime.Token.Until('${Escape(value)}', input)` +function FromUntil(options: Options, name: string, values: string[]): string { + const escaped = values.map(value => `'${Escape(value)}'`) + return `Runtime.Token.Until(${escaped.join(', ')}, input)` } // ------------------------------------------------------------------ // Ident @@ -125,7 +126,7 @@ function FromParser(options: Options, name: string, parser: Runtime.IParser): st Runtime.IsOptional(parser) ? FromOptional(options, name, parser) : Runtime.IsString(parser) ? FromString(options, name, parser.options) : Runtime.IsConst(parser) ? FromConst(options, name, parser.value) : - Runtime.IsUntil(parser) ? FromUntil(options, name, parser.value) : + Runtime.IsUntil(parser) ? FromUntil(options, name, parser.values) : Runtime.IsRef(parser) ? FromRef(options, name, parser.ref) : Runtime.IsIdent(parser) ? FromIdent(options, name) : Runtime.IsNumber(parser) ? FromNumber(options, name) : diff --git a/src/compile/type/type.ts b/src/compile/type/type.ts index d7ef668..e54b707 100644 --- a/src/compile/type/type.ts +++ b/src/compile/type/type.ts @@ -87,8 +87,9 @@ function FromConst(options: Options, name: string, value: string): string { // ------------------------------------------------------------------ // Until // ------------------------------------------------------------------ -function FromUntil(options: Options, name: string, value: string): string { - return `Static.Token.Until<'${Escape(value)}', Input>` +function FromUntil(options: Options, name: string, values: string[]): string { + const escaped = values.map(value => `'${Escape(value)}'`) + return `Static.Token.Until<${escaped.join(', ')}, Input>` } // ------------------------------------------------------------------ // Ident @@ -127,7 +128,7 @@ function FromParser(options: Options, name: string, parser: Runtime.IParser): st Runtime.IsOptional(parser) ? FromOptional(options, name, parser) : Runtime.IsString(parser) ? FromString(options, name, parser.options) : Runtime.IsConst(parser) ? FromConst(options, name, parser.value) : - Runtime.IsUntil(parser) ? FromUntil(options, name, parser.value) : + Runtime.IsUntil(parser) ? FromUntil(options, name, parser.values) : Runtime.IsRef(parser) ? FromRef(options, name, parser.ref) : Runtime.IsIdent(parser) ? FromIdent(options, name) : Runtime.IsNumber(parser) ? FromNumber(options, name) : diff --git a/src/runtime/parse.ts b/src/runtime/parse.ts index 087c9a5..cfc2c67 100644 --- a/src/runtime/parse.ts +++ b/src/runtime/parse.ts @@ -66,12 +66,6 @@ function ParseConst(value: Value, code: string, context: u return Token.Const(value, code) as never } // ------------------------------------------------------------------ -// Until -// ------------------------------------------------------------------ -function ParseUntil(value: Value, code: string, context: unknown): [] | [Value, string] { - return Token.Until(value, code) as never -} -// ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ function ParseIdent(code: string, _context: unknown): [] | [string, string] { @@ -129,6 +123,12 @@ function ParseUnion(values: [...Values], code: string, context: unknown): [] | [string, string] { + return Token.Until(values, code) as never +} +// ------------------------------------------------------------------ // Parser // ------------------------------------------------------------------ function ParseParser(moduleProperties: Types.IModuleProperties, parser: Parser, code: string, context: unknown): [] | [Types.StaticParser, string] { @@ -143,7 +143,7 @@ function ParseParser(moduleProperties: Types.IModu Types.IsString(parser) ? ParseString(parser.options, code, context) : Types.IsTuple(parser) ? ParseTuple(moduleProperties, parser.parsers, code, context) : Types.IsUnion(parser) ? ParseUnion(moduleProperties, parser.parsers, code, context) : - Types.IsUntil(parser) ? ParseUntil(parser.value, code, context) : + Types.IsUntil(parser) ? ParseUntil(parser.values, code, context) : [] ) return (result.length === 2 ? [parser.mapping(result[0], context), result[1]] : result) as never diff --git a/src/runtime/token.ts b/src/runtime/token.ts index 62361e0..ae29a6b 100644 --- a/src/runtime/token.ts +++ b/src/runtime/token.ts @@ -233,18 +233,22 @@ export function String(options: string[], input: string) { // ------------------------------------------------------------------ // Until // ------------------------------------------------------------------ -function UntilStartsWith(value: string, input: string) { - return input.startsWith(value) -} -export function Until(value: string, input: string, result: string = ''): [] | [string, string] { +function UntilStartsWith(value: string[], input: string): boolean { + const [left, ...right] = value + return (typeof left === 'string') + ? input.startsWith(left) + ? true + : UntilStartsWith(right, input) + : false +} +export function Until(value: string[], input: string, result: string = ''): [] | [string, string] { return ( - input === '' ? [] : (() => { - return UntilStartsWith(value, input) - ? [result, input] - : (() => { - const [left, right] = [input.slice(0, 1), input.slice(1)] - return Until(value, right, `${result}${left}`) - })() + input === '' ? [] : + UntilStartsWith(value, input) + ? [result, input] + : (() => { + const [left, right] = [input.slice(0, 1), input.slice(1)] + return Until(value, right, `${result}${left}`) })() ) } \ No newline at end of file diff --git a/src/runtime/types.ts b/src/runtime/types.ts index d89b7d6..8b67023 100644 --- a/src/runtime/types.ts +++ b/src/runtime/types.ts @@ -324,22 +324,22 @@ export function IsUnion(value: unknown): value is IUnion { // ------------------------------------------------------------------ export interface IUntil extends IParser { type: 'Until' - value: string + values: string[] } /** `[TERM]` Creates a Until Parser */ -export function Until>(value: string, mapping: Mapping): IUntil +export function Until>(values: string[], mapping: Mapping): IUntil /** `[TERM]` Creates a Until Parser */ -export function Until(value: string): IUntil +export function Until(values: string[]): IUntil /** `[TERM]` Creates a Until Parser */ export function Until(...args: unknown[]): never { - const [value, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] - return { type: 'Until', value, mapping } as never + const [values, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] + return { type: 'Until', values, mapping } as never } /** Returns true if the value is a Until Parser */ export function IsUntil(value: unknown): value is IUntil { return Guard.IsObject(value) && Guard.HasPropertyKey(value, 'type') - && Guard.HasPropertyKey(value, 'value') + && Guard.HasPropertyKey(value, 'values') && Guard.IsEqual(value.type, 'Until') - && Guard.IsString(value.value) + && Guard.IsArray(value.values) } \ No newline at end of file diff --git a/src/static/parse.ts b/src/static/parse.ts index e2e8b0d..494941a 100644 --- a/src/static/parse.ts +++ b/src/static/parse.ts @@ -56,14 +56,6 @@ type ConstParser = ( - Tokens.Until extends [infer Match extends string, infer Rest extends string] - ? [Match, Rest] - : [] -) -// ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ type IdentParser = ( @@ -116,6 +108,14 @@ type UnionParser = ( + Tokens.Until extends [infer Match extends string, infer Rest extends string] + ? [Match, Rest] + : [] +) +// ------------------------------------------------------------------ // Parse // ------------------------------------------------------------------ type ParseCode = ( @@ -128,7 +128,7 @@ type ParseCode ? StringParser : Parser extends Types.Tuple ? TupleParser : Parser extends Types.Union ? UnionParser : - Parser extends Types.Until ? UntilParser : + Parser extends Types.Until ? UntilParser : [] ) type ParseMapping = ( diff --git a/src/static/token.ts b/src/static/token.ts index f4ff5d2..443ce18 100644 --- a/src/static/token.ts +++ b/src/static/token.ts @@ -204,14 +204,18 @@ export type Ident = NextIdent> // ------------------------------------------------------------------ // Until // ------------------------------------------------------------------ -type UntilStartsWith = ( - Input extends `${Value}${string}` ? true : false +type UntilStartsWith = ( + Values extends [infer Left extends string, ...infer Right extends string[]] + ? Input extends `${Left}${string}` + ? true + : UntilStartsWith + : false ) -export type Until = ( +export type Until = ( Input extends `` ? [] : - UntilStartsWith extends true + UntilStartsWith extends true ? [Result, Input] : Input extends `${infer Left extends string}${infer Right extends string}` - ? Until + ? Until : never ) \ No newline at end of file diff --git a/src/static/types.ts b/src/static/types.ts index 7aaca37..fea46f7 100644 --- a/src/static/types.ts +++ b/src/static/types.ts @@ -88,25 +88,24 @@ export interface Const extends IParser { +export interface Until extends IParser { type: 'Until' - value: Value + values: Values } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ -/** Creates an Ident Parser. */ +/** Creates an Ident Parser */ export interface Ident extends IParser { type: 'Ident' } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ -/** Creates a Number Parser. */ +/** Creates a Number Parser */ export interface Number extends IParser { type: 'Number' } - // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ diff --git a/tasks.ts b/tasks.ts index bcf1316..c092562 100644 --- a/tasks.ts +++ b/tasks.ts @@ -34,7 +34,7 @@ Task.run('build', () => Task.build('src', { packageJson: { name: '@sinclair/parsebox', description: 'Parser Combinators in the TypeScript Type System', - version: '0.9.3', + version: '0.9.4', keywords: ['typescript', 'parser', 'combinator'], license: 'MIT', author: 'sinclairzx81', diff --git a/test/__tests__/runtime/parse.ts b/test/__tests__/runtime/parse.ts index 75f2322..3cf5bd3 100644 --- a/test/__tests__/runtime/parse.ts +++ b/test/__tests__/runtime/parse.ts @@ -25,11 +25,17 @@ Deno.test('Const', () => { // Until // ---------------------------------------------------------------- Deno.test('Until', () => { - Assert(Runtime.Parse(Runtime.Until('A'), ''), []) - Assert(Runtime.Parse(Runtime.Until('A'), 'A'), ['', 'A']) - Assert(Runtime.Parse(Runtime.Until('A'), ' A'), [' ', 'A']) - Assert(Runtime.Parse(Runtime.Until('A'), ' A '), [' ', 'A ']) + Assert(Runtime.Parse(Runtime.Until(['A']), ''), []) + Assert(Runtime.Parse(Runtime.Until(['A']), 'A'), ['', 'A']) + Assert(Runtime.Parse(Runtime.Until(['A']), ' A'), [' ', 'A']) + Assert(Runtime.Parse(Runtime.Until(['A']), ' A '), [' ', 'A ']) + + Assert(Runtime.Parse(Runtime.Until(['A', 'B']), ''), []) + Assert(Runtime.Parse(Runtime.Until(['A', 'B']), 'BA'), ['', 'BA']) + Assert(Runtime.Parse(Runtime.Until(['A', 'B']), ' BA'), [' ', 'BA']) + Assert(Runtime.Parse(Runtime.Until(['A', 'B']), ' BA '), [' ', 'BA ']) }) + // ---------------------------------------------------------------- // Ident // ---------------------------------------------------------------- diff --git a/test/__tests__/runtime/token.ts b/test/__tests__/runtime/token.ts index dd4bc7e..e4c8560 100644 --- a/test/__tests__/runtime/token.ts +++ b/test/__tests__/runtime/token.ts @@ -93,87 +93,103 @@ Deno.test('Const: Newline-Multi-Whitespace', () => { // Until // ------------------------------------------------------------------ Deno.test('Until: Empty', () => { - Assert(Runtime.Token.Until('', ''), []) - Assert(Runtime.Token.Until('', 'A'), ['', 'A']) - Assert(Runtime.Token.Until('', ' A'), ['', ' A']) + Assert(Runtime.Token.Until([''], ''), []) + Assert(Runtime.Token.Until([''], 'A'), ['', 'A']) + Assert(Runtime.Token.Until([''], ' A'), ['', ' A']) }) Deno.test('Until: Single-Char', () => { - Assert(Runtime.Token.Until('A', 'A'), ['', 'A']) - Assert(Runtime.Token.Until('A', 'A '), ['', 'A ']) - Assert(Runtime.Token.Until('A', 'AA'), ['', 'AA']) - Assert(Runtime.Token.Until('A', 'AA '), ['', 'AA ']) + Assert(Runtime.Token.Until(['A'], 'A'), ['', 'A']) + Assert(Runtime.Token.Until(['A'], 'A '), ['', 'A ']) + Assert(Runtime.Token.Until(['A'], 'AA'), ['', 'AA']) + Assert(Runtime.Token.Until(['A'], 'AA '), ['', 'AA ']) }) Deno.test('Until: Multi-Char', () => { - Assert(Runtime.Token.Until('AB', 'AB'), ['', 'AB']) - Assert(Runtime.Token.Until('AB', 'AB '), ['', 'AB ']) - Assert(Runtime.Token.Until('AB', 'ABA'), ['', 'ABA']) - Assert(Runtime.Token.Until('AB', 'ABA '), ['', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], 'AB'), ['', 'AB']) + Assert(Runtime.Token.Until(['AB'], 'AB '), ['', 'AB ']) + Assert(Runtime.Token.Until(['AB'], 'ABA'), ['', 'ABA']) + Assert(Runtime.Token.Until(['AB'], 'ABA '), ['', 'ABA ']) }) Deno.test('Until: Single-Char -> Ignore-Whitespace', () => { - Assert(Runtime.Token.Until('A', ' A'), [' ', 'A']) - Assert(Runtime.Token.Until('A', ' A '), [' ', 'A ']) - Assert(Runtime.Token.Until('A', ' AA'), [' ', 'AA']) - Assert(Runtime.Token.Until('A', ' AA '), [' ', 'AA ']) - Assert(Runtime.Token.Until('A', '\nAA '), ['\n', 'AA ']) - Assert(Runtime.Token.Until('A', ' \nAA '), [' \n', 'AA ']) - Assert(Runtime.Token.Until('A', '\n AA '), ['\n ', 'AA ']) - Assert(Runtime.Token.Until('A', ' \n AA '), [' \n ', 'AA ']) + Assert(Runtime.Token.Until(['A'], ' A'), [' ', 'A']) + Assert(Runtime.Token.Until(['A'], ' A '), [' ', 'A ']) + Assert(Runtime.Token.Until(['A'], ' AA'), [' ', 'AA']) + Assert(Runtime.Token.Until(['A'], ' AA '), [' ', 'AA ']) + Assert(Runtime.Token.Until(['A'], '\nAA '), ['\n', 'AA ']) + Assert(Runtime.Token.Until(['A'], ' \nAA '), [' \n', 'AA ']) + Assert(Runtime.Token.Until(['A'], '\n AA '), ['\n ', 'AA ']) + Assert(Runtime.Token.Until(['A'], ' \n AA '), [' \n ', 'AA ']) }) Deno.test('Until: Multi-Char -> Ignore-Whitespace', () => { - Assert(Runtime.Token.Until('AB', ' AB'), [' ', 'AB']) - Assert(Runtime.Token.Until('AB', ' AB '), [' ', 'AB ']) - Assert(Runtime.Token.Until('AB', ' ABA'), [' ', 'ABA']) - Assert(Runtime.Token.Until('AB', ' ABA '), [' ', 'ABA ']) - Assert(Runtime.Token.Until('AB', '\nABA '), ['\n', 'ABA ']) - Assert(Runtime.Token.Until('AB', ' \nABA '), [' \n', 'ABA ']) - Assert(Runtime.Token.Until('AB', '\n ABA '), ['\n ', 'ABA ']) - Assert(Runtime.Token.Until('AB', ' \n ABA '), [' \n ', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], ' AB'), [' ', 'AB']) + Assert(Runtime.Token.Until(['AB'], ' AB '), [' ', 'AB ']) + Assert(Runtime.Token.Until(['AB'], ' ABA'), [' ', 'ABA']) + Assert(Runtime.Token.Until(['AB'], ' ABA '), [' ', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], '\nABA '), ['\n', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], ' \nABA '), [' \n', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], '\n ABA '), ['\n ', 'ABA ']) + Assert(Runtime.Token.Until(['AB'], ' \n ABA '), [' \n ', 'ABA ']) }) Deno.test('Until: Single-Whitespace', () => { - Assert(Runtime.Token.Until(' ', ''), []) - Assert(Runtime.Token.Until(' ', ' '), ['', ' ']) - Assert(Runtime.Token.Until(' ', ' A'), ['', ' A']) - Assert(Runtime.Token.Until(' ', ' A '), ['', ' A ']) - Assert(Runtime.Token.Until(' ', ' AA'), ['', ' AA']) - Assert(Runtime.Token.Until(' ', ' AA '), ['', ' AA ']) + Assert(Runtime.Token.Until([' '], ''), []) + Assert(Runtime.Token.Until([' '], ' '), ['', ' ']) + Assert(Runtime.Token.Until([' '], ' A'), ['', ' A']) + Assert(Runtime.Token.Until([' '], ' A '), ['', ' A ']) + Assert(Runtime.Token.Until([' '], ' AA'), ['', ' AA']) + Assert(Runtime.Token.Until([' '], ' AA '), ['', ' AA ']) }) Deno.test('Until: Multi-Whitespace', () => { - Assert(Runtime.Token.Until(' ', ''), []) - Assert(Runtime.Token.Until(' ', ' '), []) - Assert(Runtime.Token.Until(' ', ' A'), ['', ' A']) - Assert(Runtime.Token.Until(' ', ' A '), ['', ' A ']) - Assert(Runtime.Token.Until(' ', ' AA'), ['', ' AA']) - Assert(Runtime.Token.Until(' ', ' AA '), ['', ' AA ']) + Assert(Runtime.Token.Until([' '], ''), []) + Assert(Runtime.Token.Until([' '], ' '), []) + Assert(Runtime.Token.Until([' '], ' A'), ['', ' A']) + Assert(Runtime.Token.Until([' '], ' A '), ['', ' A ']) + Assert(Runtime.Token.Until([' '], ' AA'), ['', ' AA']) + Assert(Runtime.Token.Until([' '], ' AA '), ['', ' AA ']) }) Deno.test('Until: Newline', () => { - Assert(Runtime.Token.Until('\n', ''), []) - Assert(Runtime.Token.Until('\n', ' '), []) - Assert(Runtime.Token.Until('\n', '\nA'), ['', '\nA']) - Assert(Runtime.Token.Until('\n', ' \nA '), [' ', '\nA ']) - Assert(Runtime.Token.Until('\n', ' \nAA'), [' ', '\nAA']) - Assert(Runtime.Token.Until('\n', ' \nAA '), [' ', '\nAA ']) + Assert(Runtime.Token.Until(['\n'], ''), []) + Assert(Runtime.Token.Until(['\n'], ' '), []) + Assert(Runtime.Token.Until(['\n'], '\nA'), ['', '\nA']) + Assert(Runtime.Token.Until(['\n'], ' \nA '), [' ', '\nA ']) + Assert(Runtime.Token.Until(['\n'], ' \nAA'), [' ', '\nAA']) + Assert(Runtime.Token.Until(['\n'], ' \nAA '), [' ', '\nAA ']) }) Deno.test('Until: Newline-Single-Whitespace', () => { - Assert(Runtime.Token.Until('\n ', ''), []) - Assert(Runtime.Token.Until('\n ', ' '), []) - Assert(Runtime.Token.Until('\n ', '\nA'), []) - Assert(Runtime.Token.Until('\n ', ' \nA '), []) - Assert(Runtime.Token.Until('\n ', ' \nAA'), []) - Assert(Runtime.Token.Until('\n ', ' \nAA '), []) - Assert(Runtime.Token.Until('\n ', '\n A'), ['', '\n A']) - Assert(Runtime.Token.Until('\n ', ' \n A '), [' ', '\n A ']) - Assert(Runtime.Token.Until('\n ', ' \n AA'), [' ', '\n AA']) - Assert(Runtime.Token.Until('\n ', ' \n AA '), [' ', '\n AA ']) + Assert(Runtime.Token.Until(['\n '], ''), []) + Assert(Runtime.Token.Until(['\n '], ' '), []) + Assert(Runtime.Token.Until(['\n '], '\nA'), []) + Assert(Runtime.Token.Until(['\n '], ' \nA '), []) + Assert(Runtime.Token.Until(['\n '], ' \nAA'), []) + Assert(Runtime.Token.Until(['\n '], ' \nAA '), []) + Assert(Runtime.Token.Until(['\n '], '\n A'), ['', '\n A']) + Assert(Runtime.Token.Until(['\n '], ' \n A '), [' ', '\n A ']) + Assert(Runtime.Token.Until(['\n '], ' \n AA'), [' ', '\n AA']) + Assert(Runtime.Token.Until(['\n '], ' \n AA '), [' ', '\n AA ']) }) Deno.test('Until: Newline-Multi-Whitespace', () => { - Assert(Runtime.Token.Until('\n ', ''), []) - Assert(Runtime.Token.Until('\n ', ' '), []) - Assert(Runtime.Token.Until('\n ', '\nA'), []) - Assert(Runtime.Token.Until('\n ', ' \nA '), []) - Assert(Runtime.Token.Until('\n ', ' \nAA'), []) - Assert(Runtime.Token.Until('\n ', ' \nAA '), []) - Assert(Runtime.Token.Until('\n ', '\n A'), ['', '\n A']) - Assert(Runtime.Token.Until('\n ', ' \n A '), [' ', '\n A ']) - Assert(Runtime.Token.Until('\n ', ' \n AA'), [' ', '\n AA']) - Assert(Runtime.Token.Until('\n ', ' \n AA '), [' ', '\n AA ']) + Assert(Runtime.Token.Until(['\n '], ''), []) + Assert(Runtime.Token.Until(['\n '], ' '), []) + Assert(Runtime.Token.Until(['\n '], '\nA'), []) + Assert(Runtime.Token.Until(['\n '], ' \nA '), []) + Assert(Runtime.Token.Until(['\n '], ' \nAA'), []) + Assert(Runtime.Token.Until(['\n '], ' \nAA '), []) + Assert(Runtime.Token.Until(['\n '], '\n A'), ['', '\n A']) + Assert(Runtime.Token.Until(['\n '], ' \n A '), [' ', '\n A ']) + Assert(Runtime.Token.Until(['\n '], ' \n AA'), [' ', '\n AA']) + Assert(Runtime.Token.Until(['\n '], ' \n AA '), [' ', '\n AA ']) +}) + +Deno.test('Until: Multi Sentinal Test', () => { + Assert(Runtime.Token.Until(['A', 'B'], ''), []) + Assert(Runtime.Token.Until(['A', 'B'], 'A'), ['', 'A']) + Assert(Runtime.Token.Until(['A', 'B'], 'B'), ['', 'B']) + Assert(Runtime.Token.Until(['A', 'B'], 'AB'), ['', 'AB']) + Assert(Runtime.Token.Until(['A', 'B'], 'BA'), ['', 'BA']) + Assert(Runtime.Token.Until(['A', 'B'], ' AB'), [' ', 'AB']) + Assert(Runtime.Token.Until(['A', 'B'], ' BA'), [' ', 'BA']) + Assert(Runtime.Token.Until(['A', ' B'], ' BA'), [' ', ' BA']) + Assert(Runtime.Token.Until([' A', 'B'], ' BA'), [' ', 'BA']) + Assert(Runtime.Token.Until(['B', 'A'], ' AB'), [' ', 'AB']) + Assert(Runtime.Token.Until(['B', 'A'], ' BA'), [' ', 'BA']) + Assert(Runtime.Token.Until(['B', ' A'], ' BA'), [' ', 'BA']) + Assert(Runtime.Token.Until([' B', 'A'], ' BA'), [' ', ' BA']) }) \ No newline at end of file diff --git a/test/__tests__/static/parse.ts b/test/__tests__/static/parse.ts index 235efa5..671809d 100644 --- a/test/__tests__/static/parse.ts +++ b/test/__tests__/static/parse.ts @@ -24,10 +24,16 @@ Assert, ' A '>, ['A', ' ']>() // ------------------------------------------------------------------ // Until // ------------------------------------------------------------------ -Assert, ''>, []>() -Assert, 'A'>, ['', 'A']>() -Assert, ' A'>, [' ', 'A']>() -Assert, ' A '>, [' ', 'A ']>() +Assert, ''>, []>() +Assert, 'A'>, ['', 'A']>() +Assert, ' A'>, [' ', 'A']>() +Assert, ' A '>, [' ', 'A ']>() + +Assert, ''>, []> +Assert, 'BA'>, ['', 'BA']> +Assert, ' BA'>, [' ', 'BA']> +Assert, ' BA '>, [' ', 'BA ']> + // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ diff --git a/test/__tests__/static/token.ts b/test/__tests__/static/token.ts index 3b0f72f..b99ef42 100644 --- a/test/__tests__/static/token.ts +++ b/test/__tests__/static/token.ts @@ -110,104 +110,122 @@ Assert, ['\n ', 'AA ']>() // ------------------------------------------------------------------ // Until: Empty // ------------------------------------------------------------------ -Assert, []> -Assert, ['', 'A']> -Assert, ['', ' A']> +Assert, []> +Assert, ['', 'A']> +Assert, ['', ' A']> // ------------------------------------------------------------------ // Until: Single-Char // ------------------------------------------------------------------ -Assert, ['', 'A']> -Assert, ['', 'A ']> -Assert, ['', 'AA']> -Assert, ['', 'AA ']> +Assert, ['', 'A']> +Assert, ['', 'A ']> +Assert, ['', 'AA']> +Assert, ['', 'AA ']> // ------------------------------------------------------------------ // Until: Multi-Char // ------------------------------------------------------------------ -Assert, ['', 'AB']> -Assert, ['', 'AB ']> -Assert, ['', 'ABA']> -Assert, ['', 'ABA ']> +Assert, ['', 'AB']> +Assert, ['', 'AB ']> +Assert, ['', 'ABA']> +Assert, ['', 'ABA ']> // ------------------------------------------------------------------ // Until: Single-Char -> Ignore-Whitespace // ------------------------------------------------------------------ -Assert, [' ', 'A']> -Assert, [' ', 'A ']> -Assert, [' ', 'AA']> -Assert, [' ', 'AA ']> -Assert, ['\n', 'AA ']> -Assert, [' \n', 'AA ']> -Assert, ['\n ', 'AA ']> -Assert, [' \n ', 'AA ']> +Assert, [' ', 'A']> +Assert, [' ', 'A ']> +Assert, [' ', 'AA']> +Assert, [' ', 'AA ']> +Assert, ['\n', 'AA ']> +Assert, [' \n', 'AA ']> +Assert, ['\n ', 'AA ']> +Assert, [' \n ', 'AA ']> // ------------------------------------------------------------------ // Until: Multi-Char -> Ignore-Whitespace // ------------------------------------------------------------------ -Assert, [' ', 'AB']> -Assert, [' ', 'AB ']> -Assert, [' ', 'ABA']> -Assert, [' ', 'ABA ']> -Assert, ['\n', 'ABA ']> -Assert, [' \n', 'ABA ']> -Assert, ['\n ', 'ABA ']> -Assert, [' \n ', 'ABA ']> +Assert, [' ', 'AB']> +Assert, [' ', 'AB ']> +Assert, [' ', 'ABA']> +Assert, [' ', 'ABA ']> +Assert, ['\n', 'ABA ']> +Assert, [' \n', 'ABA ']> +Assert, ['\n ', 'ABA ']> +Assert, [' \n ', 'ABA ']> // ------------------------------------------------------------------ // Until: Single-Whitespace // ------------------------------------------------------------------ -Assert, []> -Assert, ['', ' ']> -Assert, ['', ' A']> -Assert, ['', ' A ']> -Assert, ['', ' AA']> -Assert, ['', ' AA ']> +Assert, []> +Assert, ['', ' ']> +Assert, ['', ' A']> +Assert, ['', ' A ']> +Assert, ['', ' AA']> +Assert, ['', ' AA ']> // ------------------------------------------------------------------ // Until: Multi-Whitespace // ------------------------------------------------------------------ -Assert, []> -Assert, []> -Assert, ['', ' A']> -Assert, ['', ' A ']> -Assert, ['', ' AA']> -Assert, ['', ' AA ']> +Assert, []> +Assert, []> +Assert, ['', ' A']> +Assert, ['', ' A ']> +Assert, ['', ' AA']> +Assert, ['', ' AA ']> // ------------------------------------------------------------------ // Until: Newline // ------------------------------------------------------------------ -Assert, []> -Assert, []> -Assert, ['', '\nA']> -Assert, [' ', '\nA ']> -Assert, [' ', '\nAA']> -Assert, [' ', '\nAA ']> +Assert, []> +Assert, []> +Assert, ['', '\nA']> +Assert, [' ', '\nA ']> +Assert, [' ', '\nAA']> +Assert, [' ', '\nAA ']> // ------------------------------------------------------------------ // Until: Newline-Single-Whitespace // ------------------------------------------------------------------ -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, ['', '\n A']> -Assert, [' ', '\n A ']> -Assert, [' ', '\n AA']> -Assert, [' ', '\n AA ']> +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, ['', '\n A']> +Assert, [' ', '\n A ']> +Assert, [' ', '\n AA']> +Assert, [' ', '\n AA ']> // ------------------------------------------------------------------ // Until: Newline-Multi-Whitespace // ------------------------------------------------------------------ -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, []> -Assert, ['', '\n A']> -Assert, [' ', '\n A ']> -Assert, [' ', '\n AA']> -Assert, [' ', '\n AA ']> \ No newline at end of file +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, []> +Assert, ['', '\n A']> +Assert, [' ', '\n A ']> +Assert, [' ', '\n AA']> +Assert, [' ', '\n AA ']> + +// ------------------------------------------------------------------ +// Until: Multi Sentinal Test +// ------------------------------------------------------------------ +Assert, []> +Assert, ['', 'A']> +Assert, ['', 'B']> +Assert, ['', 'AB']> +Assert, ['', 'BA']> +Assert, [' ', 'AB']> +Assert, [' ', 'BA']> +Assert, [' ', ' BA']> +Assert, [' ', 'BA']> +Assert, [' ', 'AB']> +Assert, [' ', 'BA']> +Assert, [' ', 'BA']> +Assert, [' ', ' BA']> +