@luma.gl/shadertools
Version:
Shader module system for luma.gl
54 lines • 2.5 kB
JavaScript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
const DEFINE_NAME_PATTERN = '([a-zA-Z_][a-zA-Z0-9_]*)';
const IFDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*$`);
const IFNDEF_REGEXP = new RegExp(`^\\s*\\#\\s*ifndef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
const ELSE_REGEXP = /^\s*\#\s*else\s*(?:\/\/.*)?$/;
const ENDIF_REGEXP = /^\s*\#\s*endif\s*$/;
const IFDEF_WITH_COMMENT_REGEXP = new RegExp(`^\\s*\\#\\s*ifdef\\s*${DEFINE_NAME_PATTERN}\\s*(?:\\/\\/.*)?$`);
const ENDIF_WITH_COMMENT_REGEXP = /^\s*\#\s*endif\s*(?:\/\/.*)?$/;
export function preprocess(source, options) {
const lines = source.split('\n');
const output = [];
const conditionalStack = [];
let conditional = true;
for (const line of lines) {
const matchIf = line.match(IFDEF_WITH_COMMENT_REGEXP) || line.match(IFDEF_REGEXP);
const matchIfNot = line.match(IFNDEF_REGEXP);
const matchElse = line.match(ELSE_REGEXP);
const matchEnd = line.match(ENDIF_WITH_COMMENT_REGEXP) || line.match(ENDIF_REGEXP);
if (matchIf || matchIfNot) {
const defineName = (matchIf || matchIfNot)?.[1];
const defineValue = Boolean(options?.defines?.[defineName]);
const branchTaken = matchIf ? defineValue : !defineValue;
const active = conditional && branchTaken;
conditionalStack.push({ parentActive: conditional, branchTaken, active });
conditional = active;
}
else if (matchElse) {
const currentConditional = conditionalStack[conditionalStack.length - 1];
if (!currentConditional) {
throw new Error('Encountered #else without matching #ifdef or #ifndef');
}
currentConditional.active =
currentConditional.parentActive && !currentConditional.branchTaken;
currentConditional.branchTaken = true;
conditional = currentConditional.active;
}
else if (matchEnd) {
conditionalStack.pop();
conditional = conditionalStack.length
? conditionalStack[conditionalStack.length - 1].active
: true;
}
else if (conditional) {
output.push(line);
}
}
if (conditionalStack.length > 0) {
throw new Error('Unterminated conditional block in shader source');
}
return output.join('\n');
}
//# sourceMappingURL=preprocessor.js.map