diff --git a/src/parser.ts b/src/parser.ts index 166c4a2..da26b2b 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -74,6 +74,28 @@ class Parser { 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('[')) { this.skipWhitespace(); diff --git a/src/test.ts b/src/test.ts index 5460a25..8779dc6 100644 --- a/src/test.ts +++ b/src/test.ts @@ -5,12 +5,17 @@ console.log('=== Testing Schema Parser ===\n'); const testCases = [ { schema: 'string', value: 'hello', description: 'Simple string' }, { 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: '[string; number]', value: '[hello; 42]', description: 'Tuple' }, { 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 without brackets' }, { 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 without outer brackets' }, { 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]])}\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 ==='); diff --git a/src/types.ts b/src/types.ts index c293c1b..9f8f07b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -export type SchemaType = 'string' | 'number' | 'boolean'; +export type SchemaType = 'string' | 'number' | 'int' | 'float' | 'boolean'; export interface PrimitiveSchema { type: SchemaType; diff --git a/src/validator.ts b/src/validator.ts index 6be26fc..2ca2799 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -39,6 +39,10 @@ class ValueParser { return this.parseStringValue(); case 'number': return this.parseNumberValue(); + case 'int': + return this.parseIntValue(); + case 'float': + return this.parseFloatValue(); case 'boolean': return this.parseBooleanValue(); case 'tuple': @@ -84,6 +88,25 @@ class ValueParser { 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 { if (this.consumeStr('true')) { return true; @@ -224,6 +247,10 @@ export function createValidator(schema: Schema): (value: unknown) => boolean { return typeof value === 'string'; case 'number': 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': return typeof value === 'boolean'; case 'tuple':