feat: add int/float to types

This commit is contained in:
hypercross 2026-04-04 17:05:25 +08:00
parent 8bf28c8aed
commit 4146fda348
4 changed files with 78 additions and 1 deletions

View File

@ -74,6 +74,28 @@ class Parser {
return { type: 'number' }; return { type: 'number' };
} }
if (this.consumeStr('int')) {
if (this.consumeStr('[')) {
this.skipWhitespace();
if (!this.consumeStr(']')) {
throw new ParseError('Expected ]', this.pos);
}
return { type: 'array', element: { type: 'int' } };
}
return { type: 'int' };
}
if (this.consumeStr('float')) {
if (this.consumeStr('[')) {
this.skipWhitespace();
if (!this.consumeStr(']')) {
throw new ParseError('Expected ]', this.pos);
}
return { type: 'array', element: { type: 'float' } };
}
return { type: 'float' };
}
if (this.consumeStr('boolean')) { if (this.consumeStr('boolean')) {
if (this.consumeStr('[')) { if (this.consumeStr('[')) {
this.skipWhitespace(); this.skipWhitespace();

View File

@ -5,12 +5,17 @@ console.log('=== Testing Schema Parser ===\n');
const testCases = [ const testCases = [
{ schema: 'string', value: 'hello', description: 'Simple string' }, { schema: 'string', value: 'hello', description: 'Simple string' },
{ schema: 'number', value: '42', description: 'Simple number' }, { schema: 'number', value: '42', description: 'Simple number' },
{ schema: 'int', value: '42', description: 'Simple int' },
{ schema: 'float', value: '3.14', description: 'Simple float' },
{ schema: 'float', value: '42', description: 'Float with integer value' },
{ schema: 'boolean', value: 'true', description: 'Simple boolean' }, { schema: 'boolean', value: 'true', description: 'Simple boolean' },
{ schema: '[string; number]', value: '[hello; 42]', description: 'Tuple' }, { schema: '[string; number]', value: '[hello; 42]', description: 'Tuple' },
{ schema: '[string; number]', value: 'hello; 42', description: 'Tuple without brackets' }, { schema: '[string; number]', value: 'hello; 42', description: 'Tuple without brackets' },
{ schema: 'string[]', value: '[hello; world; test]', description: 'Array of strings' }, { schema: 'string[]', value: '[hello; world; test]', description: 'Array of strings' },
{ schema: 'string[]', value: 'hello; world; test', description: 'Array without brackets' }, { schema: 'string[]', value: 'hello; world; test', description: 'Array without brackets' },
{ schema: 'number[]', value: '[1; 2; 3; 4]', description: 'Array of numbers' }, { schema: 'number[]', value: '[1; 2; 3; 4]', description: 'Array of numbers' },
{ schema: 'int[]', value: '[1; 2; 3; 4]', description: 'Array of ints' },
{ schema: 'float[]', value: '[1.5; 2.5; 3.5]', description: 'Array of floats' },
{ schema: '[string; number][]', value: '[[a; 1]; [b; 2]; [c; 3]]', description: 'Array of tuples' }, { schema: '[string; number][]', value: '[[a; 1]; [b; 2]; [c; 3]]', description: 'Array of tuples' },
{ schema: '[string; number][]', value: '[a; 1]; [b; 2]; [c; 3]', description: 'Array of tuples without outer brackets' }, { schema: '[string; number][]', value: '[a; 1]; [b; 2]; [c; 3]', description: 'Array of tuples without outer brackets' },
{ schema: 'word-smith', value: 'word-smith', description: 'String with hyphen' }, { schema: 'word-smith', value: 'word-smith', description: 'String with hyphen' },
@ -70,4 +75,27 @@ console.log('Array of tuples [string; number][] validation:');
console.log(` [["a", 1], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', 1], ['b', 2]])}`); console.log(` [["a", 1], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', 1], ['b', 2]])}`);
console.log(` [["a", "1"], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', '1'], ['b', 2]])}\n`); console.log(` [["a", "1"], ["b", 2]] is valid: ${arrayOfTuplesSchema.validator([['a', '1'], ['b', 2]])}\n`);
console.log('=== Testing Int and Float Types ===\n');
const intSchema = defineSchema('int');
console.log('Int schema validation:');
console.log(` 42 is valid: ${intSchema.validator(42)}`);
console.log(` 3.14 is valid: ${intSchema.validator(3.14)}\n`);
const floatSchema = defineSchema('float');
console.log('Float schema validation:');
console.log(` 3.14 is valid: ${floatSchema.validator(3.14)}`);
console.log(` 42 is valid: ${floatSchema.validator(42)}`);
console.log(` "3.14" is valid: ${floatSchema.validator('3.14')}\n`);
const intArraySchema = defineSchema('int[]');
console.log('Int array validation:');
console.log(` [1, 2, 3] is valid: ${intArraySchema.validator([1, 2, 3])}`);
console.log(` [1, 2.5, 3] is valid: ${intArraySchema.validator([1, 2.5, 3])}\n`);
const floatArraySchema = defineSchema('float[]');
console.log('Float array validation:');
console.log(` [1.5, 2.5, 3.5] is valid: ${floatArraySchema.validator([1.5, 2.5, 3.5])}`);
console.log(` [1, 2, 3] is valid: ${floatArraySchema.validator([1, 2, 3])}\n`);
console.log('=== All tests completed ==='); console.log('=== All tests completed ===');

View File

@ -1,4 +1,4 @@
export type SchemaType = 'string' | 'number' | 'boolean'; export type SchemaType = 'string' | 'number' | 'int' | 'float' | 'boolean';
export interface PrimitiveSchema { export interface PrimitiveSchema {
type: SchemaType; type: SchemaType;

View File

@ -39,6 +39,10 @@ class ValueParser {
return this.parseStringValue(); return this.parseStringValue();
case 'number': case 'number':
return this.parseNumberValue(); return this.parseNumberValue();
case 'int':
return this.parseIntValue();
case 'float':
return this.parseFloatValue();
case 'boolean': case 'boolean':
return this.parseBooleanValue(); return this.parseBooleanValue();
case 'tuple': case 'tuple':
@ -84,6 +88,25 @@ class ValueParser {
return num; return num;
} }
private parseIntValue(): number {
let numStr = '';
while (this.pos < this.input.length && /[\d.\-+eE]/.test(this.peek())) {
numStr += this.consume();
}
const num = parseFloat(numStr);
if (isNaN(num)) {
throw new ParseError('Invalid number', this.pos - numStr.length);
}
if (!Number.isInteger(num)) {
throw new ParseError('Expected integer value', this.pos - numStr.length);
}
return num;
}
private parseFloatValue(): number {
return this.parseNumberValue();
}
private parseBooleanValue(): boolean { private parseBooleanValue(): boolean {
if (this.consumeStr('true')) { if (this.consumeStr('true')) {
return true; return true;
@ -224,6 +247,10 @@ export function createValidator(schema: Schema): (value: unknown) => boolean {
return typeof value === 'string'; return typeof value === 'string';
case 'number': case 'number':
return typeof value === 'number' && !isNaN(value); return typeof value === 'number' && !isNaN(value);
case 'int':
return typeof value === 'number' && !isNaN(value) && Number.isInteger(value);
case 'float':
return typeof value === 'number' && !isNaN(value);
case 'boolean': case 'boolean':
return typeof value === 'boolean'; return typeof value === 'boolean';
case 'tuple': case 'tuple':