toosoon-lsystem
Version:
Library providing functionalities for creating and manipulating Lindenmayer systems (L-Systems) using various parameters
90 lines (89 loc) • 3.6 kB
JavaScript
import { BRANCH_SYMBOLS } from './constants';
import { transformPhraseToAxiom } from './transformers';
/**
* Check if a symbol matches a context
*
* @param {object}
* @returns {boolean}
*/
export function matchContext({ axiom, index, match, direction, alphabet, ignoredSymbols, defines }) {
// Normalize match
const matchSymbols = typeof match === 'string'
? transformPhraseToAxiom(match, alphabet, ignoredSymbols, defines).map((part) => part.symbol)
: match;
let branchCount = 0;
let explicitBranchCount = 0;
// Set some variables depending on the direction to match
let axiomIndex;
let matchIndex;
let matchIndexChange;
let matchIndexOverflow;
let loopIndexChange;
let branchStart;
let branchEnd;
if (direction === 'before') {
axiomIndex = index - 1;
matchIndex = matchSymbols.length - 1;
matchIndexChange = -1;
matchIndexOverflow = -1;
loopIndexChange = -1;
branchEnd = BRANCH_SYMBOLS[0];
branchStart = BRANCH_SYMBOLS[1];
}
else {
axiomIndex = index + 1;
matchIndex = 0;
matchIndexChange = +1;
matchIndexOverflow = matchSymbols.length;
loopIndexChange = +1;
branchStart = BRANCH_SYMBOLS[0];
branchEnd = BRANCH_SYMBOLS[1];
}
// Loop into axiom
for (; axiomIndex < axiom.length && axiomIndex >= 0; axiomIndex += loopIndexChange) {
let axiomSymbol = axiom[axiomIndex].symbol;
let matchSymbol = matchSymbols[matchIndex];
// Compare current symbol of axiom with current symbol of match
if (axiomSymbol === matchSymbol) {
// If it's a match and previously NOT inside branch (branchCount === 0) or in explicitly wanted branch (explicitBranchCount > 0)
if (branchCount === 0 || explicitBranchCount > 0) {
// If a bracket was explicitly stated in match axiom
if (axiomSymbol === branchStart) {
explicitBranchCount++;
branchCount++;
matchIndex += matchIndexChange;
}
else if (axiomSymbol === branchEnd) {
explicitBranchCount = Math.max(0, explicitBranchCount - 1);
branchCount = Math.max(0, branchCount - 1);
// Only increase match if we are out of explicit branch
if (explicitBranchCount === 0)
matchIndex += matchIndexChange;
}
else {
matchIndex += matchIndexChange;
}
}
// Overflowing matchIndices (matchIndexEnd for 'before' match, matchIndex + 1 for 'after' match)
if (matchIndex === matchIndexOverflow) {
return true;
}
}
else if (axiomSymbol === branchStart) {
branchCount++;
if (explicitBranchCount > 0)
explicitBranchCount++;
}
else if (axiomSymbol === branchEnd) {
branchCount = Math.max(0, branchCount - 1);
if (explicitBranchCount > 0)
explicitBranchCount = Math.max(0, explicitBranchCount - 1);
}
else if ((branchCount === 0 || (explicitBranchCount > 0 && matchSymbol !== branchEnd)) &&
ignoredSymbols.includes(axiomSymbol) === false) {
// Not in branch or if in explicit branch and not at the very end (']'), and symbol not in ignoredSymbols: return false
return false;
}
}
return false;
}