wesl 0.6.49 → 0.7.1

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.
Files changed (94) hide show
  1. package/dist/index.d.ts +269 -215
  2. package/dist/index.js +2911 -1539
  3. package/package.json +6 -8
  4. package/src/AbstractElems.ts +81 -81
  5. package/src/Assertions.ts +5 -5
  6. package/src/BindIdents.ts +192 -306
  7. package/src/ClickableError.ts +3 -2
  8. package/src/Conditions.ts +2 -2
  9. package/src/LinkedWesl.ts +1 -1
  10. package/src/Linker.ts +4 -3
  11. package/src/LinkerUtil.ts +1 -1
  12. package/src/Logging.ts +165 -0
  13. package/src/LowerAndEmit.ts +278 -110
  14. package/src/ModuleResolver.ts +15 -25
  15. package/src/ParseError.ts +9 -0
  16. package/src/ParseWESL.ts +30 -94
  17. package/src/RawEmit.ts +1 -4
  18. package/src/Reflection.ts +1 -1
  19. package/src/Scope.ts +3 -0
  20. package/src/Span.ts +2 -0
  21. package/src/SrcMap.ts +208 -0
  22. package/src/Stream.ts +30 -0
  23. package/src/TransformBindingStructs.ts +2 -2
  24. package/src/Util.ts +1 -1
  25. package/src/debug/ASTtoString.ts +84 -135
  26. package/src/discovery/FindUnboundIdents.ts +14 -5
  27. package/src/index.ts +4 -0
  28. package/src/parse/ContentsHelpers.ts +70 -0
  29. package/src/parse/ExpressionUtil.ts +121 -0
  30. package/src/parse/Keywords.ts +12 -12
  31. package/src/parse/OperatorBinding.ts +146 -0
  32. package/src/parse/ParseAttribute.ts +272 -0
  33. package/src/parse/ParseCall.ts +77 -0
  34. package/src/parse/ParseControlFlow.ts +129 -0
  35. package/src/parse/ParseDirective.ts +105 -0
  36. package/src/parse/ParseExpression.ts +288 -0
  37. package/src/parse/ParseFn.ts +151 -0
  38. package/src/parse/ParseGlobalVar.ts +131 -0
  39. package/src/parse/ParseIdent.ts +77 -0
  40. package/src/parse/ParseImport.ts +160 -0
  41. package/src/parse/ParseLocalVar.ts +69 -0
  42. package/src/parse/ParseLoop.ts +112 -0
  43. package/src/parse/ParseModule.ts +116 -0
  44. package/src/parse/ParseSimpleStatement.ts +162 -0
  45. package/src/parse/ParseStatement.ts +215 -0
  46. package/src/parse/ParseStruct.ts +89 -0
  47. package/src/parse/ParseType.ts +71 -0
  48. package/src/parse/ParseUtil.ts +174 -0
  49. package/src/parse/ParseValueDeclaration.ts +130 -0
  50. package/src/parse/ParseWesl.ts +51 -0
  51. package/src/parse/ParsingContext.ts +93 -0
  52. package/src/parse/WeslStream.ts +63 -20
  53. package/src/parse/stream/CachingStream.ts +48 -0
  54. package/src/parse/stream/MatchersStream.ts +85 -0
  55. package/src/parse/stream/RegexHelpers.ts +38 -0
  56. package/src/test/BevyLink.test.ts +100 -0
  57. package/src/test/BindStdTypes.test.ts +110 -0
  58. package/src/test/{BindWESL.test.ts → BindWESLV2.test.ts} +21 -22
  59. package/src/test/BulkTests.test.ts +11 -12
  60. package/src/test/ConditionLinking.test.ts +107 -0
  61. package/src/test/ConditionalElif.test.ts +1 -13
  62. package/src/test/ConditionalTranslationCases.test.ts +5 -0
  63. package/src/test/ErrorLogging.test.ts +2 -2
  64. package/src/test/ImportCasesV2.test.ts +63 -0
  65. package/src/test/LinkFails.test.ts +69 -0
  66. package/src/test/LinkPackage.test.ts +1 -1
  67. package/src/test/Linker.test.ts +75 -2
  68. package/src/test/LogCatcher.ts +53 -0
  69. package/src/test/Mangling.test.ts +1 -1
  70. package/src/test/ParseComments.test.ts +1 -2
  71. package/src/test/{ParseConditions.test.ts → ParseConditionsV2.test.ts} +57 -49
  72. package/src/test/ParseErrorV2.test.ts +73 -0
  73. package/src/test/{ParseWESL.test.ts → ParseWeslV2.test.ts} +288 -370
  74. package/src/test/{ScopeWESL.test.ts → ScopeWESLV2.test.ts} +205 -176
  75. package/src/test/TestLink.ts +51 -51
  76. package/src/test/TestSetup.ts +9 -3
  77. package/src/test/TestUtil.ts +47 -77
  78. package/src/test/TrimmedMatch.ts +40 -0
  79. package/src/test/VirtualModules.test.ts +33 -2
  80. package/src/test/WeslDevice.test.ts +9 -2
  81. package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +67 -0
  82. package/src/test-util.ts +7 -0
  83. package/src/WESLCollect.ts +0 -656
  84. package/src/parse/AttributeGrammar.ts +0 -232
  85. package/src/parse/ImportGrammar.ts +0 -195
  86. package/src/parse/WeslBaseGrammar.ts +0 -11
  87. package/src/parse/WeslExpression.ts +0 -231
  88. package/src/parse/WeslGrammar.ts +0 -739
  89. package/src/test/Expression.test.ts +0 -22
  90. package/src/test/ImportSyntaxCases.test.ts +0 -24
  91. package/src/test/ParseError.test.ts +0 -45
  92. package/src/test/Reflection.test.ts +0 -176
  93. package/src/test/TransformBindingStructs.test.ts +0 -238
  94. /package/src/test/{ParseElif.test.ts → ParseElifV2.test.ts} +0 -0
