Skip to content

Commit 6568034

Browse files
committed
Parser test suite
1 parent c9f4e6a commit 6568034

File tree

8 files changed

+474
-38
lines changed

8 files changed

+474
-38
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,23 @@ The following shader stages are supported by the Khronos tools and recognized by
110110
- ``optimizerDebugSkipOptimizer`` : ``boolean`` (default false) When ``optimize`` enabled, skip the SPIR-V optimizer - compiles to SPIR-V then cross-compiles back to GLSL immediately.
111111
- ``suppressLineExtensionDirective`` : ``boolean`` (default false) When `emitLineDirectives` enabled, suppress the ``GL_GOOGLE_cpp_style_line_directive`` directive.
112112
- ``extraValidatorParams``, ``extraOptimizerParams``, ``extraCrossParams`` : ``string[]`` (default undefined) Additional parameters for the Khronos Glslang Validator [here](doc/glslangValidator.md), the Khronos SPIR-V Optimizer [here](doc/spirv-opt.md), and the Khronos SPIR-V Cross compiler [here](doc/spirv-cross.md).
113-
- ``glslangValidatorPath``, ``glslangOptimizerPath``, ``glslangCrossPath`` : ``string`` (default undefined) Provide / override binary tool paths. Note the environment variables always take precedence if set.
113+
- ``glslangValidatorPath``, ``glslangOptimizerPath``, ``glslangCrossPath`` : ``string`` (default undefined) Provide / override binary tool paths.\
114+
*It's recommended to instead use the environment variables ``GLSLANG_VALIDATOR``, ``GLSLANG_OPTIMIZER``, ``GLSLANG_CROSS`` where needed. They always take precedence if set.*
114115

115116
## Changelog
116117
Available in [CHANGES.md](CHANGES.md).
117118

118119
#### Caveats & Known Issues
119-
* This plugin handles glsl and glsify by itself. Use with conflicting plugins (e.g. rollup-plugin-glsl, rollup-plugin-glslify) will cause unpredictable results.
120+
* This plugin handles glsl and glslify by itself. Use with conflicting plugins (e.g. rollup-plugin-glsl, rollup-plugin-glslify) will cause unpredictable results.
120121
* Optimizer: ``lowp`` precision qualifier - emitted as ``mediump``\
121-
*SPIR-V has a single ``RelaxedPrecision`` decoration for 16-32bit precision. However most implementations now treat ``mediump`` and ``lowp`` equivalently, hence the lack of need for it in SPIR-V.*
122+
*SPIR-V has a single ``RelaxedPrecision`` decoration for 16-32bit precision. However most implementations actually treat ``mediump`` and ``lowp`` equivalently, hence the lack of need for it in SPIR-V.*
122123

123124
## License
124125

