add some stuffs
This commit is contained in:
commit
35ba1a129f
12 changed files with 520 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules/
|
||||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "vendor/kuebiko"]
|
||||||
|
path = vendor/kuebiko
|
||||||
|
url = git@git.kitsu.cafe:rowan/kuebiko.git
|
22
package-lock.json
generated
Normal file
22
package-lock.json
generated
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "wgsl-reflect",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "wgsl-reflect",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"folktest": "git+https://git.kitsu.cafe/rowan/folktest.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/folktest": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "git+https://git.kitsu.cafe/rowan/folktest.git#708d44f1215be33fcceba426029f44b4f963dbe5",
|
||||||
|
"dev": true,
|
||||||
|
"license": "GPL-3.0-or-later"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
package.json
Normal file
16
package.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "wgsl-reflect",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "./tests/index.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"folktest": "git+https://git.kitsu.cafe/rowan/folktest.git"
|
||||||
|
}
|
||||||
|
}
|
77
src/index.js
Normal file
77
src/index.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
const shader = `// A fragment shader which lights textured geometry with point lights.
|
||||||
|
|
||||||
|
// Lights from a storage buffer binding.
|
||||||
|
struct PointLight {
|
||||||
|
position : vec3f,
|
||||||
|
color : vec3f,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LightStorage {
|
||||||
|
pointCount : u32,
|
||||||
|
point : array<PointLight>,
|
||||||
|
}
|
||||||
|
@group(0) @binding(0) var<storage> lights : LightStorage;
|
||||||
|
|
||||||
|
// Texture and sampler.
|
||||||
|
@group(1) @binding(0) var baseColorSampler : sampler;
|
||||||
|
@group(1) @binding(1) var baseColorTexture : texture_2d<f32>;
|
||||||
|
|
||||||
|
// Function arguments are values from the vertex shader.
|
||||||
|
@fragment
|
||||||
|
fn fragmentMain(@location(0) worldPos : vec3f,
|
||||||
|
@location(1) normal : vec3f,
|
||||||
|
@location(2) uv : vec2f) -> @location(0) vec4f {
|
||||||
|
// Sample the base color of the surface from a texture.
|
||||||
|
let baseColor = textureSample(baseColorTexture, baseColorSampler, uv);
|
||||||
|
|
||||||
|
let N = normalize(normal);
|
||||||
|
var surfaceColor = vec3f(0);
|
||||||
|
|
||||||
|
// Loop over the scene point lights.
|
||||||
|
for (var i = 0u; i < lights.pointCount; i++) {
|
||||||
|
let worldToLight = lights.point[i].position - worldPos;
|
||||||
|
let dist = length(worldToLight);
|
||||||
|
let dir = normalize(worldToLight);
|
||||||
|
|
||||||
|
// Determine the contribution of this light to the surface color.
|
||||||
|
let radiance = lights.point[i].color * (1 / pow(dist, 2));
|
||||||
|
let nDotL = max(dot(N, dir), 0);
|
||||||
|
|
||||||
|
// Accumulate light contribution to the surface color.
|
||||||
|
surfaceColor += baseColor.rgb * radiance * nDotL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the accumulated surface color.
|
||||||
|
return vec4(surfaceColor, baseColor.a);
|
||||||
|
}`
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
3.1 Parsing
|
||||||
|
Remove comments:
|
||||||
|
|
||||||
|
Replace the first comment with a space code point (U+0020).
|
||||||
|
|
||||||
|
Repeat until no comments remain.
|
||||||
|
|
||||||
|
Find template lists, using the algorithm in § 3.9 Template Lists.
|
||||||
|
|
||||||
|
Parse the whole text, attempting to match the translation_unit grammar rule. Parsing uses a LALR(1) parser (one token of lookahead) [DeRemer1969], with the following customization:
|
||||||
|
|
||||||
|
Tokenization is interleaved with parsing, and is context-aware. When the parser requests the next token:
|
||||||
|
|
||||||
|
Consume and ignore an initial sequence of blankspace code points.
|
||||||
|
|
||||||
|
If the next code point is the start of a template list, consume it and return _template_args_start.
|
||||||
|
|
||||||
|
If the next code point is the end of a template list, consume it and return _template_args_end.
|
||||||
|
|
||||||
|
Otherwise:
|
||||||
|
|
||||||
|
A token candidate is any WGSL token formed from the non-empty prefix of the remaining unconsumed code points.
|
||||||
|
|
||||||
|
The token returned is the longest token candidate that is also a valid lookahead token for the current parser state. [VanWyk2007]
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
16
src/parser/comments.js
Normal file
16
src/parser/comments.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { char, until } from '../../vendor/kuebiko/src/index.js'
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/WGSL/#comments
|
||||||
|
const slash = char('\u002f')
|
||||||
|
const asterisk = char('\u002a')
|
||||||
|
|
||||||
|
const comment = seq(slash, slash)
|
||||||
|
|
||||||
|
const blockCommentStart = seq(slash, asterisk)
|
||||||
|
const blockCommentEnd = seq(asterisk, slash)
|
||||||
|
|
||||||
|
const blockComment = seq(
|
||||||
|
blockCommentStart,
|
||||||
|
until(blockCommentEnd)
|
||||||
|
)
|
||||||
|
|
188
src/parser/keyword.js
Normal file
188
src/parser/keyword.js
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
import { any, anyChar, char, many, not, seq, str, until } from '../../vendor/kuebiko/src/index.js'
|
||||||
|
|
||||||
|
export const ident = seq(
|
||||||
|
not(any(
|
||||||
|
char('_'),
|
||||||
|
seq(str('__'), many(anyChar)),
|
||||||
|
)),
|
||||||
|
until(' ')
|
||||||
|
)
|
||||||
|
|
||||||
|
const Keyword = [
|
||||||
|
'alias',
|
||||||
|
'break',
|
||||||
|
'case',
|
||||||
|
'const',
|
||||||
|
'const_assert',
|
||||||
|
'continue',
|
||||||
|
'continuing',
|
||||||
|
'default',
|
||||||
|
'diagnostic',
|
||||||
|
'discard',
|
||||||
|
'else',
|
||||||
|
'enable',
|
||||||
|
'false',
|
||||||
|
'fn',
|
||||||
|
'for',
|
||||||
|
'if',
|
||||||
|
'let',
|
||||||
|
'loop',
|
||||||
|
'override',
|
||||||
|
'requires',
|
||||||
|
'return',
|
||||||
|
'struct',
|
||||||
|
'switch',
|
||||||
|
'true',
|
||||||
|
'var',
|
||||||
|
'while'
|
||||||
|
]
|
||||||
|
|
||||||
|
const Reserved = [
|
||||||
|
'NULL',
|
||||||
|
'Self',
|
||||||
|
'abstract',
|
||||||
|
'active',
|
||||||
|
'alignas',
|
||||||
|
'alignof',
|
||||||
|
'as',
|
||||||
|
'asm',
|
||||||
|
'asm_fragment',
|
||||||
|
'async',
|
||||||
|
'attribute',
|
||||||
|
'auto',
|
||||||
|
'await',
|
||||||
|
'become',
|
||||||
|
'cast',
|
||||||
|
'catch',
|
||||||
|
'class',
|
||||||
|
'co_await',
|
||||||
|
'co_return',
|
||||||
|
'co_yield',
|
||||||
|
'coherent',
|
||||||
|
'column_major',
|
||||||
|
'common',
|
||||||
|
'compile',
|
||||||
|
'compile_fragment',
|
||||||
|
'concept',
|
||||||
|
'const_cast',
|
||||||
|
'consteval',
|
||||||
|
'constexpr',
|
||||||
|
'constinit',
|
||||||
|
'crate',
|
||||||
|
'debugger',
|
||||||
|
'decltype',
|
||||||
|
'delete',
|
||||||
|
'demote',
|
||||||
|
'demote_to_helper',
|
||||||
|
'do',
|
||||||
|
'dynamic_cast',
|
||||||
|
'enum',
|
||||||
|
'explicit',
|
||||||
|
'export',
|
||||||
|
'extends',
|
||||||
|
'extern',
|
||||||
|
'external',
|
||||||
|
'fallthrough',
|
||||||
|
'filter',
|
||||||
|
'final',
|
||||||
|
'finally',
|
||||||
|
'friend',
|
||||||
|
'from',
|
||||||
|
'fxgroup',
|
||||||
|
'get',
|
||||||
|
'goto',
|
||||||
|
'groupshared',
|
||||||
|
'highp',
|
||||||
|
'impl',
|
||||||
|
'implements',
|
||||||
|
'import',
|
||||||
|
'inline',
|
||||||
|
'instanceof',
|
||||||
|
'interface',
|
||||||
|
'layout',
|
||||||
|
'lowp',
|
||||||
|
'macro',
|
||||||
|
'macro_rules',
|
||||||
|
'match',
|
||||||
|
'mediump',
|
||||||
|
'meta',
|
||||||
|
'mod',
|
||||||
|
'module',
|
||||||
|
'move',
|
||||||
|
'mut',
|
||||||
|
'mutable',
|
||||||
|
'namespace',
|
||||||
|
'new',
|
||||||
|
'nil',
|
||||||
|
'noexcept',
|
||||||
|
'noinline',
|
||||||
|
'nointerpolation',
|
||||||
|
'non_coherent',
|
||||||
|
'noncoherent',
|
||||||
|
'noperspective',
|
||||||
|
'null',
|
||||||
|
'nullptr',
|
||||||
|
'of',
|
||||||
|
'operator',
|
||||||
|
'package',
|
||||||
|
'packoffset',
|
||||||
|
'partition',
|
||||||
|
'pass',
|
||||||
|
'patch',
|
||||||
|
'pixelfragment',
|
||||||
|
'precise',
|
||||||
|
'precision',
|
||||||
|
'premerge',
|
||||||
|
'priv',
|
||||||
|
'protected',
|
||||||
|
'pub',
|
||||||
|
'public',
|
||||||
|
'readonly',
|
||||||
|
'ref',
|
||||||
|
'regardless',
|
||||||
|
'register',
|
||||||
|
'reinterpret_cast',
|
||||||
|
'require',
|
||||||
|
'resource',
|
||||||
|
'restrict',
|
||||||
|
'self',
|
||||||
|
'set',
|
||||||
|
'shared',
|
||||||
|
'sizeof',
|
||||||
|
'smooth',
|
||||||
|
'snorm',
|
||||||
|
'static',
|
||||||
|
'static_assert',
|
||||||
|
'static_cast',
|
||||||
|
'std',
|
||||||
|
'subroutine',
|
||||||
|
'super',
|
||||||
|
'target',
|
||||||
|
'template',
|
||||||
|
'this',
|
||||||
|
'thread_local',
|
||||||
|
'throw',
|
||||||
|
'trait',
|
||||||
|
'try',
|
||||||
|
'type',
|
||||||
|
'typedef',
|
||||||
|
'typeid',
|
||||||
|
'typename',
|
||||||
|
'typeof',
|
||||||
|
'union',
|
||||||
|
'unless',
|
||||||
|
'unorm',
|
||||||
|
'unsafe',
|
||||||
|
'unsized',
|
||||||
|
'use',
|
||||||
|
'using',
|
||||||
|
'varying',
|
||||||
|
'virtual',
|
||||||
|
'volatile',
|
||||||
|
'wgsl',
|
||||||
|
'where',
|
||||||
|
'with',
|
||||||
|
'writeonly',
|
||||||
|
'yield'
|
||||||
|
]
|
||||||
|
|
145
src/parser/literal.js
Normal file
145
src/parser/literal.js
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
import { any, anyOf, digit, maybe, seq, str } from '../../vendor/kuebiko/src/index.js'
|
||||||
|
import { many } from '../../vendor/kuebiko/src/index.js'
|
||||||
|
|
||||||
|
|
||||||
|
const iu = anyOf('iu')
|
||||||
|
const decimal = char('.')
|
||||||
|
const sign = anyOf('+-')
|
||||||
|
const e = anyOf('eE')
|
||||||
|
const p = anyOf('pP')
|
||||||
|
const fh = anyOf('fh')
|
||||||
|
|
||||||
|
export const zero = char('0')
|
||||||
|
export const digits = many(digit)
|
||||||
|
|
||||||
|
export const booleanLiteral = any(str('true'), str('false'))
|
||||||
|
export const decimalIntLiteral = any(
|
||||||
|
zero,
|
||||||
|
seq(
|
||||||
|
not(zero),
|
||||||
|
digits,
|
||||||
|
maybe(iu)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const hexDigit = any(digit, anyOf('abcdef'), anyOf('ABCDEF'))
|
||||||
|
|
||||||
|
const hexPrefix = seq(zero, anyOf('xX'))
|
||||||
|
|
||||||
|
const hexIntLiteral = seq(
|
||||||
|
hexPrefix,
|
||||||
|
hexDigit,
|
||||||
|
maybe(iu)
|
||||||
|
)
|
||||||
|
|
||||||
|
export const integerLiteral = any(
|
||||||
|
decimalIntLiteral,
|
||||||
|
hexIntLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
const nonzeroDigit = anyOf('123456789')
|
||||||
|
|
||||||
|
const many1 = parser => seq(parser, many(parser))
|
||||||
|
|
||||||
|
const exponent = seq(
|
||||||
|
e,
|
||||||
|
sign,
|
||||||
|
many1(digit)
|
||||||
|
)
|
||||||
|
|
||||||
|
const fhDecimalFloatLiteral = seq(
|
||||||
|
any(
|
||||||
|
zero,
|
||||||
|
seq(
|
||||||
|
nonzeroDigit,
|
||||||
|
digits
|
||||||
|
)
|
||||||
|
),
|
||||||
|
fh
|
||||||
|
)
|
||||||
|
|
||||||
|
const eDecimalFloatLiteral = seq(
|
||||||
|
digits,
|
||||||
|
exponent,
|
||||||
|
fh
|
||||||
|
)
|
||||||
|
|
||||||
|
const cDecimalFloatLiteral = seq(
|
||||||
|
any(
|
||||||
|
seq(
|
||||||
|
digits,
|
||||||
|
decimal,
|
||||||
|
many1(digit)
|
||||||
|
),
|
||||||
|
|
||||||
|
seq(
|
||||||
|
many1(digit),
|
||||||
|
decimal,
|
||||||
|
digits
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
maybe(seq(exponent, fh)),
|
||||||
|
)
|
||||||
|
|
||||||
|
const decimalFloatLiteral = any(
|
||||||
|
fhDecimalFloatLiteral,
|
||||||
|
eDecimalFloatLiteral,
|
||||||
|
cDecimalFloatLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
const sHexFloatLiteral = seq(
|
||||||
|
hexPrefix,
|
||||||
|
any(
|
||||||
|
seq(
|
||||||
|
many(hexDigit),
|
||||||
|
decimal,
|
||||||
|
many1(hexDigit)
|
||||||
|
),
|
||||||
|
|
||||||
|
seq(
|
||||||
|
many1(hexDigit),
|
||||||
|
decimal,
|
||||||
|
many(hexDigit)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
maybe(
|
||||||
|
seq(
|
||||||
|
p,
|
||||||
|
maybe(sign),
|
||||||
|
many1(digit),
|
||||||
|
fh
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const zHexFloatLiteral = seq(
|
||||||
|
hexPrefix,
|
||||||
|
many1(hexDigit),
|
||||||
|
p,
|
||||||
|
maybe(sign),
|
||||||
|
many1(digit),
|
||||||
|
maybe(fh)
|
||||||
|
)
|
||||||
|
const hexFloatLiteral = any(
|
||||||
|
sHexFloatLiteral,
|
||||||
|
zHexFloatLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
export const floatingPointLiteral = any(
|
||||||
|
decimalFloatLiteral,
|
||||||
|
hexFloatLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
export const numericLiteral = any(
|
||||||
|
integerLiteral,
|
||||||
|
floatingPointLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
export const literal = any(
|
||||||
|
numericLiteral,
|
||||||
|
booleanLiteral
|
||||||
|
)
|
25
src/parser/whitespace.js
Normal file
25
src/parser/whitespace.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { any, char, seq } from '../../vendor/kuebiko/src/index.js'
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/WGSL/#blankspace-and-line-breaks
|
||||||
|
export const space = char('\u0020')
|
||||||
|
export const ht = char('\u0009')
|
||||||
|
export const lf = char('\u000a')
|
||||||
|
export const vt = char('\u000b')
|
||||||
|
export const ff = char('\u000c')
|
||||||
|
export const cr = char('\u000d')
|
||||||
|
export const nel = char('\u000d')
|
||||||
|
export const ltr = char('\u200e')
|
||||||
|
export const rtl = char('\u200f')
|
||||||
|
export const ls = char('\u200f')
|
||||||
|
export const ps = char('\u2029')
|
||||||
|
|
||||||
|
export const blankspace = any(
|
||||||
|
space, ht, lf, vt, ff,
|
||||||
|
cr, nel, ltr, rtl, ls
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
export const linebreak = any(
|
||||||
|
lf, vt, ff, cr, nel, ls, ps
|
||||||
|
)
|
||||||
|
|
8
tests/index.js
Executable file
8
tests/index.js
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { TerminalRunner } from 'folktest'
|
||||||
|
import * as Tests from './units/index.js'
|
||||||
|
|
||||||
|
console.log(TerminalRunner(Tests).toString())
|
||||||
|
|
||||||
|
|
17
tests/units/index.js
Normal file
17
tests/units/index.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { it, assert } from 'folktest'
|
||||||
|
import { ident } from '../../src/parser/keyword.js'
|
||||||
|
|
||||||
|
export const Tests = [
|
||||||
|
it('whatever', () => {
|
||||||
|
const pass1 = 'test1'
|
||||||
|
const pass2 = '_Test2'
|
||||||
|
const fail1 = '_'
|
||||||
|
const fail2 = '__test'
|
||||||
|
const fail3 = 'default'
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
ident
|
||||||
|
)
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
1
vendor/kuebiko
vendored
Submodule
1
vendor/kuebiko
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 74bac48730187475160fe6cf3cdb4bc89c8e6c0b
|
Loading…
Add table
Reference in a new issue