parser.ts
1 /** 2 * Command parser for Dunnet 3 */ 4 5 export interface ParsedCommand { 6 verb: string; 7 args: string[]; 8 } 9 10 const IGNORED_WORDS = ['the', 'to', 'at', 'a', 'an', 'some']; 11 12 export function parseCommand(input: string): ParsedCommand | null { 13 const trimmed = input.trim().toLowerCase(); 14 if (!trimmed) return null; 15 16 // Tokenize 17 const words = trimmed.split(/[ ,:;]+/).filter(w => w.length > 0); 18 19 if (words.length === 0) return null; 20 21 // Remove ignored words 22 const filtered = words.filter(w => !IGNORED_WORDS.includes(w)); 23 24 if (filtered.length === 0) return null; 25 26 return { 27 verb: filtered[0], 28 args: filtered.slice(1) 29 }; 30 } 31 32 export function parseTwoWordCommand(input: string): { direct: string | null; indirect: string | null } { 33 // Handle "put X in/into/on Y" or "put X in Y" 34 const trimmed = input.trim().toLowerCase(); 35 36 // Match patterns like "put diamond in jar", "put key in box", "put weight on button" 37 const putMatch = trimmed.match(/^(?:put|insert|place)\s+(.+?)\s+(?:in|into|on|onto)\s+(.+)$/); 38 if (putMatch) { 39 return { direct: putMatch[1], indirect: putMatch[2] }; 40 } 41 42 // Simple space split for other cases 43 const words = trimmed.split(/\s+/).filter(w => w.length > 0 && !IGNORED_WORDS.includes(w)); 44 45 if (words.length >= 2) { 46 return { direct: words[1], indirect: null }; 47 } 48 49 return { direct: words[1] || null, indirect: null }; 50 } 51 52 export function matchObject(query: string, objectNames: Map<string, number>): number | null { 53 const normalized = query.replace(/\s+/g, '').toLowerCase(); 54 55 // Direct match 56 if (objectNames.has(normalized)) { 57 return objectNames.get(normalized)!; 58 } 59 60 // Partial match (first attempt) 61 for (const [name, id] of objectNames) { 62 if (name.includes(normalized) || normalized.includes(name)) { 63 return id; 64 } 65 } 66 67 // Try matching just the first word 68 const firstWord = normalized.split(/\s+/)[0]; 69 for (const [name, id] of objectNames) { 70 if (name.startsWith(firstWord)) { 71 return id; 72 } 73 } 74 75 return null; 76 }