parse(startName, input, callbackData, startChar, endChar) {
const FUNCTION_NAME = `${this.#FILENAME}parse(): `;
for (const udt of this.#udts) {
if (!this.#udtCallbacks[udt.index]) {
throw new Error(`${this.#FILENAME}UDT callback not defined: ${udt.name}`);
}
}
this.#reset();
this.#chars = input;
if (typeof input === 'string') {
this.#charType = id.UINT32;
this.#chars = utils.stringToCodePoints(input);
} else if (input instanceof Uint8Array) {
this.#charType = id.UINT8;
} else if (input instanceof Uint16Array) {
this.#charType = id.UINT16;
} else if (input instanceof Uint32Array) {
this.#charType = id.UINT32;
} else if (Array.isArray(input)) {
this.#charType = id.ARRAY;
} else {
throw new Error(
`${FUNCTION_NAME} invalid input - must string, Array, Buffer, Uint8Array, Uint16Array or Uin32Array`
);
}
const ret = utils.sliceInterval(this.#chars.length, startChar, endChar);
this.#charStart = ret.indexStart;
this.#charEnd = ret.indexEnd;
const r = this.#rules;
const lower = startName.toLowerCase();
let startIndex = undefined;
for (const rule of this.#rules) {
if (lower === rule.lower) {
startIndex = rule.index;
break;
}
}
if (startIndex === undefined) {
throw new Error(`${FUNCTION_NAME}start name not a valid grammar rule name: '${startName}'`);
}
if (this.#trace) {
this.#trace.init(this.#rules, this.#udts, this.#chars, this.#charEnd, this.#charType);
}
if (this.#stats) {
this.#stats.init(this.#rules, this.#udts);
}
if (this.#ast) {
this.#ast.initChars(this.#chars);
}
this.#opcodes = [
{
type: id.RNM,
index: startIndex,
},
];
this.#userData = callbackData;
this.#opExecute(0, this.#charStart);
this.#opcodes = undefined;
let success = false;
switch (this.#sysData.state) {
case id.ACTIVE:
throw new Error(`${FUNCTION_NAME}final state should never be 'ACTIVE'`);
case id.NOMATCH:
success = false;
break;
case id.EMPTY:
case id.MATCH:
success = this.#sysData.phraseLength === this.#charEnd - this.#charStart;
break;
default:
throw new Error(`${FUNCTION_NAME}unrecognized final state: ${this.#sysData.state}`);
}
return {
success,
state: this.#sysData.state,
stateName: id.idName(this.#sysData.state),
length: this.#charEnd - this.#charStart,
matched: this.#sysData.phraseLength,
maxMatched: this.#maxMatched - this.#charStart,
maxTreeDepth: this.#maxTreeDepth,
nodeHits: this.#nodeHits,
};
}