wesl 0.6.0-pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2617 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2617 -0
- package/dist/index.js.map +1 -0
- package/dist/linker/packages/linker/src/AbstractElems.d.ts +104 -0
- package/dist/linker/packages/linker/src/BindIdents.d.ts +16 -0
- package/dist/linker/packages/linker/src/CommentsGrammar.d.ts +6 -0
- package/dist/linker/packages/linker/src/FlattenTreeImport.d.ts +11 -0
- package/dist/linker/packages/linker/src/ImportGrammar.d.ts +13 -0
- package/dist/linker/packages/linker/src/ImportTree.d.ts +17 -0
- package/dist/linker/packages/linker/src/Linker.d.ts +26 -0
- package/dist/linker/packages/linker/src/LowerAndEmit.d.ts +25 -0
- package/dist/linker/packages/linker/src/ParseWESL.d.ts +36 -0
- package/dist/linker/packages/linker/src/ParsedRegistry.d.ts +26 -0
- package/dist/linker/packages/linker/src/PathUtil.d.ts +9 -0
- package/dist/linker/packages/linker/src/Scope.d.ts +55 -0
- package/dist/linker/packages/linker/src/Slicer.d.ts +26 -0
- package/dist/linker/packages/linker/src/StandardTypes.d.ts +6 -0
- package/dist/linker/packages/linker/src/Util.d.ts +26 -0
- package/dist/linker/packages/linker/src/WESLCollect.d.ts +29 -0
- package/dist/linker/packages/linker/src/WESLGrammar.d.ts +23 -0
- package/dist/linker/packages/linker/src/WESLTokens.d.ts +42 -0
- package/dist/linker/packages/linker/src/WgslBundle.d.ts +13 -0
- package/dist/linker/packages/linker/src/debug/ASTtoString.d.ts +3 -0
- package/dist/linker/packages/linker/src/debug/ImportToString.d.ts +2 -0
- package/dist/linker/packages/linker/src/debug/LineWrapper.d.ts +21 -0
- package/dist/linker/packages/linker/src/debug/ScopeToString.d.ts +4 -0
- package/dist/linker/packages/linker/src/index.d.ts +7 -0
- package/dist/linker/packages/linker/src/test/ErrorLogging.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Expression.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/FlattenTreeImport.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ImportSyntaxCases.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkGlob.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/LinkPackage.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Linker.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/MatchWgslD.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseComments.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ParseWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PathUtil.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/PrettyGrammar.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/ScopeWESL.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/Slicer.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestSetup.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/TestUtil.d.ts +15 -0
- package/dist/linker/packages/linker/src/test/Util.test.d.ts +1 -0
- package/dist/linker/packages/linker/src/test/WgslTests.d.ts +0 -0
- package/dist/linker/packages/linker/src/test/shared/StringUtil.d.ts +8 -0
- package/dist/linker/packages/linker/src/test/shared/test/StringUtil.test.d.ts +1 -0
- package/dist/minified.cjs +2 -0
- package/dist/minified.cjs.map +1 -0
- package/dist/minified.js +2617 -0
- package/dist/minified.js.map +1 -0
- package/dist/wesl-testsuite/src/test-cases/BulkTests.d.ts +4 -0
- package/dist/wesl-testsuite/src/test-cases/ImportCases.d.ts +3 -0
- package/dist/wesl-testsuite/src/test-cases/ImportSyntaxCases.d.ts +3 -0
- package/package.json +45 -0
- package/src/AbstractElems.ts +148 -0
- package/src/BindIdents.ts +277 -0
- package/src/CommentsGrammar.ts +44 -0
- package/src/FlattenTreeImport.ts +59 -0
- package/src/ImportGrammar.ts +142 -0
- package/src/ImportTree.ts +19 -0
- package/src/Linker.ts +151 -0
- package/src/LowerAndEmit.ts +143 -0
- package/src/ParseWESL.ts +106 -0
- package/src/ParsedRegistry.ts +97 -0
- package/src/PathUtil.ts +52 -0
- package/src/Scope.ts +100 -0
- package/src/Slicer.ts +127 -0
- package/src/StandardTypes.ts +66 -0
- package/src/Util.ts +112 -0
- package/src/WESLCollect.ts +336 -0
- package/src/WESLGrammar.ts +538 -0
- package/src/WESLTokens.ts +97 -0
- package/src/WgslBundle.ts +16 -0
- package/src/debug/ASTtoString.ts +149 -0
- package/src/debug/ImportToString.ts +21 -0
- package/src/debug/LineWrapper.ts +65 -0
- package/src/debug/ScopeToString.ts +51 -0
- package/src/index.ts +7 -0
- package/src/test/ErrorLogging.test.ts +14 -0
- package/src/test/Expression.test.ts +22 -0
- package/src/test/FlattenTreeImport.test.ts +56 -0
- package/src/test/ImportCases.test.ts +440 -0
- package/src/test/ImportSyntaxCases.test.ts +22 -0
- package/src/test/LinkGlob.test.ts +25 -0
- package/src/test/LinkPackage.test.ts +26 -0
- package/src/test/Linker.test.ts +120 -0
- package/src/test/MatchWgslD.test.ts +16 -0
- package/src/test/ParseComments.test.ts +74 -0
- package/src/test/ParseWESL.test.ts +902 -0
- package/src/test/PathUtil.test.ts +34 -0
- package/src/test/PrettyGrammar.test.ts +21 -0
- package/src/test/ScopeWESL.test.ts +272 -0
- package/src/test/Slicer.test.ts +103 -0
- package/src/test/TestSetup.ts +4 -0
- package/src/test/TestUtil.ts +52 -0
- package/src/test/Util.test.ts +22 -0
- package/src/test/WgslTests.ts +0 -0
- package/src/test/__snapshots__/ParseDirectives.test.ts.snap +25 -0
- package/src/test/__snapshots__/ParseWESL.test.ts.snap +119 -0
- package/src/test/__snapshots__/ParseWESL2.test.ts.snap +67 -0
- package/src/test/__snapshots__/RustDirective.test.ts.snap +359 -0
- package/src/test/shared/StringUtil.ts +59 -0
- package/src/test/shared/test/StringUtil.test.ts +32 -0
- package/src/test/wgsl_1/main.wgsl +3 -0
- package/src/test/wgsl_1/util.wgsl +1 -0
- package/src/test/wgsl_2/main2.wgsl +3 -0
- package/src/test/wgsl_2/util2.wgsl +1 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eof,
|
|
3
|
+
kind,
|
|
4
|
+
opt,
|
|
5
|
+
or,
|
|
6
|
+
Parser,
|
|
7
|
+
preParse,
|
|
8
|
+
repeat,
|
|
9
|
+
repeatPlus,
|
|
10
|
+
req,
|
|
11
|
+
seq,
|
|
12
|
+
setTraceName,
|
|
13
|
+
tagScope,
|
|
14
|
+
text,
|
|
15
|
+
tokens,
|
|
16
|
+
tokenSkipSet,
|
|
17
|
+
tracing,
|
|
18
|
+
withSep,
|
|
19
|
+
withSepPlus,
|
|
20
|
+
} from "mini-parse";
|
|
21
|
+
import { weslImport } from "./ImportGrammar.ts";
|
|
22
|
+
import { bracketTokens, mainTokens } from "./WESLTokens.ts";
|
|
23
|
+
import { comment } from "./CommentsGrammar.ts";
|
|
24
|
+
import {
|
|
25
|
+
collectFn,
|
|
26
|
+
collectFnParam,
|
|
27
|
+
collectModule,
|
|
28
|
+
collectNameElem,
|
|
29
|
+
collectSimpleElem,
|
|
30
|
+
collectStruct,
|
|
31
|
+
collectStructMember,
|
|
32
|
+
collectVarLike,
|
|
33
|
+
declIdentElem,
|
|
34
|
+
refIdent,
|
|
35
|
+
scopeCollect,
|
|
36
|
+
} from "./WESLCollect.ts";
|
|
37
|
+
|
|
38
|
+
/** parser that recognizes key parts of WGSL and also directives like #import */
|
|
39
|
+
|
|
40
|
+
export const word = or(
|
|
41
|
+
kind(mainTokens.ident),
|
|
42
|
+
kind(mainTokens.textureStorage),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const qualified_ident = withSepPlus("::", word);
|
|
46
|
+
|
|
47
|
+
const diagnostic_rule_name = withSep(".", word, { requireOne: true });
|
|
48
|
+
const diagnostic_control = seq(
|
|
49
|
+
"(",
|
|
50
|
+
word,
|
|
51
|
+
",",
|
|
52
|
+
diagnostic_rule_name,
|
|
53
|
+
opt(","),
|
|
54
|
+
")",
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/** list of words that we don't need to collect (e.g. for @interpolate) */
|
|
58
|
+
const word_list = seq("(", withSep(",", word, { requireOne: true }), ")");
|
|
59
|
+
|
|
60
|
+
const attribute = seq(
|
|
61
|
+
"@",
|
|
62
|
+
req(
|
|
63
|
+
or(
|
|
64
|
+
// These attributes have no arguments
|
|
65
|
+
or("compute", "const", "fragment", "invariant", "must_use", "vertex"),
|
|
66
|
+
// These attributes have arguments, but the argument doesn't have any identifiers
|
|
67
|
+
seq(
|
|
68
|
+
or("interpolate", "builtin"),
|
|
69
|
+
req(() => word_list),
|
|
70
|
+
),
|
|
71
|
+
seq("diagnostic", diagnostic_control),
|
|
72
|
+
// These are normal attributes
|
|
73
|
+
seq(
|
|
74
|
+
or(
|
|
75
|
+
"workgroup_size",
|
|
76
|
+
"align",
|
|
77
|
+
"binding",
|
|
78
|
+
"blend_src",
|
|
79
|
+
"group",
|
|
80
|
+
"id",
|
|
81
|
+
"location",
|
|
82
|
+
"size",
|
|
83
|
+
),
|
|
84
|
+
req(() => argument_expression_list),
|
|
85
|
+
),
|
|
86
|
+
// Everything else is also a normal attribute, it might have an expression list
|
|
87
|
+
seq(
|
|
88
|
+
word,
|
|
89
|
+
opt(() => argument_expression_list),
|
|
90
|
+
),
|
|
91
|
+
),
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const argument_expression_list = seq(
|
|
96
|
+
"(",
|
|
97
|
+
withSep(",", () => expression),
|
|
98
|
+
req(")"),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const opt_attributes = repeat(attribute);
|
|
102
|
+
|
|
103
|
+
/** parse an identifier into a TypeNameElem */
|
|
104
|
+
export const typeNameDecl = req(word.collect(declIdentElem, "typeName"));
|
|
105
|
+
|
|
106
|
+
/** parse an identifier into a TypeNameElem */
|
|
107
|
+
export const fnNameDecl = req(
|
|
108
|
+
word.collect(declIdentElem, "fnName"),
|
|
109
|
+
"missing fn name",
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const std_type_specifier = seq(
|
|
113
|
+
word.collect(refIdent, "typeRef"),
|
|
114
|
+
() => opt_template_list,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const texture_storage_type = seq(
|
|
118
|
+
kind(mainTokens.textureStorage),
|
|
119
|
+
() => opt_template_words,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const ptr_type = seq(
|
|
123
|
+
"ptr",
|
|
124
|
+
req("<"),
|
|
125
|
+
word,
|
|
126
|
+
req(","),
|
|
127
|
+
() => template_arg_expression,
|
|
128
|
+
opt(seq(",", word)),
|
|
129
|
+
req(">"),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
export const type_specifier: Parser<any> = or(
|
|
133
|
+
texture_storage_type,
|
|
134
|
+
ptr_type,
|
|
135
|
+
std_type_specifier,
|
|
136
|
+
) as any;
|
|
137
|
+
|
|
138
|
+
const optionally_typed_ident = seq(
|
|
139
|
+
word.collect(declIdentElem, "declIdent"),
|
|
140
|
+
opt(seq(":", type_specifier)),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const req_optionally_typed_ident = req(optionally_typed_ident);
|
|
144
|
+
|
|
145
|
+
export const struct_member = seq(
|
|
146
|
+
opt_attributes,
|
|
147
|
+
word.collect(collectNameElem, "nameElem"),
|
|
148
|
+
":",
|
|
149
|
+
req(type_specifier),
|
|
150
|
+
).collect(collectStructMember());
|
|
151
|
+
|
|
152
|
+
export const struct_decl = seq(
|
|
153
|
+
"struct",
|
|
154
|
+
req(typeNameDecl),
|
|
155
|
+
seq(
|
|
156
|
+
req("{"),
|
|
157
|
+
withSepPlus(",", struct_member).ptag("members"),
|
|
158
|
+
req("}"),
|
|
159
|
+
).collect(scopeCollect(), "struct_scope"),
|
|
160
|
+
).collect(collectStruct());
|
|
161
|
+
|
|
162
|
+
/** Also covers func_call_statement.post.ident */
|
|
163
|
+
export const fn_call = seq(
|
|
164
|
+
word.collect(refIdent, "fn_call.refIdent"), // we collect this in fnDecl, to attach to FnElem
|
|
165
|
+
() => opt_template_list,
|
|
166
|
+
argument_expression_list,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const fnParam = tagScope(
|
|
170
|
+
seq(
|
|
171
|
+
opt_attributes,
|
|
172
|
+
word.collect(declIdentElem, "paramName"),
|
|
173
|
+
opt(seq(":", req(type_specifier))),
|
|
174
|
+
).collect(collectFnParam()),
|
|
175
|
+
).ctag("fnParam");
|
|
176
|
+
|
|
177
|
+
const fnParamList = seq("(", withSep(",", fnParam), ")");
|
|
178
|
+
|
|
179
|
+
const local_variable_decl = seq(
|
|
180
|
+
"var",
|
|
181
|
+
() => opt_template_list,
|
|
182
|
+
req_optionally_typed_ident,
|
|
183
|
+
opt(seq("=", () => expression)),
|
|
184
|
+
).collect(collectVarLike("var"), "variable_decl");
|
|
185
|
+
|
|
186
|
+
const global_variable_decl = seq(
|
|
187
|
+
"var",
|
|
188
|
+
() => opt_template_words,
|
|
189
|
+
req_optionally_typed_ident,
|
|
190
|
+
opt(seq("=", () => expression.collect(scopeCollect(), "decl_scope"))),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
/** Aka template_elaborated_ident.post.ident */
|
|
194
|
+
const opt_template_list = opt(
|
|
195
|
+
seq(
|
|
196
|
+
tokens(bracketTokens, "<"),
|
|
197
|
+
withSepPlus(",", () => template_arg_expression),
|
|
198
|
+
tokens(bracketTokens, ">"),
|
|
199
|
+
),
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
/** template list of non-identifier words. e.g. var <storage> */
|
|
203
|
+
const opt_template_words = opt(
|
|
204
|
+
seq(
|
|
205
|
+
tokens(bracketTokens, "<"),
|
|
206
|
+
withSepPlus(",", () => word),
|
|
207
|
+
tokens(bracketTokens, ">"),
|
|
208
|
+
),
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const template_elaborated_ident = seq(
|
|
212
|
+
word.collect(refIdent),
|
|
213
|
+
opt_template_list,
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
const literal = or("true", "false", kind(mainTokens.digits));
|
|
217
|
+
|
|
218
|
+
const paren_expression = seq("(", () => expression, req(")"));
|
|
219
|
+
|
|
220
|
+
const call_expression = seq(
|
|
221
|
+
template_elaborated_ident,
|
|
222
|
+
argument_expression_list,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const primary_expression = or(
|
|
226
|
+
literal,
|
|
227
|
+
paren_expression,
|
|
228
|
+
call_expression,
|
|
229
|
+
template_elaborated_ident,
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const component_or_swizzle = repeatPlus(
|
|
233
|
+
or(
|
|
234
|
+
seq(".", word),
|
|
235
|
+
seq("[", () => expression, req("]")),
|
|
236
|
+
),
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* bitwise_expression.post.unary_expression
|
|
241
|
+
* & ^ |
|
|
242
|
+
* expression
|
|
243
|
+
* && ||
|
|
244
|
+
* relational_expression.post.unary_expression
|
|
245
|
+
* > >= < <= != ==
|
|
246
|
+
* shift_expression.post.unary_expression
|
|
247
|
+
* % * / + - << >>
|
|
248
|
+
*/
|
|
249
|
+
const makeExpressionOperator = (isTemplate: boolean) => {
|
|
250
|
+
const allowedOps = (
|
|
251
|
+
"& | ^ << <= < != == % * / + -" + (isTemplate ? "" : " && || >> >= >")
|
|
252
|
+
).split(" ");
|
|
253
|
+
return or(...allowedOps);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const unary_expression: Parser<any> = or(
|
|
257
|
+
seq(or(..."! & * - ~".split(" ")), () => unary_expression),
|
|
258
|
+
seq(primary_expression, opt(component_or_swizzle)),
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const makeExpression = (isTemplate: boolean) => {
|
|
262
|
+
return seq(
|
|
263
|
+
unary_expression,
|
|
264
|
+
repeat(seq(makeExpressionOperator(isTemplate), unary_expression)),
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
export const expression = makeExpression(false);
|
|
269
|
+
const template_arg_expression = makeExpression(true);
|
|
270
|
+
|
|
271
|
+
const unscoped_compound_statement = seq(
|
|
272
|
+
opt_attributes,
|
|
273
|
+
text("{"),
|
|
274
|
+
repeat(() => statement),
|
|
275
|
+
req("}"),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const compound_statement = seq(
|
|
279
|
+
opt_attributes,
|
|
280
|
+
seq(
|
|
281
|
+
text("{"),
|
|
282
|
+
repeat(() => statement),
|
|
283
|
+
req("}"),
|
|
284
|
+
).collect(scopeCollect()),
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const for_init = or(
|
|
288
|
+
fn_call,
|
|
289
|
+
() => variable_or_value_statement,
|
|
290
|
+
() => variable_updating_statement,
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
const for_update = or(fn_call, () => variable_updating_statement);
|
|
294
|
+
|
|
295
|
+
const for_statement = seq(
|
|
296
|
+
opt_attributes,
|
|
297
|
+
"for",
|
|
298
|
+
seq(
|
|
299
|
+
req("("),
|
|
300
|
+
opt(for_init),
|
|
301
|
+
req(";"),
|
|
302
|
+
opt(expression),
|
|
303
|
+
req(";"),
|
|
304
|
+
opt(for_update),
|
|
305
|
+
req(")"),
|
|
306
|
+
unscoped_compound_statement,
|
|
307
|
+
).collect(scopeCollect()),
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
const if_statement = seq(
|
|
311
|
+
opt_attributes,
|
|
312
|
+
"if",
|
|
313
|
+
req(seq(expression, compound_statement)),
|
|
314
|
+
repeat(seq("else", "if", req(seq(expression, compound_statement)))),
|
|
315
|
+
opt(seq("else", req(compound_statement))),
|
|
316
|
+
);
|
|
317
|
+
const loop_statement = seq(
|
|
318
|
+
opt_attributes,
|
|
319
|
+
"loop",
|
|
320
|
+
opt_attributes,
|
|
321
|
+
req(
|
|
322
|
+
seq(
|
|
323
|
+
"{",
|
|
324
|
+
repeat(() => statement),
|
|
325
|
+
opt(
|
|
326
|
+
seq(
|
|
327
|
+
"continuing",
|
|
328
|
+
opt_attributes,
|
|
329
|
+
"{",
|
|
330
|
+
repeat(() => statement),
|
|
331
|
+
opt(seq("break", "if", expression, ";")),
|
|
332
|
+
"}",
|
|
333
|
+
),
|
|
334
|
+
),
|
|
335
|
+
"}",
|
|
336
|
+
),
|
|
337
|
+
),
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
const case_selector = or("default", expression);
|
|
341
|
+
const switch_clause = or(
|
|
342
|
+
seq(
|
|
343
|
+
"case",
|
|
344
|
+
withSep(",", case_selector, { requireOne: true }),
|
|
345
|
+
opt(":"),
|
|
346
|
+
compound_statement,
|
|
347
|
+
),
|
|
348
|
+
seq("default", opt(":"), compound_statement),
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
const switch_body = seq(opt_attributes, "{", repeatPlus(switch_clause), "}");
|
|
352
|
+
const switch_statement = seq(opt_attributes, "switch", expression, switch_body);
|
|
353
|
+
|
|
354
|
+
const while_statement = seq(
|
|
355
|
+
opt_attributes,
|
|
356
|
+
"while",
|
|
357
|
+
expression,
|
|
358
|
+
compound_statement,
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
const statement: Parser<any> = or(
|
|
362
|
+
for_statement,
|
|
363
|
+
if_statement,
|
|
364
|
+
loop_statement,
|
|
365
|
+
switch_statement,
|
|
366
|
+
while_statement,
|
|
367
|
+
compound_statement,
|
|
368
|
+
seq("break", ";"),
|
|
369
|
+
seq("continue", ";"),
|
|
370
|
+
seq(";"),
|
|
371
|
+
() => const_assert,
|
|
372
|
+
seq("discard", ";"),
|
|
373
|
+
seq("return", opt(expression), ";"),
|
|
374
|
+
seq(fn_call, ";"),
|
|
375
|
+
seq(() => variable_or_value_statement, ";"),
|
|
376
|
+
seq(() => variable_updating_statement, ";"),
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
const lhs_expression: Parser<any> = or(
|
|
380
|
+
seq(word.collect(refIdent), opt(component_or_swizzle)),
|
|
381
|
+
seq("(", () => lhs_expression, ")", opt(component_or_swizzle)),
|
|
382
|
+
seq("&", () => lhs_expression),
|
|
383
|
+
seq("*", () => lhs_expression),
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const variable_or_value_statement = or(
|
|
387
|
+
// Also covers the = expression case
|
|
388
|
+
local_variable_decl,
|
|
389
|
+
seq("const", req_optionally_typed_ident, req("="), expression),
|
|
390
|
+
seq("let", req_optionally_typed_ident, req("="), expression),
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
const variable_updating_statement = or(
|
|
394
|
+
seq(
|
|
395
|
+
lhs_expression,
|
|
396
|
+
or("=", "<<=", ">>=", "%=", "&=", "*=", "+=", "-=", "/=", "^=", "|="), // TODO: try making this a lexer rule instead of a parser rule
|
|
397
|
+
expression,
|
|
398
|
+
),
|
|
399
|
+
seq(lhs_expression, or("++", "--")),
|
|
400
|
+
seq("_", "=", expression),
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
export const fn_decl = seq(
|
|
404
|
+
opt_attributes,
|
|
405
|
+
text("fn"),
|
|
406
|
+
req(fnNameDecl),
|
|
407
|
+
seq(
|
|
408
|
+
req(fnParamList),
|
|
409
|
+
opt(seq("->", opt_attributes, type_specifier.ctag("returnType"))),
|
|
410
|
+
req(unscoped_compound_statement),
|
|
411
|
+
).collect(scopeCollect(), "body_scope"),
|
|
412
|
+
).collect(collectFn());
|
|
413
|
+
|
|
414
|
+
const global_value_decl = or(
|
|
415
|
+
seq(
|
|
416
|
+
opt_attributes,
|
|
417
|
+
"override",
|
|
418
|
+
optionally_typed_ident,
|
|
419
|
+
seq(opt(seq("=", expression.collect(scopeCollect(), "decl_scope")))),
|
|
420
|
+
";",
|
|
421
|
+
).collect(collectVarLike("override")),
|
|
422
|
+
seq(
|
|
423
|
+
"const",
|
|
424
|
+
optionally_typed_ident,
|
|
425
|
+
"=",
|
|
426
|
+
seq(expression).collect(scopeCollect(), "decl_scope"),
|
|
427
|
+
";",
|
|
428
|
+
).collect(collectVarLike("const")),
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
export const global_alias = seq(
|
|
432
|
+
"alias",
|
|
433
|
+
req(word).collect(declIdentElem, "declIdent"),
|
|
434
|
+
req("="),
|
|
435
|
+
req(type_specifier).collect(scopeCollect(), "decl_scope"),
|
|
436
|
+
req(";"),
|
|
437
|
+
).collect(collectVarLike("alias"), "global_alias");
|
|
438
|
+
|
|
439
|
+
const const_assert = seq("const_assert", req(expression), ";").collect(
|
|
440
|
+
collectSimpleElem("assert"),
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
const import_statement = weslImport;
|
|
444
|
+
|
|
445
|
+
const global_directive = seq(
|
|
446
|
+
or(
|
|
447
|
+
seq("diagnostic", diagnostic_control),
|
|
448
|
+
seq("enable", withSep(",", word, { requireOne: true })),
|
|
449
|
+
seq("requires", withSep(",", word, { requireOne: true })),
|
|
450
|
+
),
|
|
451
|
+
";",
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
export const global_decl = tagScope(
|
|
455
|
+
or(
|
|
456
|
+
fn_decl,
|
|
457
|
+
seq(opt_attributes, global_variable_decl, ";").collect(
|
|
458
|
+
collectVarLike("gvar"),
|
|
459
|
+
"g_variable_decl",
|
|
460
|
+
),
|
|
461
|
+
global_value_decl,
|
|
462
|
+
";",
|
|
463
|
+
global_alias,
|
|
464
|
+
const_assert,
|
|
465
|
+
struct_decl,
|
|
466
|
+
),
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const end = tokenSkipSet(null, seq(repeat(kind(mainTokens.ws)), eof()));
|
|
470
|
+
export const weslRoot = preParse(
|
|
471
|
+
comment,
|
|
472
|
+
seq(
|
|
473
|
+
repeat(weslImport),
|
|
474
|
+
repeat(or(global_directive, weslImport)),
|
|
475
|
+
repeat(or(global_decl, weslImport)),
|
|
476
|
+
req(end),
|
|
477
|
+
).collect(collectModule(), "collectModule"),
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
if (tracing) {
|
|
481
|
+
const names: Record<string, Parser<unknown>> = {
|
|
482
|
+
qualified_ident,
|
|
483
|
+
diagnostic_rule_name,
|
|
484
|
+
diagnostic_control,
|
|
485
|
+
attribute,
|
|
486
|
+
argument_expression_list,
|
|
487
|
+
opt_attributes,
|
|
488
|
+
typeNameDecl,
|
|
489
|
+
fnNameDecl,
|
|
490
|
+
type_specifier,
|
|
491
|
+
optionally_typed_ident,
|
|
492
|
+
struct_member,
|
|
493
|
+
struct_decl,
|
|
494
|
+
fn_call,
|
|
495
|
+
fnParam,
|
|
496
|
+
fnParamList,
|
|
497
|
+
local_variable_decl,
|
|
498
|
+
global_variable_decl,
|
|
499
|
+
opt_template_list,
|
|
500
|
+
template_elaborated_ident,
|
|
501
|
+
literal,
|
|
502
|
+
paren_expression,
|
|
503
|
+
call_expression,
|
|
504
|
+
primary_expression,
|
|
505
|
+
component_or_swizzle,
|
|
506
|
+
unary_expression,
|
|
507
|
+
expression,
|
|
508
|
+
template_arg_expression,
|
|
509
|
+
compound_statement,
|
|
510
|
+
for_init,
|
|
511
|
+
for_update,
|
|
512
|
+
for_statement,
|
|
513
|
+
if_statement,
|
|
514
|
+
loop_statement,
|
|
515
|
+
case_selector,
|
|
516
|
+
switch_clause,
|
|
517
|
+
switch_body,
|
|
518
|
+
switch_statement,
|
|
519
|
+
while_statement,
|
|
520
|
+
statement,
|
|
521
|
+
lhs_expression,
|
|
522
|
+
variable_or_value_statement,
|
|
523
|
+
variable_updating_statement,
|
|
524
|
+
fn_decl,
|
|
525
|
+
global_value_decl,
|
|
526
|
+
global_alias,
|
|
527
|
+
const_assert,
|
|
528
|
+
import_statement,
|
|
529
|
+
global_directive,
|
|
530
|
+
global_decl,
|
|
531
|
+
end,
|
|
532
|
+
weslRoot,
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
Object.entries(names).forEach(([name, parser]) => {
|
|
536
|
+
setTraceName(parser, name);
|
|
537
|
+
});
|
|
538
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { matchOneOf, tokenMatcher } from "mini-parse";
|
|
2
|
+
|
|
3
|
+
// https://www.w3.org/TR/WGSL/#blankspace-and-line-breaks
|
|
4
|
+
/** New lines */
|
|
5
|
+
export const eol = /[\n\v\f\u{0085}\u{2028}\u{2029}]|\r\n?/u;
|
|
6
|
+
/** Whitespaces including new lines */
|
|
7
|
+
export const blankspaces =
|
|
8
|
+
/[ \t\n\v\f\r\u{0085}\u{200E}\u{200F}\u{2028}\u{2029}]+/u;
|
|
9
|
+
|
|
10
|
+
export const directive = /#[a-zA-Z_]\w*/;
|
|
11
|
+
|
|
12
|
+
const symbolSet =
|
|
13
|
+
"& && -> @ / ! [ ] { } :: : , == = != >>= >> >= > <<= << <= < % - --" +
|
|
14
|
+
" . + ++ | || ( ) ; * ~ ^ // /* */ += -= *= /= %= &= |= ^=" +
|
|
15
|
+
// For the _ = expr; syntax
|
|
16
|
+
" _";
|
|
17
|
+
|
|
18
|
+
const symbol = matchOneOf(symbolSet);
|
|
19
|
+
const quote = /["']/;
|
|
20
|
+
|
|
21
|
+
export const ident =
|
|
22
|
+
/(?:(?:[_\p{XID_Start}][\p{XID_Continue}]+)|(?:[\p{XID_Start}]))/u;
|
|
23
|
+
|
|
24
|
+
export const digits = new RegExp(
|
|
25
|
+
// decimal_float_literal
|
|
26
|
+
/(?:0[fh])|(?:[1-9][0-9]*[fh])/.source +
|
|
27
|
+
/|(?:[0-9]*\.[0-9]+(?:[eE][+-]?[0-9]+)?[fh]?)/.source +
|
|
28
|
+
/|(?:[0-9]+\.[0-9]*(?:[eE][+-]?[0-9]+)?[fh]?)/.source +
|
|
29
|
+
/|(?:[0-9]+[eE][+-]?[0-9]+[fh]?)/.source +
|
|
30
|
+
// hex_float_literal
|
|
31
|
+
/|(?:0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+(?:[pP][+-]?[0-9]+[fh]?)?)/.source +
|
|
32
|
+
/|(?:0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*(?:[pP][+-]?[0-9]+[fh]?)?)/.source +
|
|
33
|
+
/|(?:0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?)/.source +
|
|
34
|
+
// hex_int_literal
|
|
35
|
+
/|(?:0[xX][0-9a-fA-F]+[iu]?)/.source +
|
|
36
|
+
// decimal_int_literal
|
|
37
|
+
/|(?:0[iu]?)|(?:[1-9][0-9]*[iu]?)/.source,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const textureStorage = matchOneOf(
|
|
41
|
+
"texture_strorage_1d texture_storage_2d texture_storage_2d_array texture_storage_3d",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
/** main set of tokens for WGSL */
|
|
45
|
+
export const mainTokens = tokenMatcher(
|
|
46
|
+
{
|
|
47
|
+
directive,
|
|
48
|
+
textureStorage,
|
|
49
|
+
ident,
|
|
50
|
+
digits,
|
|
51
|
+
symbol,
|
|
52
|
+
quote,
|
|
53
|
+
ws: blankspaces,
|
|
54
|
+
},
|
|
55
|
+
"main",
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
export const bracketTokens = tokenMatcher(
|
|
59
|
+
{
|
|
60
|
+
bracket: /<|>/,
|
|
61
|
+
ws: blankspaces,
|
|
62
|
+
other: /[^<>]+/,
|
|
63
|
+
},
|
|
64
|
+
"bracket",
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
/** matching tokens at the start of a '//' line comment that might contain #directives */
|
|
68
|
+
export const lineCommentTokens = tokenMatcher(
|
|
69
|
+
{
|
|
70
|
+
ws: /[ \t]+/, // note ws must be before notEol
|
|
71
|
+
notEol: /[^\n]+/,
|
|
72
|
+
eol,
|
|
73
|
+
},
|
|
74
|
+
"lineComment",
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
/** matching tokens while parsing directive parameters #export foo(param1, param2) */
|
|
78
|
+
export const argsTokens = tokenMatcher(
|
|
79
|
+
{
|
|
80
|
+
directive,
|
|
81
|
+
quote,
|
|
82
|
+
relPath: /[.][/\w._-]+/,
|
|
83
|
+
arg: /[\w._-]+/,
|
|
84
|
+
symbol,
|
|
85
|
+
ws: /[ \t]+/, // don't include \n, so we can find eol separately
|
|
86
|
+
eol,
|
|
87
|
+
},
|
|
88
|
+
"argsTokens",
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
export const rootWs = tokenMatcher(
|
|
92
|
+
{
|
|
93
|
+
blanks: /\s+/,
|
|
94
|
+
other: /[^\s]+/,
|
|
95
|
+
},
|
|
96
|
+
"rootWs",
|
|
97
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface WgslBundle {
|
|
2
|
+
/** name of the package, e.g. wgsl-rand */
|
|
3
|
+
name: string;
|
|
4
|
+
|
|
5
|
+
/** npm version of the package e.g. 0.4.1 */
|
|
6
|
+
version: string;
|
|
7
|
+
|
|
8
|
+
/** wesl edition of the code e.g. wesl_unstable_2024_1 */
|
|
9
|
+
edition: string;
|
|
10
|
+
|
|
11
|
+
/** map of wesl/wgsl modules:
|
|
12
|
+
* keys are file paths, relative to package root (e.g. "./lib.wgsl")
|
|
13
|
+
* values are wgsl/wesl code strings
|
|
14
|
+
*/
|
|
15
|
+
modules: Record<string, string>;
|
|
16
|
+
}
|