Skip to content

Instantly share code, notes, and snippets.

@robertleeplummerjr
Created March 13, 2019 14:42
Show Gist options
  • Save robertleeplummerjr/a315bc3b11678caa074ded809fd38e50 to your computer and use it in GitHub Desktop.
Save robertleeplummerjr/a315bc3b11678caa074ded809fd38e50 to your computer and use it in GitHub Desktop.
/**
* A highly readable very forgiving micro-parser for a glsl function that gets argument types
* @param {String} source
* @returns {{types: String[], names: String[]}}
*/
function parseGLSLArgumentTypes(source) {
const types = [];
const names = [];
const states = [];
const isStartingVariableName = /^[a-zA-Z_]/;
const isVariableChar = /[a-zA-Z_0-9]/;
let i = 0;
let name = null;
let type = null;
while (i < source.length) {
const char = source[i];
const nextChar = source[i + 1];
const state = states.length > 0 ? states[states.length - 1] : null;
// begin MULTI_LINE_COMMENT handling
if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '*') { states.push('MULTI_LINE_COMMENT'); i += 2; continue; }
else if (state === 'MULTI_LINE_COMMENT' && char === '*' && nextChar === '/') { states.pop(); i += 2; continue; }
// end MULTI_LINE_COMMENT handling
// begin COMMENT handling
else if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '/') { states.push('COMMENT'); i += 2; continue; }
else if (state === 'COMMENT' && char === '\n') { states.pop(); i++; continue; }
// end COMMENT handling
// being FUNCTION_ARGUMENTS handling
else if (state === null && char === '(') { states.push('FUNCTION_ARGUMENTS'); i++; continue; }
else if (state === 'FUNCTION_ARGUMENTS') {
if (char === ')') {
states.pop();
break;
}
if (char === 'f' && nextChar === 'l' && source[i + 2] === 'o' && source[i + 3] === 'a' && source[i + 4] === 't' && source[i + 5] === ' ') {
states.push('DECLARE_VARIABLE');
type = 'float';
name = '';
i += 6;
continue;
} else if (char === 'i' && nextChar === 'n' && source[i + 2] === 't' && source[i + 3] === ' ') {
states.push('DECLARE_VARIABLE');
type = 'int';
name = '';
i += 4;
continue;
} else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '2' && source[i + 4] === ' ') {
states.push('DECLARE_VARIABLE');
type = 'vec2';
name = '';
i += 5;
continue;
} else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '3' && source[i + 4] === ' ') {
states.push('DECLARE_VARIABLE');
type = 'vec3';
name = '';
i += 5;
continue;
} else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '4' && source[i + 4] === ' ') {
states.push('DECLARE_VARIABLE');
type = 'vec4';
name = '';
i += 5;
continue;
}
}
// end FUNCTION_ARGUMENTS handling
// begin DECLARE_VARIABLE handling
else if (state === 'DECLARE_VARIABLE') {
if (name === '') {
if (char === ' ') {
i++;
continue;
}
if (!isStartingVariableName.test(char)) {
throw new Error('variable name is not expected string');
}
}
name += char;
if (!isVariableChar.test(nextChar)) {
states.pop();
names.push(name);
types.push(type);
}
}
// end DECLARE_VARIABLE handling
// Progress to next character
i++;
}
return {
names,
types
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment