65 lines
3.0 KiB
TypeScript
65 lines
3.0 KiB
TypeScript
import { log, LogTypes as LT } from '@Log4Deno';
|
|
|
|
import config from '~config';
|
|
|
|
import { loopCountCheck } from 'artigen/managers/loopManager.ts';
|
|
|
|
import { MathConf } from 'artigen/math/math.d.ts';
|
|
|
|
import { closeInternal, openInternal } from 'artigen/utils/escape.ts';
|
|
import { loggingEnabled } from 'artigen/utils/logFlag.ts';
|
|
|
|
const checkBalance = (conf: MathConf[], openStr: string, closeStr: string, errorType: string, getMatching: boolean, openIdx: number): number => {
|
|
let parenCnt = 0;
|
|
|
|
// Verify there are equal numbers of opening and closing parenthesis by adding 1 for opening parens and subtracting 1 for closing parens
|
|
for (let i = openIdx; i < conf.length; i++) {
|
|
loopCountCheck();
|
|
loggingEnabled &&
|
|
log(
|
|
LT.LOG,
|
|
`${getMatching ? 'Looking for matching' : 'Checking'} ${openStr}/${closeStr} ${getMatching ? '' : 'balance '}on ${
|
|
JSON.stringify(
|
|
conf,
|
|
)
|
|
} | at ${JSON.stringify(conf[i])}`,
|
|
);
|
|
if (conf[i] === openStr) {
|
|
parenCnt++;
|
|
} else if (conf[i] === closeStr) {
|
|
parenCnt--;
|
|
}
|
|
|
|
// If parenCnt ever goes below 0, that means too many closing paren appeared before opening parens
|
|
if (parenCnt < 0) {
|
|
throw new Error(`Unbalanced${errorType}`);
|
|
}
|
|
|
|
// When parenCnt reaches 0 again, we will have found the matching closing parenthesis and can safely exit the for loop
|
|
if (getMatching && parenCnt === 0) {
|
|
loggingEnabled && log(LT.LOG, `Matching ${openStr}/${closeStr} found at "${i}" | ${JSON.stringify(conf[i])}`);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// If the parenCnt is not 0, then we do not have balanced parens and need to error out now
|
|
// If getMatching flag is set and we have exited the loop, we did not find a matching paren
|
|
if (parenCnt !== 0 || getMatching) {
|
|
throw new Error(`Unbalanced${errorType}`);
|
|
}
|
|
|
|
// getMatching flag not set, this value is unused
|
|
return 0;
|
|
};
|
|
|
|
// assertXBalance verifies the entire conf has balanced X
|
|
export const assertGroupBalance = (conf: MathConf[]) => checkBalance(conf, '{', '}', 'Group', false, 0);
|
|
export const assertParenBalance = (conf: MathConf[]) => checkBalance(conf, '(', ')', 'Paren', false, 0);
|
|
export const assertPrePostBalance = (conf: MathConf[]) => checkBalance(conf, config.prefix, config.postfix, 'PrefixPostfix', false, 0);
|
|
|
|
// getMatchingXIdx gets the matching X, also partially verifies the conf has balanced X
|
|
export const getMatchingGroupIdx = (conf: MathConf[], openIdx: number): number => checkBalance(conf, '{', '}', 'Group', true, openIdx);
|
|
export const getMatchingInternalIdx = (conf: MathConf[], openIdx: number): number => checkBalance(conf, openInternal, closeInternal, 'Internal', true, openIdx);
|
|
export const getMatchingParenIdx = (conf: MathConf[], openIdx: number): number => checkBalance(conf, '(', ')', 'Paren', true, openIdx);
|
|
export const getMatchingPostfixIdx = (conf: MathConf[], openIdx: number): number => checkBalance(conf, config.prefix, config.postfix, 'PrefixPostfix', true, openIdx);
|