@@ -1,232 +0,0 @@
1
- import {
2
- delimited,
3
- fn,
4
- opt,
5
- or,
6
- type Parser,
7
- preceded,
8
- repeatPlus,
9
- req,
10
- type Span,
11
- type Stream,
12
- seq,
13
- span,
14
- tagScope,
15
- token,
16
- tokenKind,
17
- tokenOf,
18
- yes,
19
- } from "mini-parse";
20
- import type {
21
- BinaryExpression,
22
- BinaryOperator,
23
- ElifAttribute,
24
- ElseAttribute,
25
- ExpressionElem,
26
- IfAttribute,
27
- Literal,
28
- ParenthesizedExpression,
29
- TranslateTimeExpressionElem,
30
- TranslateTimeFeature,
31
- UnaryExpression,
32
- UnaryOperator,
33
- } from "../AbstractElems.ts";
34
- import { specialAttribute } from "../WESLCollect.ts";
35
- import type { WeslToken } from "./WeslStream.ts";
36
- import { weslExtension } from "./WeslStream.ts";
37
-
38
- // Expression parsers for @if conditions - supports literals (true/false),
39
- // parenthesized expressions, translate-time features, and binary operators (&&, ||)
40
- const attribute_if_primary_expression: Parser<
41
- Stream<WeslToken>,
42
- Literal | ParenthesizedExpression | TranslateTimeFeature
43
- > = or(
44
- tokenOf("keyword", ["true", "false"]).map(makeLiteral),
45
- delimited(
46
- token("symbol", "("),
47
- fn(() => attribute_if_expression),
48
- token("symbol", ")"),
49
- ).map(makeParenthesizedExpression),
50
- tokenKind("word").map(makeTranslateTimeFeature),
51
- );
52
-
53
- const attribute_if_unary_expression: Parser<
54
- Stream<WeslToken>,
55
- ExpressionElem
56
- > = or(
57
- seq(
58
- token("symbol", "!").map(makeUnaryOperator),
59
- fn(() => attribute_if_unary_expression),
60
- ).map(makeUnaryExpression),
61
- attribute_if_primary_expression,
62
- );
63
-
64
- const attribute_if_expression: Parser<
65
- Stream<WeslToken>,
66
- ExpressionElem
67
- > = weslExtension(
68
- seq(
69
- attribute_if_unary_expression,
70
- or(
71
- repeatPlus(
72
- seq(
73
- token("symbol", "||").map(makeBinaryOperator),
74
- req(
75
- attribute_if_unary_expression,
76
- "invalid expression, expected expression",
77
- ),
78
- ),
79
- ),
80
- repeatPlus(
81
- seq(
82
- token("symbol", "&&").map(makeBinaryOperator),
83
- req(
84
- attribute_if_unary_expression,
85
- "invalid expression, expected expression",
86
- ),
87
- ),
88
- ),
89
- yes().map(() => []),
90
- ),
91
- ).map(makeRepeatingBinaryExpression),
92
- );
93
-
94
- /** Base parser for @if attributes without collection - use in seq() compositions */
95
- // prettier-ignore
96
- export const if_attribute_base = preceded(
97
- seq("@", weslExtension("if")),
98
- span(
99
- delimited(
100
- "(",
101
- fn(() => attribute_if_expression),
102
- seq(opt(","), ")"),
103
- ),
104
- ).map(makeTranslateTimeExpressionElem),
105
- )
106
- .map(makeIfAttribute)
107
- .ptag("attr_variant");
108
-
109
- /** Base parser for @elif attributes without collection - use in seq() compositions */
110
- // prettier-ignore
111
- export const elif_attribute_base = preceded(
112
- seq("@", weslExtension("elif")),
113
- span(
114
- delimited(
115
- "(",
116
- fn(() => attribute_if_expression),
117
- seq(opt(","), ")"),
118
- ),
119
- ).map(makeTranslateTimeExpressionElem),
120
- )
121
- .map(makeElifAttribute)
122
- .ptag("attr_variant");
123
-
124
- /** Base parser for @else attributes without collection - use in seq() compositions */
125
- // prettier-ignore
126
- export const else_attribute_base = preceded(
127
- seq("@", weslExtension("else")),
128
- yes,
129
- )
130
- .map(makeElseAttribute)
131
- .ptag("attr_variant");
132
-
133
- /** Collected parser for @if attributes - use standalone, not in seq() */
134
- // prettier-ignore
135
- export const if_attribute = tagScope(
136
- if_attribute_base.collect(specialAttribute),
137
- );
138
-
139
- /** Collected parser for @elif attributes - use standalone, not in seq() */
140
- // prettier-ignore
141
- export const elif_attribute = tagScope(
142
- elif_attribute_base.collect(specialAttribute),
143
- );
144
-
145
- /** Collected parser for @else attributes - use standalone, not in seq() */
146
- // prettier-ignore
147
- export const else_attribute = tagScope(
148
- else_attribute_base.collect(specialAttribute),
149
- );
150
-
151
- // Helper functions
152
- function makeIfAttribute(param: TranslateTimeExpressionElem): IfAttribute {
153
- return { kind: "@if", param };
154
- }
155
-
156
- function makeElifAttribute(param: TranslateTimeExpressionElem): ElifAttribute {
157
- return { kind: "@elif", param };
158
- }
159
-
160
- function makeElseAttribute(): ElseAttribute {
161
- return { kind: "@else" };
162
- }
163
-
164
- function makeTranslateTimeExpressionElem(args: {
165
- value: ExpressionElem;
166
- span: Span;
167
- }): TranslateTimeExpressionElem {
168
- return {
169
- kind: "translate-time-expression",
170
- expression: args.value,
171
- span: args.span,
172
- };
173
- }
174
-
175
- function makeLiteral(token: WeslToken<"keyword" | "number">): Literal {
176
- return {
177
- kind: "literal",
178
- value: token.text,
179
- span: token.span,
180
- };
181
- }
182
-
183
- function makeTranslateTimeFeature(
184
- token: WeslToken<"word">,
185
- ): TranslateTimeFeature {
186
- return {
187
- kind: "translate-time-feature",
188
- name: token.text,
189
- span: token.span,
190
- };
191
- }
192
-
193
- function makeParenthesizedExpression(
194
- expression: ExpressionElem,
195
- ): ParenthesizedExpression {
196
- return {
197
- kind: "parenthesized-expression",
198
- expression,
199
- };
200
- }
201
-
202
- function makeUnaryOperator(token: WeslToken<"symbol">): UnaryOperator {
203
- return { value: token.text as any, span: token.span };
204
- }
205
-
206
- function makeBinaryOperator(token: WeslToken<"symbol">): BinaryOperator {
207
- return { value: token.text as any, span: token.span };
208
- }
209
-
210
- function makeUnaryExpression([operator, expression]: [
211
- UnaryOperator,
212
- ExpressionElem,
213
- ]): UnaryExpression {
214
- return { kind: "unary-expression", operator, expression };
215
- }
216
-
217
- function makeRepeatingBinaryExpression([start, repeating]: [
218
- ExpressionElem,
219
- [BinaryOperator, ExpressionElem][],
220
- ]): ExpressionElem {
221
- let result: ExpressionElem = start;
222
- for (const [op, left] of repeating) {
223
- const binaryExpression: BinaryExpression = {
224
- kind: "binary-expression",
225
- operator: op,
226
- left: result,
227
- right: left,
228
- };
229
- result = binaryExpression;
230
- }
231
- return result;
232
- }
@@ -1,195 +0,0 @@
1
- import {
2
- delimited,
3
- fn,
4
- not,
5
- opt,
6
- or,
7
- type Parser,
8
- preceded,
9
- repeat,
10
- repeatPlus,
11
- req,
12
- type Stream,
13
- seq,
14
- seqObj,
15
- span,
16
- tagScope,
17
- terminated,
18
- tracing,
19
- withSepPlus,
20
- yes,
21
- } from "mini-parse";
22
- import type {
23
- AttributeElem,
24
- ElifAttribute,
25
- ElseAttribute,
26
- IfAttribute,
27
- ImportCollection,
28
- ImportElem,
29
- ImportItem,
30
- ImportSegment,
31
- ImportStatement,
32
- } from "../AbstractElems.ts";
33
- import { assertUnreachable } from "../Assertions.ts";
34
- import { importElem } from "../WESLCollect.ts";
35
- import {
36
- elif_attribute_base,
37
- else_attribute_base,
38
- if_attribute_base,
39
- } from "./AttributeGrammar.ts";
40
- import { keyword, word } from "./WeslBaseGrammar.ts";
41
- import type { WeslToken } from "./WeslStream.ts";
42
-
43
- function makeStatement(
44
- segments: ImportSegment[],
45
- finalSegment: ImportCollection | ImportItem,
46
- ): ImportStatement {
47
- return { kind: "import-statement", segments, finalSegment };
48
- }
49
- function makeSegment(name: string): ImportSegment {
50
- return { kind: "import-segment", name };
51
- }
52
- function makeCollection(subtrees: ImportStatement[]): ImportCollection {
53
- return {
54
- kind: "import-collection",
55
- subtrees,
56
- };
57
- }
58
- function makeItem(name: string, as?: string): ImportItem {
59
- return { kind: "import-item", name, as };
60
- }
61
- function prependSegments(
62
- segments: ImportSegment[],
63
- statement: ImportStatement,
64
- ): ImportStatement {
65
- statement.segments = segments.concat(statement.segments);
66
- return statement;
67
- }
68
-
69
- // forward references for mutual recursion
70
- let import_collection: Parser<
71
- Stream<WeslToken>,
72
- ImportCollection
73
- > = null as any;
74
-
75
- const segment_blacklist = or("super", "package", "import", "as");
76
-
77
- /** words allowed in an import segment (after the package:: or super::super:: part if any) */
78
- const packageWord = preceded(not(segment_blacklist), or(word, keyword));
79
-
80
- const import_path_or_item: Parser<Stream<WeslToken>, ImportStatement> = seq(
81
- packageWord,
82
- or(
83
- preceded(
84
- "::",
85
- req(
86
- or(
87
- fn(() => import_collection),
88
- fn(() => import_path_or_item),
89
- ),
90
- "invalid import, expected '{' or name",
91
- ),
92
- ),
93
- preceded("as", req(word, "invalid alias, expected name")).map(v =>
94
- makeItem("", v),
95
- ),
96
- yes().map(() => makeItem("")), // Optional
97
- ),
98
- // biome-ignore lint/suspicious/useIterableCallbackReturn: biome doesn't recognize assertUnreachable's never return type
99
- ).map(([name, next]): ImportStatement => {
100
- if (next.kind === "import-collection") {
101
- return makeStatement([makeSegment(name)], next);
102
- } else if (next.kind === "import-statement") {
103
- return prependSegments([makeSegment(name)], next);
104
- } else if (next.kind === "import-item") {
105
- next.name = name;
106
- return makeStatement([], next);
107
- } else {
108
- assertUnreachable(next);
109
- }
110
- });
111
-
112
- import_collection = delimited(
113
- "{",
114
- withSepPlus(",", () => import_path_or_item).map(makeCollection),
115
- req("}", "invalid import collection, expected }"),
116
- );
117
-
118
- const import_relative = or(
119
- terminated("package", req("::", "invalid import, expected '::'")).map(v => [
120
- makeSegment(v),
121
- ]),
122
- repeatPlus(
123
- terminated("super", req("::", "invalid import, expected '::'")).map(
124
- makeSegment,
125
- ),
126
- ),
127
- );
128
-
129
- const import_statement_base = delimited(
130
- "import",
131
- seqObj({
132
- relative: opt(import_relative),
133
- collection_or_statement: req(
134
- or(import_collection, import_path_or_item),
135
- "invalid import, expected { or name",
136
- ),
137
- }).map(({ relative, collection_or_statement }): ImportStatement => {
138
- if (collection_or_statement.kind === "import-statement") {
139
- return prependSegments(relative ?? [], collection_or_statement);
140
- } else {
141
- return makeStatement(relative ?? [], collection_or_statement);
142
- }
143
- }),
144
- req(";", "invalid import, expected ';'"),
145
- );
146
-
147
- function wrapAttributes(
148
- rawAttributes: (IfAttribute | ElifAttribute | ElseAttribute)[],
149
- ): AttributeElem[] {
150
- return rawAttributes.map(attribute => ({
151
- kind: "attribute",
152
- attribute,
153
- contents: [],
154
- start: 0,
155
- end: 0,
156
- }));
157
- }
158
-
159
- const import_statement = span(
160
- seq(
161
- repeat(or(if_attribute_base, elif_attribute_base, else_attribute_base)),
162
- import_statement_base,
163
- ),
164
- ).map(({ value: [rawAttributes, imports], span }): ImportElem => {
165
- const importElem: ImportElem = {
166
- kind: "import",
167
- imports,
168
- start: span[0],
169
- end: span[1],
170
- };
171
-
172
- if (rawAttributes.length > 0) {
173
- return { ...importElem, attributes: wrapAttributes(rawAttributes) };
174
- }
175
- return importElem;
176
- });
177
-
178
- /** parse a WESL style wgsl import statement. */
179
- export const weslImports: Parser<Stream<WeslToken>, ImportElem[]> = tagScope(
180
- repeat(import_statement).ptag("owo").collect(importElem),
181
- );
182
-
183
- if (tracing) {
184
- const names: Record<string, Parser<Stream<WeslToken>, unknown>> = {
185
- import_collection,
186
- import_path_or_item,
187
- import_relative,
188
- import_statement,
189
- weslImports,
190
- };
191
-
192
- Object.entries(names).forEach(([name, parser]) => {
193
- parser.setTraceName(name);
194
- });
195
- }
@@ -1,11 +0,0 @@
1
- import { kind, or, withSepPlus } from "mini-parse";
2
- import type { WeslTokenKind } from "./WeslStream";
3
-
4
- export const word = kind<WeslTokenKind>("word");
5
- export const keyword = kind<WeslTokenKind>("keyword");
6
-
7
- export const qualified_ident = withSepPlus(
8
- "::",
9
- or(word, keyword, "package", "super"),
10
- ); // LATER consider efficiency (it's a pretty hot area of the grammar.)
11
- export const number = kind<WeslTokenKind>("number");
@@ -1,231 +0,0 @@
1
- import {
2
- collectArray,
3
- delimited,
4
- fn,
5
- opt,
6
- or,
7
- type Parser,
8
- preceded,
9
- repeat,
10
- repeatPlus,
11
- req,
12
- type Stream,
13
- seq,
14
- tagScope,
15
- tokenOf,
16
- tracing,
17
- withSep,
18
- withSepPlus,
19
- yes,
20
- } from "mini-parse";
21
- import {
22
- expressionCollect,
23
- memberRefCollect,
24
- nameCollect,
25
- refIdent,
26
- stuffCollect,
27
- typeRefCollect,
28
- } from "../WESLCollect.ts";
29
- import { number, qualified_ident, word } from "./WeslBaseGrammar.ts";
30
- import { templateClose, templateOpen, type WeslToken } from "./WeslStream.ts";
31
-
32
- export const opt_template_list = opt(
33
- seq(
34
- templateOpen,
35
- withSepPlus(",", () => template_parameter),
36
- req(templateClose, "invalid template, expected '>'"),
37
- ),
38
- );
39
-
40
- const other_address_space = or("private", "workgroup", "uniform", "function");
41
-
42
- const storage_address_space = seq(
43
- "storage",
44
- opt(seq(",", or("read", "read_write"))),
45
- );
46
-
47
- export const var_template_list = opt(
48
- seq(
49
- templateOpen,
50
- or(storage_address_space, other_address_space),
51
- req(templateClose, "invalid template, expected '>'"),
52
- ),
53
- );
54
-
55
- // prettier-ignore
56
- const template_elaborated_ident = seq(
57
- qualified_ident.collect(refIdent),
58
- opt_template_list,
59
- );
60
- const literal = or("true", "false", number);
61
- const paren_expression = seq(
62
- "(",
63
- () => expression,
64
- req(")", "invalid expression, expected ')'"),
65
- );
66
-
67
- const primary_expression = or(
68
- literal,
69
- paren_expression,
70
- seq(template_elaborated_ident, opt(fn(() => argument_expression_list))),
71
- );
72
- export const component_or_swizzle = repeatPlus(
73
- or(
74
- preceded(".", word),
75
- collectArray(
76
- delimited(
77
- "[",
78
- () => expression,
79
- req("]", "invalid expression, expected ']'"),
80
- ),
81
- ),
82
- ),
83
- );
84
- // LATER Remove
85
- // prettier-ignore
86
- /** parse simple struct.member style references specially, for binding struct lowering */
87
- export const simple_component_reference = tagScope(
88
- seq(
89
- qualified_ident.collect(refIdent, "structRef"),
90
- seq(".", word.collect(nameCollect, "component")),
91
- opt(component_or_swizzle.collect(stuffCollect, "extra_components")),
92
- ).collect(memberRefCollect),
93
- );
94
- const unary_expression: Parser<Stream<WeslToken>, any> = or(
95
- seq(tokenOf("symbol", ["!", "&", "*", "-", "~"]), () => unary_expression),
96
- or(
97
- simple_component_reference,
98
- seq(primary_expression, opt(component_or_swizzle)),
99
- ),
100
- );
101
- const bitwise_post_unary = or(
102
- // LATER I can skip template list discovery in these cases, because a&b<c cannot be a comparison. Must be a template
103
- repeatPlus(seq("&", unary_expression)),
104
- repeatPlus(seq("^", unary_expression)),
105
- repeatPlus(seq("|", unary_expression)),
106
- );
107
- const multiplicative_operator = or("%", "*", "/");
108
- const additive_operator = or("+", "-");
109
- const shift_post_unary = (inTemplate: boolean) => {
110
- const shift_left = seq("<<", unary_expression);
111
- const shift_right = seq(">>", unary_expression);
112
- const mul_add = seq(
113
- repeat(seq(multiplicative_operator, unary_expression)),
114
- repeat(
115
- seq(
116
- additive_operator,
117
- unary_expression,
118
- repeat(seq(multiplicative_operator, unary_expression)),
119
- ),
120
- ),
121
- );
122
- return inTemplate
123
- ? or(shift_left, mul_add)
124
- : or(shift_left, shift_right, mul_add);
125
- };
126
- const relational_post_unary = (inTemplate: boolean) => {
127
- return seq(
128
- shift_post_unary(inTemplate),
129
- opt(
130
- seq(
131
- // '<' is unambiguous, since templates were already caught by the primary expression inside of the previous unary_expression!
132
- inTemplate
133
- ? tokenOf("symbol", ["<", "<=", "!=", "=="])
134
- : tokenOf("symbol", [">", ">=", "<", "<=", "!=", "=="]),
135
- // LATER I can skip template list discovery in this cases, because a>=b<c cannot be a comparison. Must be a template
136
- unary_expression,
137
- shift_post_unary(inTemplate),
138
- ),
139
- ),
140
- );
141
- };
142
-
143
- /** The expression parser exists in two variants
144
- * `true` is template-expression: Refuses to parse parse symbols like `&&` and `||`.
145
- * `false` is maybe-template-expression: Does the template disambiguation.
146
- */
147
- const expressionParser = (
148
- inTemplate: boolean,
149
- ): Parser<Stream<WeslToken>, any> => {
150
- return seq(
151
- unary_expression,
152
- or(
153
- bitwise_post_unary,
154
- seq(
155
- relational_post_unary(inTemplate),
156
- inTemplate
157
- ? // Don't accept || or && in template mode
158
- yes()
159
- : or(
160
- repeatPlus(
161
- seq("||", seq(unary_expression, relational_post_unary(false))),
162
- ),
163
- repeatPlus(
164
- seq("&&", seq(unary_expression, relational_post_unary(false))),
165
- ),
166
- yes().map(() => []),
167
- ),
168
- ),
169
- ),
170
- );
171
- };
172
-
173
- const maybe_template = false;
174
- export const expression = expressionParser(maybe_template);
175
- const is_template = true;
176
- const template_arg_expression = expressionParser(is_template);
177
-
178
- // prettier-ignore
179
- const std_type_specifier = seq(
180
- qualified_ident.collect(refIdent, "typeRefName"),
181
- () => opt_template_list,
182
- ).collect(typeRefCollect);
183
-
184
- // prettier-ignore
185
- export const type_specifier: Parser<Stream<WeslToken>, any> = tagScope(
186
- std_type_specifier,
187
- ).ctag("typeRefElem");
188
-
189
- /** a template_arg_expression with additional collection for parameters
190
- * that are types like array<f32> vs. expressions like 1+2 */
191
- // prettier-ignore
192
- const template_parameter = or(
193
- // LATER Remove this, it's wrong. This should instead be done by inspecting the syntax tree.
194
- type_specifier.ctag("templateParam"),
195
- template_arg_expression.collect(expressionCollect, "templateParam"),
196
- );
197
-
198
- export const argument_expression_list = seq(
199
- "(",
200
- withSep(",", expression),
201
- req(")", "invalid fn arguments, expected ')'"),
202
- );
203
-
204
- if (tracing) {
205
- const names: Record<string, Parser<Stream<WeslToken>, unknown>> = {
206
- opt_template_list,
207
- other_address_space,
208
- storage_address_space,
209
- var_template_list,
210
- template_elaborated_ident,
211
- primary_expression,
212
- literal,
213
- paren_expression,
214
- component_or_swizzle,
215
- simple_component_reference,
216
- unary_expression,
217
- bitwise_post_unary,
218
- multiplicative_operator,
219
- additive_operator,
220
- expression,
221
- template_arg_expression,
222
- std_type_specifier,
223
- type_specifier,
224
- template_parameter,
225
- argument_expression_list,
226
- };
227
-
228
- Object.entries(names).forEach(([name, parser]) => {
229
- parser.setTraceName(name);
230
- });
231
- }