core/parsers/constants.parser.ts
core/parsers/constants.parser.ts is a file in GovLab Quality. 77 lines of code and 14 definitions.
const QUOTE_CHARS: ReadonlySet<string> = new Set(['"', "'", "`"]);
const OPENER_CHARS: ReadonlySet<string> = new Set(["(", "[", "{"]);
const CLOSER_CHARS: ReadonlySet<string> = new Set([")", "]", "}"]);
interface ScanState {
depth: number;
done: boolean;
escaped: boolean;
out: string;
pendingSpace: boolean;
quote: string;
}
const appendChar = function appendChar(state: ScanState, ch: string): void {
if (state.pendingSpace) {
state.out += " ";
state.pendingSpace = false;
}
state.out += ch;
};
const scanInQuote = function scanInQuote(state: ScanState, ch: string): void {
state.out += ch;
if (state.escaped) {
state.escaped = false;
return;
}
if (ch === "\\") {
state.escaped = true;
return;
}
if (ch === state.quote) {
state.quote = "";
}
};
const depthDelta = function depthDelta(ch: string): number {
if (OPENER_CHARS.has(ch)) {
return 1;
}
return CLOSER_CHARS.has(ch) ? -1 : 0;
};
const scanChar = function scanChar(state: ScanState, ch: string): void {
if (state.quote !== "") {
scanInQuote(state, ch);
return;
}
if (QUOTE_CHARS.has(ch)) {
appendChar(state, ch);
state.quote = ch;
return;
}
if (ch === " " || ch === "\t") {
state.pendingSpace = state.out.length > 0;
return;
}
if (ch === ";" && state.depth === 0) {
state.done = true;
return;
}
state.depth += depthDelta(ch);
appendChar(state, ch);
};
export const captureValue = function captureValue(
lines: readonly string[],
startIndex: number,
): { endIndex: number; value: string } {
const eq = (lines[startIndex] ?? "").indexOf("=");
const state: ScanState = { depth: 0, done: false, escaped: false, out: "", pendingSpace: false, quote: "" };
for (let li = startIndex; li < lines.length; li += 1) {
const line = lines[li] ?? "";
for (let ci = li === startIndex ? eq + 1 : 0; ci < line.length; ci += 1) {
scanChar(state, line[ci] ?? "");
if (state.done) {
return { endIndex: li, value: state.out.trim() };
}
}
state.pendingSpace = state.out.length > 0;
}
return { endIndex: lines.length - 1, value: state.out.trim() };
};