import { NameTerm, NumberTerm } from "./terms.js"; class ParseCommandError extends SyntaxError { } class Parameter { name; value; constructor(name, value) { if (!name instanceof NameTerm) { throw new TypeError("Parameter name must be a NameTerm"); } this.name = name; this.value = value; } toString() { return this.value ? `${this.name}=${this.value}` : `${this.name}`; } valueOf() { if (this.value !== undefined) { return this.value.valueOf(); } else { return this.name; } } } export class Command { static stringRegex = /'[^'"]*'|"[^'"]*"/; static whitespaceRegex = /\s+/; static parse(commandString) { const terms = commandString.split(Command.whitespaceRegex).filter(s => !!s); if (terms.length < 1) { return null; } let verb; try { verb = new NameTerm(terms[0]); } catch { throw new ParseCommandError(`Invalid verb: ${verb}`); } const parameters = terms.slice(1).map(t => { const [nameString, valueString, ...rest] = t.split("="); if (rest.length > 0) { throw new ParseCommandError(`Invalid parameter: ${t}`); } let name; try { name = new NameTerm(nameString); } catch { throw new ParseCommandError(`Invalid parameter name: ${t}`); } let value; if (valueString) { for (const termClass of [NameTerm, NumberTerm]) { try { value = new termClass(valueString); break; } catch { continue; } } if (!value) { throw new ParseCommandError(`Invalid parameter value: ${t}`); } } return new Parameter(name, value); }); return new Command(commandString, verb, parameters); } originalString; verb; parameters = [] constructor(originalString, verb, parameters) { if (!verb instanceof String) { throw new TypeError("Command verb must be a string"); } this.originalString = originalString; this.verb = verb; this.parameters = parameters; } parameter(nameOrIndex) { if (typeof nameOrIndex === "string" || nameOrIndex instanceof String) { return this.parameters.find(p => p.name == nameOrIndex); } else if (nameOrIndex instanceof Number) { return this.parameters[nameOrIndex].valueOf(); } return null; } toString() { return `Command: {verb: "${this.verb.toString()}", parameters: [${this.parameters.join(", ")}] }`; } }