import { describe, test } from 'node:test'; import assert from 'node:assert/strict'; import { PeggyDSLParser } from '../../src/ast/parser/PeggyDSLParser.js'; describe('Peggy DSL Parser', () => { const parser = new PeggyDSLParser(); test('Basic parsing', () => { const dsl = ` definition User { role: string isActive: boolean } fact hasRole(user: User, role: string) evidence canRead(user: User, doc: Document) { hasRole(user, 'admin') } `; const program = parser.parse(dsl); assert.ok(program !== null, 'Program should be created'); assert.ok(program.definitions.length === 1, 'Should have 1 definition'); assert.ok(program.facts.length === 1, 'Should have 1 fact'); assert.ok(program.evidence.length === 1, 'Should have 1 evidence'); }); test('Complex DSL parsing', () => { const dsl = ` definition User { role: string isActive: boolean clearance: string BEHAVES { blurring adaptive confidence_95 } CACHE eager } fact hasRole(user: User, role: string) CACHE eager fact isMember(user: User, group: Group) transitive CACHE lazy evidence canRead(user: User, doc: Document) { hasRole(user, 'admin') isMember(user, *group) { canRead(group, doc) } limit 5 WHEN hasRole(user, 'admin') UNLESS isSuspended(user) } `; const program = parser.parse(dsl); assert.ok(program !== null, 'Program should be created'); assert.ok(program.definitions.length === 1, 'Should have 1 definition'); assert.ok(program.facts.length === 2, 'Should have 2 facts'); assert.ok(program.evidence.length === 1, 'Should have 1 evidence'); }); test('Error handling', () => { const invalidDSL = ` definition User { role: string // Missing closing brace fact hasRole(user: User, role: string) // Missing semicolon `; assert.throws( () => parser.parse(invalidDSL), /Parsing failed/, 'Should have parsing error message' ); }); test('Validation', () => { const validDSL = ` definition User { role: string isActive: boolean } fact hasRole(user: User, role: string) `; const invalidDSL = ` definition User { role: string // Missing closing brace `; const validResult = parser.validate(validDSL); assert.ok(validResult.success, 'Valid DSL should pass validation'); assert.ok(validResult.program !== null, 'Valid DSL should return program'); const invalidResult = parser.validate(invalidDSL); assert.ok(!invalidResult.success, 'Invalid DSL should fail validation'); assert.ok(invalidResult.errors.length > 0, 'Should have validation errors'); }); });