125126
Released under the [MIT license](LICENSE).\
126127
*Strip whitespace function adapted from code by Vincent Wochnik ([rollup-plugin-glsl](https://github.com/vwochnik/rollup-plugin-glsl)).*
127128

128-
Khronos tool binaries (built by the upstream projects) are distributed and installed with this plugin under the terms of the Apache License Version 2.0. See the corresponding LICENSE files in the ``bin`` folder.
129+
Khronos tool binaries (built by the upstream projects) are distributed and installed with this plugin under the terms of the Apache License Version 2.0. See the corresponding LICENSE files installed in the ``bin`` folder and the [binary releases](https://github.com/docd27/rollup-plugin-glsl-optimize/releases/).
129130

130131
[ci]: https://github.com/docd27/rollup-plugin-glsl-optimize/actions/workflows/node-ci.yml/badge.svg
131132
[ci-url]: https://github.com/docd27/rollup-plugin-glsl-optimize/actions/workflows/node-ci.yml

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rollup-plugin-glsl-optimize",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "Import GLSL source files as strings. Pre-processed, validated and optimized with Khronos Group SPIRV-Tools. Supports glslify.",
55
"homepage": "https://github.com/docd27/rollup-plugin-glsl-optimize#readme",
66
"keywords": [

src/lib/parse.js

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -281,16 +281,14 @@ function* parser(input) {
281281
}
282282
}
283283

284+
const warnParse = (message, token) => console.error(`Warning: ${formatParseError(message, token)}`);
284285

285-
const warnParse = (message, token) => console.error(formatParseError(message, token));
286-
287-
/* c8 ignore start */
288286
/**
289287
* @internal
290288
* @param {string} message
291289
* @param {LexerToken} token
292290
*/
293-
export const formatParseError = (message, token) => `Warning: ${message}\nLine ${
291+
export const formatParseError = (message, token) => `${message}\nLine ${
294292
token.line} col ${token.col}:\n${formatLine(token.text)}`;
295293

296294
const formatLine = (line) => {
@@ -326,11 +324,9 @@ const printToken = (t) => {
326324
restKV.length ? ` | ${restKV.map(([k, v]) => `${k} : '${v}'`).join(' | ')}`: ''}`;
327325
};
328326

329-
/** @internal */
330-
export function parseDump(input) {
331-
for (const token of simpleParse(input)) {
332-
console.log(printToken(token));
333-
}
334-
}
335-
336-
/* c8 ignore stop */
327+
export const test = {
328+
iterateStringLookahead,
329+
lexer,
330+
parser,
331+
printToken,
332+
};

src/lib/preamble.js

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const GLSL_LINE_EXT = 'GL_GOOGLE_cpp_style_line_directive';
99
* @param {string} filePath
1010
* @param {(version: string) => string} [versionReplacer]
1111
* @param {string} [extraPreamble]
12-
* @return {{code: string, didInsertion: boolean, foundVersionString?: string}}
12+
* @return {{code: string, didInsertion: boolean}}
1313
*/
1414
export function insertExtensionPreamble(code, filePath, versionReplacer = (v) => v, extraPreamble) {
1515
// let extensionDirectiveRequired = true;
@@ -105,18 +105,30 @@ export function fixupDirectives(code, preserve = false, required = true, searchL
105105
* @internal
106106
* @param {Iterable<import('./parse.js').ParserToken>} tokens
107107
* @param {(fixupLineNo: number) => import('./parse.js').ParserToken} preambleToken
108+
* PRE: emits trailing \n
108109
* @param {(version: string) => string} [versionReplacer]
109-
* @return {{code: string, didInsertion: boolean, foundVersionString?: string}}
110+
* If versionReplacer(undefined) !== undefined also inserts a version token when an existing one is not found
111+
* @return {{code: string, didInsertion: boolean}}
110112
*/
111113
function insertPreambleTokens(tokens, preambleToken, versionReplacer = (v) => v) {
112-
const versionToken = function* (token) {
113-
yield {type: TOK.Version, Version: versionReplacer(undefined), col: token.col, line: token.line,
114-
text: `#version ${versionReplacer(undefined)}`, value: ''};
115-
yield {type: TOK.EOL, col: token.col, line: token.line, text: '\n', value: '\n'};
114+
/** @param {import('./parse.js').ParserToken} token */
115+
const newVersionToken = function* (token) {
116+
const newVersion = versionReplacer(undefined);
117+
if (newVersion !== undefined) {
118+
yield {type: TOK.Version, Version: newVersion, col: token.col, line: token.line,
119+
text: `#version ${newVersion}`, value: ''};
120+
yield {type: TOK.EOL, col: token.col, line: token.line, text: '\n', value: '\n'};
121+
}
116122
};
117123

118124
return {code: [...(/** @return {Generator<import('./parse.js').ParserToken>} */ function* () {
119125
let insertNext = false, acceptVersion = true, foundVersion = false, didInsertion = false;
126+
/** @param {import('./parse.js').ParserToken} token */
127+
const newVersionPreambleTokens = function* (token) {
128+
acceptVersion = false; didInsertion = true;
129+
yield* newVersionToken(token);
130+
yield preambleToken(token.line);
131+
};
120132
for (const token of tokens) {
121133
if (insertNext) {
122134
insertNext = false;
@@ -125,34 +137,47 @@ function insertPreambleTokens(tokens, preambleToken, versionReplacer = (v) => v)
125137
switch (token.type) {
126138
case TOK.Comment: break;
127139
case TOK.EOF:
128-
if (!didInsertion) {
129-
didInsertion = true;
130-
// Needs a new line
131-
if (acceptVersion) yield* versionToken(token);
132-
yield {type: TOK.EOL, col: token.col, line: token.line, text: '\n', value: '\n'};
133-
yield preambleToken(token.line + 1);
140+
if (acceptVersion) { // Zero-length input
141+
yield* newVersionPreambleTokens(token);
142+
} else {
143+
if (!didInsertion) { // EOF directly after version directive
144+
didInsertion = true;
145+
// Needs a new line
146+
yield {type: TOK.EOL, col: token.col, line: token.line, text: '\n', value: '\n'};
147+
yield preambleToken(token.line + 1);
148+
}
134149
}
135150
break;
136151
case TOK.EOL:
137-
if (acceptVersion) yield* versionToken(token);
138-
acceptVersion = false;
139-
if (!didInsertion) {
140-
didInsertion = true; insertNext = true;
152+
if (acceptVersion) { // Zero-length first line
153+
yield* newVersionPreambleTokens(token);
154+
} else {
155+
if (!didInsertion) { // Newline after version directive, insert after this EOL
156+
insertNext = true; didInsertion = true;
157+
}
141158
}
142159
break;
143160
case TOK.Version:
144161
if (acceptVersion) {
145162
acceptVersion = false; foundVersion = true;
146163
const newVersion = versionReplacer(token.Version);
147164
token.Version = newVersion;
165+
/*
166+
Even though the parser may parse a line like "#version{COMMENT}300"
167+
The following is legal because per the spec:
168+
The #version directive must be present in the first line of a shader
169+
and must be followed by a newline. It may contain optional white-space as specified below
170+
but no other characters are allowed.
171+
*/
148172
token.text = `#version ${newVersion}`;
149173
} else {
150174
throw new Error(formatParseError(`Parse error: #version directive must be on first line`, token));
151175
}
152176
break;
153177
default:
154-
if (acceptVersion) yield* versionToken(token);
155-
acceptVersion = false;
178+
if (acceptVersion) { // Some other token on first line
179+
yield* newVersionPreambleTokens(token);
180+
}
156181
}
157182
yield token;
158183
}
@@ -172,3 +197,7 @@ export function insertPreamble(code, preamble) {
172197
(fixupLineNo) => ({col: 0, line: fixupLineNo, type: TOK.Comment, value: '', text:
173198
`${preamble}\n`}));
174199
}
200+
201+
export const test = {
202+
insertPreambleTokens,
203+
};

test/tests/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import * as util from 'util';
22
import chai from 'chai';
33
import chaiAsPromised from 'chai-as-promised';
4+
import {settings} from '../../settings.js';
45

56
import {installTests} from './install.js';
67
import {utilTests} from './util.js';
8+
import {parserTests} from './parser.js';
9+
import {preambleTests} from './preamble.js';
710
import {glslifyTests} from './glslify.js';
811
import {shaderTests} from './shader.js';
9-
import {settings} from '../../settings.js';
12+
1013

1114
/**
1215
* Log to console without mocking
@@ -24,6 +27,8 @@ export function runTests(glslOptimize) {
2427

2528
installTests();
2629
utilTests();
30+
parserTests();
31+
preambleTests();
2732
shaderTests(glslOptimize);
2833
glslifyTests(glslOptimize);
2934
}

0 commit comments

Comments
 (0)