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