@shaderfrog/glsl-parser
Version:
A GLSL ES 1.0 and 3.0 parser and preprocessor that can preserve whitespace and comments
156 lines (155 loc) • 5.6 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { execSync } from 'child_process';
import util from 'util';
import generate from './generator.js';
export var inspect = function (arg) {
return console.log(util.inspect(arg, false, null, true));
};
export var nextWarn = function () {
console.warn = jest.fn();
var i = 0;
// @ts-ignore
var mock = console.warn.mock;
return function () { return mock.calls[i++][0]; };
};
export var buildParser = function () {
execSync('npx peggy --cache --format es -o src/parser/parser.js src/parser/glsl-grammar.pegjs');
var parser = require('./parser');
var parse = parser.parse;
var ps = parseSrc(parse);
var ctx = {
parse: parse,
parseSrc: ps,
};
return {
parse: parse,
parser: parser,
parseSrc: ps,
debugSrc: debugSrc(ctx),
debugStatement: debugStatement(ctx),
expectParsedStatement: expectParsedStatement(ctx),
parseStatement: parseStatement(ctx),
expectParsedProgram: expectParsedProgram(ctx),
};
};
// Keeping this around in case I need to figure out how to do tracing again
// Most of this ceremony around building a parser is dealing with Peggy's error
// format() function, where the grammarSource has to line up in generate() and
// format() to get nicely formatted errors if there's a syntax error in the
// grammar
// const buildParser = (file: string) => {
// const grammar = fileContents(file);
// try {
// return peggy.generate(grammar, {
// grammarSource: file,
// cache: true,
// trace: false,
// });
// } catch (e) {
// const err = e as SyntaxError;
// if ('format' in err && typeof err.format === 'function') {
// console.error(err.format([{ source: file, text: grammar }]));
// }
// throw e;
// }
// };
var middle = /\/\* start \*\/((.|[\r\n])+)(\/\* end \*\/)?/m;
var parseSrc = function (parse) { return function (src, options) {
if (options === void 0) { options = {}; }
var grammarSource = '<anonymous glsl>';
try {
return parse(src, __assign(__assign({}, options), { grammarSource: grammarSource, tracer: {
trace: function (type) {
if (type.type === 'rule.match' &&
type.rule !== 'whitespace' &&
type.rule !== 'single_comment' &&
type.rule !== 'comment' &&
type.rule !== 'digit_sequence' &&
type.rule !== 'digit' &&
type.rule !== 'fractional_constant' &&
type.rule !== 'floating_constant' &&
type.rule !== 'translation_unit' &&
type.rule !== 'start' &&
type.rule !== 'external_declaration' &&
type.rule !== 'SEMICOLON' &&
type.rule !== 'terminal' &&
type.rule !== '_') {
if (type.rule === 'IDENTIFIER' || type.rule === 'TYPE_NAME') {
console.log('\x1b[35mMatch literal\x1b[0m', type.rule, type.result);
}
else {
console.log('\x1b[35mMatch\x1b[0m', type.rule);
}
}
// if (type.type === 'rule.fail') {
// console.log('fail', type.rule);
// }
},
} }));
}
catch (e) {
var err = e;
if ('format' in err) {
console.error(err.format([{ source: grammarSource, text: src }]));
}
console.error("Error parsing lexeme!\n\"".concat(src, "\""));
throw err;
}
}; };
var debugSrc = function (_a) {
var parseSrc = _a.parseSrc;
return function (src) {
inspect(parseSrc(src).program);
};
};
var debugStatement = function (_a) {
var parseSrc = _a.parseSrc;
return function (stmt) {
var program = "void main() {/* start */".concat(stmt, "/* end */}");
var ast = parseSrc(program);
inspect(ast.program[0].body.statements[0]);
};
};
var expectParsedStatement = function (_a) {
var parseSrc = _a.parseSrc;
return function (src, options) {
if (options === void 0) { options = {}; }
var program = "void main() {/* start */".concat(src, "/* end */}");
var ast = parseSrc(program, options);
var glsl = generate(ast);
if (glsl !== program) {
inspect(ast.program[0]);
// @ts-ignore
expect(glsl.match(middle)[1]).toBe(src);
}
};
};
var parseStatement = function (_a) {
var parseSrc = _a.parseSrc;
return function (src, options) {
if (options === void 0) { options = {}; }
var program = "void main() {".concat(src, "}");
return parseSrc(program, options);
};
};
var expectParsedProgram = function (_a) {
var parseSrc = _a.parseSrc;
return function (src, options) {
var ast = parseSrc(src, options);
var glsl = generate(ast);
if (glsl !== src) {
inspect(ast);
expect(glsl).toBe(src);
}
};
};