|
Lines 27-33
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec1
|
| 27 |
function parse(program, origin, originKind, lineNumberOffset, text) |
27 |
function parse(program, origin, originKind, lineNumberOffset, text) |
| 28 |
{ |
28 |
{ |
| 29 |
let lexer = new Lexer(origin, originKind, lineNumberOffset, text); |
29 |
let lexer = new Lexer(origin, originKind, lineNumberOffset, text); |
| 30 |
|
30 |
|
| 31 |
// The hardest part of dealing with C-like languages is parsing variable declaration statements. |
31 |
// The hardest part of dealing with C-like languages is parsing variable declaration statements. |
| 32 |
// Let's consider if this happens in WSL. Here are the valid statements in WSL that being with an |
32 |
// Let's consider if this happens in WSL. Here are the valid statements in WSL that being with an |
| 33 |
// identifier, if we assume that any expression can be a standalone statement. |
33 |
// identifier, if we assume that any expression can be a standalone statement. |
|
Lines 61-92
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec2
|
| 61 |
// pointers means that we can still allow function call statements - unlike in C, those cannot |
61 |
// pointers means that we can still allow function call statements - unlike in C, those cannot |
| 62 |
// have arbitrary expressions as the callee. The remaining two problems are solved by |
62 |
// have arbitrary expressions as the callee. The remaining two problems are solved by |
| 63 |
// backtracking. In all other respects, this is a simple recursive descent parser. |
63 |
// backtracking. In all other respects, this is a simple recursive descent parser. |
| 64 |
|
64 |
|
|
|
65 |
function fail(error) |
| 66 |
{ |
| 67 |
return new WSyntaxError(lexer.originString, error); |
| 68 |
} |
| 69 |
|
| 70 |
function backtrackingScope(callback) |
| 71 |
{ |
| 72 |
let state = lexer.state; |
| 73 |
let maybeError = callback(); |
| 74 |
if (maybeError instanceof WSyntaxError) { |
| 75 |
lexer.state = state; |
| 76 |
return null; |
| 77 |
} else |
| 78 |
return maybeError; |
| 79 |
} |
| 80 |
|
| 81 |
function testScope(callback) |
| 82 |
{ |
| 83 |
let state = lexer.state; |
| 84 |
let maybeError = callback(); |
| 85 |
lexer.state = state; |
| 86 |
return !(maybeError instanceof WSyntaxError); |
| 87 |
} |
| 88 |
|
| 65 |
function genericConsume(callback, explanation) |
89 |
function genericConsume(callback, explanation) |
| 66 |
{ |
90 |
{ |
| 67 |
let token = lexer.next(); |
91 |
let token = lexer.next(); |
| 68 |
if (!token) |
92 |
if (!token) |
| 69 |
lexer.fail("Unexpected end of file"); |
93 |
return fail("Unexpected end of file"); |
| 70 |
if (!callback(token)) |
94 |
if (!callback(token)) |
| 71 |
lexer.fail("Unexpected token: " + token.text + "; expected: " + explanation); |
95 |
return fail("Unexpected token: " + token.text + "; expected: " + explanation); |
| 72 |
return token; |
96 |
return token; |
| 73 |
} |
97 |
} |
| 74 |
|
98 |
|
| 75 |
function consume(...texts) |
99 |
function consume(...texts) |
| 76 |
{ |
100 |
{ |
| 77 |
return genericConsume(token => texts.includes(token.text), texts); |
101 |
return genericConsume(token => texts.includes(token.text), texts); |
| 78 |
} |
102 |
} |
| 79 |
|
103 |
|
| 80 |
function consumeKind(kind) |
104 |
function consumeKind(kind) |
| 81 |
{ |
105 |
{ |
| 82 |
return genericConsume(token => token.kind == kind, kind); |
106 |
return genericConsume(token => token.kind == kind, kind); |
| 83 |
} |
107 |
} |
| 84 |
|
108 |
|
| 85 |
function assertNext(...texts) |
109 |
function assertNext(...texts) |
| 86 |
{ |
110 |
{ |
| 87 |
lexer.push(consume(...texts)); |
111 |
let maybeError = consume(...texts); |
|
|
112 |
if (maybeError instanceof WSyntaxError) |
| 113 |
return maybeError; |
| 114 |
lexer.push(maybeError); |
| 88 |
} |
115 |
} |
| 89 |
|
116 |
|
| 90 |
function genericTest(callback) |
117 |
function genericTest(callback) |
| 91 |
{ |
118 |
{ |
| 92 |
let token = lexer.peek(); |
119 |
let token = lexer.peek(); |
|
Lines 94-110
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec3
|
| 94 |
return token; |
121 |
return token; |
| 95 |
return null; |
122 |
return null; |
| 96 |
} |
123 |
} |
| 97 |
|
124 |
|
| 98 |
function test(...texts) |
125 |
function test(...texts) |
| 99 |
{ |
126 |
{ |
| 100 |
return genericTest(token => texts.includes(token.text)); |
127 |
return genericTest(token => texts.includes(token.text)); |
| 101 |
} |
128 |
} |
| 102 |
|
129 |
|
| 103 |
function testKind(kind) |
130 |
function testKind(kind) |
| 104 |
{ |
131 |
{ |
| 105 |
return genericTest(token => token.kind == kind); |
132 |
return genericTest(token => token.kind == kind); |
| 106 |
} |
133 |
} |
| 107 |
|
134 |
|
| 108 |
function tryConsume(...texts) |
135 |
function tryConsume(...texts) |
| 109 |
{ |
136 |
{ |
| 110 |
let result = test(...texts); |
137 |
let result = test(...texts); |
|
Lines 112-118
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec4
|
| 112 |
lexer.next(); |
139 |
lexer.next(); |
| 113 |
return result; |
140 |
return result; |
| 114 |
} |
141 |
} |
| 115 |
|
142 |
|
| 116 |
function tryConsumeKind(kind) |
143 |
function tryConsumeKind(kind) |
| 117 |
{ |
144 |
{ |
| 118 |
let result = testKind(kind); |
145 |
let result = testKind(kind); |
|
Lines 120-135
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec5
|
| 120 |
lexer.next(); |
147 |
lexer.next(); |
| 121 |
return result; |
148 |
return result; |
| 122 |
} |
149 |
} |
| 123 |
|
150 |
|
| 124 |
function consumeEndOfTypeArgs() |
151 |
function consumeEndOfTypeArgs() |
| 125 |
{ |
152 |
{ |
| 126 |
let rightShift = tryConsume(">>"); |
153 |
let rightShift = tryConsume(">>"); |
| 127 |
if (rightShift) |
154 |
if (rightShift) |
| 128 |
lexer.push(new LexerToken(lexer, rightShift, rightShift.index, rightShift.kind, ">")); |
155 |
lexer.push(new LexerToken(lexer, rightShift, rightShift.index, rightShift.kind, ">")); |
| 129 |
else |
156 |
else { |
| 130 |
consume(">"); |
157 |
let maybeError = consume(">"); |
|
|
158 |
if (maybeError instanceof WSyntaxError) |
| 159 |
return maybeError; |
| 160 |
} |
| 131 |
} |
161 |
} |
| 132 |
|
162 |
|
| 133 |
function parseTerm() |
163 |
function parseTerm() |
| 134 |
{ |
164 |
{ |
| 135 |
let token; |
165 |
let token; |
|
Lines 140-152
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec6
|
| 140 |
if (token = tryConsumeKind("intLiteral")) { |
170 |
if (token = tryConsumeKind("intLiteral")) { |
| 141 |
let intVersion = (+token.text) | 0; |
171 |
let intVersion = (+token.text) | 0; |
| 142 |
if ("" + intVersion !== token.text) |
172 |
if ("" + intVersion !== token.text) |
| 143 |
lexer.fail("Integer literal is not an integer: " + token.text); |
173 |
return fail("Integer literal is not an integer: " + token.text); |
| 144 |
return new IntLiteral(token, intVersion); |
174 |
return new IntLiteral(token, intVersion); |
| 145 |
} |
175 |
} |
| 146 |
if (token = tryConsumeKind("uintLiteral")) { |
176 |
if (token = tryConsumeKind("uintLiteral")) { |
| 147 |
let uintVersion = token.text.substr(0, token.text.length - 1) >>> 0; |
177 |
let uintVersion = token.text.substr(0, token.text.length - 1) >>> 0; |
| 148 |
if (uintVersion + "u" !== token.text) |
178 |
if (uintVersion + "u" !== token.text) |
| 149 |
lexer.fail("Integer literal is not 32-bit unsigned integer: " + token.text); |
179 |
return fail("Integer literal is not 32-bit unsigned integer: " + token.text); |
| 150 |
return new UintLiteral(token, uintVersion); |
180 |
return new UintLiteral(token, uintVersion); |
| 151 |
} |
181 |
} |
| 152 |
if ((token = tryConsumeKind("intHexLiteral")) |
182 |
if ((token = tryConsumeKind("intHexLiteral")) |
|
Lines 162-168
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec7
|
| 162 |
else |
192 |
else |
| 163 |
intVersion = intVersion >>> 0; |
193 |
intVersion = intVersion >>> 0; |
| 164 |
if (intVersion.toString(16) !== hexString) |
194 |
if (intVersion.toString(16) !== hexString) |
| 165 |
lexer.fail("Hex integer literal is not an integer: " + token.text); |
195 |
return fail("Hex integer literal is not an integer: " + token.text); |
| 166 |
if (token.kind == "intHexLiteral") |
196 |
if (token.kind == "intHexLiteral") |
| 167 |
return new IntLiteral(token, intVersion); |
197 |
return new IntLiteral(token, intVersion); |
| 168 |
return new UintLiteral(token, intVersion >>> 0); |
198 |
return new UintLiteral(token, intVersion >>> 0); |
|
Lines 178-207
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec8
|
| 178 |
if (token = tryConsume("true", "false")) |
208 |
if (token = tryConsume("true", "false")) |
| 179 |
return new BoolLiteral(token, token.text == "true"); |
209 |
return new BoolLiteral(token, token.text == "true"); |
| 180 |
// FIXME: Need support for other literals too. |
210 |
// FIXME: Need support for other literals too. |
| 181 |
consume("("); |
211 |
let maybeError = consume("("); |
|
|
212 |
if (maybeError instanceof WSyntaxError) |
| 213 |
return maybeError; |
| 182 |
let result = parseExpression(); |
214 |
let result = parseExpression(); |
| 183 |
consume(")"); |
215 |
if (result instanceof WSyntaxError) |
|
|
216 |
return result; |
| 217 |
maybeError = consume(")"); |
| 218 |
if (maybeError instanceof WSyntaxError) |
| 219 |
return maybeError; |
| 184 |
return result; |
220 |
return result; |
| 185 |
} |
221 |
} |
| 186 |
|
222 |
|
| 187 |
function parseConstexpr() |
223 |
function parseConstexpr() |
| 188 |
{ |
224 |
{ |
| 189 |
let token; |
225 |
let token; |
| 190 |
if (token = tryConsume("-")) |
226 |
if (token = tryConsume("-")) { |
| 191 |
return new CallExpression(token, "operator" + token.text, [parseTerm()]); |
227 |
let term = parseTerm(); |
|
|
228 |
if (term instanceof WSyntaxError) |
| 229 |
return term; |
| 230 |
return new CallExpression(token, "operator" + token.text, [term]); |
| 231 |
} |
| 192 |
let left = parseTerm(); |
232 |
let left = parseTerm(); |
| 193 |
if (token = tryConsume(".")) |
233 |
if (left instanceof WSyntaxError) |
| 194 |
left = new DotExpression(token, left, consumeKind("identifier").text); |
234 |
return left; |
|
|
235 |
if (token = tryConsume(".")) { |
| 236 |
let maybeError = consumeKind("identifier") |
| 237 |
if (maybeError instanceof WSyntaxError) |
| 238 |
return maybeError; |
| 239 |
left = new DotExpression(token, left, maybeError.text); |
| 240 |
} |
| 195 |
return left; |
241 |
return left; |
| 196 |
} |
242 |
} |
| 197 |
|
243 |
|
| 198 |
function parseTypeArguments() |
244 |
function parseTypeArguments() |
| 199 |
{ |
245 |
{ |
| 200 |
if (!test("<")) |
246 |
if (!test("<")) |
| 201 |
return []; |
247 |
return []; |
| 202 |
|
248 |
|
| 203 |
let result = []; |
249 |
let result = []; |
| 204 |
consume("<"); |
250 |
let maybeError = consume("<"); |
|
|
251 |
if (maybeError instanceof WSyntaxError) |
| 252 |
return maybeError; |
| 205 |
while (!test(">")) { |
253 |
while (!test(">")) { |
| 206 |
// It's possible for a constexpr or type can syntactically overlap in the single |
254 |
// It's possible for a constexpr or type can syntactically overlap in the single |
| 207 |
// identifier case. Let's consider the possibilities: |
255 |
// identifier case. Let's consider the possibilities: |
|
Lines 214-244
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec9
|
| 214 |
// In the future we'll allow constexprs to do more things, and then we'll still have |
262 |
// In the future we'll allow constexprs to do more things, and then we'll still have |
| 215 |
// the problem that something of the form T[1][2][3]... can either be a type or a |
263 |
// the problem that something of the form T[1][2][3]... can either be a type or a |
| 216 |
// constexpr, and we can figure out in the checker which it is. |
264 |
// constexpr, and we can figure out in the checker which it is. |
| 217 |
let typeRef = lexer.backtrackingScope(() => { |
265 |
let typeRef = backtrackingScope(() => { |
| 218 |
let result = consumeKind("identifier"); |
266 |
let result = consumeKind("identifier"); |
| 219 |
assertNext(",", ">", ">>"); |
267 |
if (result instanceof WSyntaxError) |
|
|
268 |
return result; |
| 269 |
let maybeError = assertNext(",", ">", ">>"); |
| 270 |
if (maybeError instanceof WSyntaxError) |
| 271 |
return maybeError; |
| 220 |
return new TypeRef(result, result.text); |
272 |
return new TypeRef(result, result.text); |
| 221 |
}); |
273 |
}); |
| 222 |
if (typeRef) |
274 |
if (typeRef) |
| 223 |
result.push(typeRef); |
275 |
result.push(typeRef); |
| 224 |
else { |
276 |
else { |
| 225 |
let constexpr = lexer.backtrackingScope(() => { |
277 |
let constexpr = backtrackingScope(() => { |
| 226 |
let result = parseConstexpr(); |
278 |
let result = parseConstexpr(); |
| 227 |
assertNext(",", ">", ">>"); |
279 |
if (result instanceof WSyntaxError) |
|
|
280 |
return result; |
| 281 |
let maybeError = assertNext(",", ">", ">>"); |
| 282 |
if (maybeError instanceof WSyntaxError) |
| 283 |
return maybeError; |
| 228 |
return result; |
284 |
return result; |
| 229 |
}); |
285 |
}); |
| 230 |
if (constexpr) |
286 |
if (constexpr) |
| 231 |
result.push(constexpr); |
287 |
result.push(constexpr); |
| 232 |
else |
288 |
else { |
| 233 |
result.push(parseType()); |
289 |
let type = parseType(); |
|
|
290 |
if (type instanceof WSyntaxError) |
| 291 |
return type; |
| 292 |
result.push(type); |
| 293 |
} |
| 234 |
} |
294 |
} |
| 235 |
if (!tryConsume(",")) |
295 |
if (!tryConsume(",")) |
| 236 |
break; |
296 |
break; |
| 237 |
} |
297 |
} |
| 238 |
consumeEndOfTypeArgs(); |
298 |
maybeError = consumeEndOfTypeArgs(); |
|
|
299 |
if (maybeError instanceof WSyntaxError) |
| 300 |
return maybeError; |
| 239 |
return result; |
301 |
return result; |
| 240 |
} |
302 |
} |
| 241 |
|
303 |
|
| 242 |
function parseType() |
304 |
function parseType() |
| 243 |
{ |
305 |
{ |
| 244 |
let token; |
306 |
let token; |
|
Lines 246-313
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec10
|
| 246 |
let addressSpaceConsumed = false; |
308 |
let addressSpaceConsumed = false; |
| 247 |
if (token = tryConsume(...addressSpaces)) |
309 |
if (token = tryConsume(...addressSpaces)) |
| 248 |
addressSpace = token.text; |
310 |
addressSpace = token.text; |
| 249 |
|
311 |
|
| 250 |
let name = consumeKind("identifier"); |
312 |
let name = consumeKind("identifier"); |
|
|
313 |
if (name instanceof WSyntaxError) |
| 314 |
return name; |
| 251 |
let typeArguments = parseTypeArguments(); |
315 |
let typeArguments = parseTypeArguments(); |
|
|
316 |
if (typeArguments instanceof WSyntaxError) |
| 317 |
return typeArguments; |
| 252 |
let type = new TypeRef(name, name.text, typeArguments); |
318 |
let type = new TypeRef(name, name.text, typeArguments); |
| 253 |
|
319 |
|
| 254 |
function getAddressSpace() |
320 |
function getAddressSpace() |
| 255 |
{ |
321 |
{ |
| 256 |
addressSpaceConsumed = true; |
322 |
addressSpaceConsumed = true; |
| 257 |
if (addressSpace) |
323 |
if (addressSpace) |
| 258 |
return addressSpace; |
324 |
return addressSpace; |
| 259 |
return consume(...addressSpaces).text; |
325 |
let consumedAddressSpace = consume(...addressSpaces); |
|
|
326 |
if (consumedAddressSpace instanceof WSyntaxError) |
| 327 |
return consumedAddressSpace; |
| 328 |
return consumedAddressSpace.text; |
| 260 |
} |
329 |
} |
| 261 |
|
330 |
|
| 262 |
const typeConstructorStack = [ ]; |
331 |
const typeConstructorStack = [ ]; |
| 263 |
|
332 |
|
| 264 |
for (let token; token = tryConsume("*", "[");) { |
333 |
for (let token; token = tryConsume("*", "[");) { |
| 265 |
if (token.text == "*") { |
334 |
if (token.text == "*") { |
| 266 |
// Likewise, the address space must be parsed before parsing continues. |
335 |
// Likewise, the address space must be parsed before parsing continues. |
| 267 |
const addressSpace = getAddressSpace(); |
336 |
const addressSpace = getAddressSpace(); |
|
|
337 |
if (addressSpace instanceof WSyntaxError) |
| 338 |
return addressSpace; |
| 268 |
typeConstructorStack.unshift(type => new PtrType(token, addressSpace, type)); |
339 |
typeConstructorStack.unshift(type => new PtrType(token, addressSpace, type)); |
| 269 |
continue; |
340 |
continue; |
| 270 |
} |
341 |
} |
| 271 |
|
342 |
|
| 272 |
if (tryConsume("]")) { |
343 |
if (tryConsume("]")) { |
| 273 |
const addressSpace = getAddressSpace(); |
344 |
const addressSpace = getAddressSpace(); |
|
|
345 |
if (addressSpace instanceof WSyntaxError) |
| 346 |
return addressSpace; |
| 274 |
typeConstructorStack.unshift(type => new ArrayRefType(token, addressSpace, type)); |
347 |
typeConstructorStack.unshift(type => new ArrayRefType(token, addressSpace, type)); |
| 275 |
continue; |
348 |
continue; |
| 276 |
} |
349 |
} |
| 277 |
|
350 |
|
| 278 |
const lengthExpr = parseConstexpr(); |
351 |
const lengthExpr = parseConstexpr(); |
|
|
352 |
if (lengthExpr instanceof WSyntaxError) |
| 353 |
return lengthExpr; |
| 279 |
typeConstructorStack.unshift(type => new ArrayType(token, type, lengthExpr)); |
354 |
typeConstructorStack.unshift(type => new ArrayType(token, type, lengthExpr)); |
| 280 |
consume("]"); |
355 |
let maybeError = consume("]"); |
|
|
356 |
if (maybeError instanceof WSyntaxError) |
| 357 |
return maybeError; |
| 281 |
} |
358 |
} |
| 282 |
|
359 |
|
| 283 |
for (let constructor of typeConstructorStack) |
360 |
for (let constructor of typeConstructorStack) |
| 284 |
type = constructor(type); |
361 |
type = constructor(type); |
| 285 |
|
362 |
|
| 286 |
if (addressSpace && !addressSpaceConsumed) |
363 |
if (addressSpace && !addressSpaceConsumed) |
| 287 |
lexer.fail("Address space specified for type that does not need address space"); |
364 |
return fail("Address space specified for type that does not need address space"); |
| 288 |
|
365 |
|
| 289 |
return type; |
366 |
return type; |
| 290 |
} |
367 |
} |
| 291 |
|
368 |
|
| 292 |
function parseTypeDef() |
369 |
function parseTypeDef() |
| 293 |
{ |
370 |
{ |
| 294 |
let origin = consume("typedef"); |
371 |
let origin = consume("typedef"); |
| 295 |
let name = consumeKind("identifier").text; |
372 |
if (origin instanceof WSyntaxError) |
| 296 |
consume("="); |
373 |
return origin; |
|
|
374 |
let maybeError = consumeKind("identifier"); |
| 375 |
if (maybeError instanceof WSyntaxError) |
| 376 |
return maybeError; |
| 377 |
let name = maybeError.text; |
| 378 |
maybeError = consume("="); |
| 379 |
if (maybeError instanceof WSyntaxError) |
| 380 |
return maybeError; |
| 297 |
let type = parseType(); |
381 |
let type = parseType(); |
| 298 |
consume(";"); |
382 |
if (type instanceof WSyntaxError) |
|
|
383 |
return type; |
| 384 |
maybeError = consume(";"); |
| 385 |
if (maybeError instanceof WSyntaxError) |
| 386 |
return maybeError; |
| 299 |
return new TypeDef(origin, name, type); |
387 |
return new TypeDef(origin, name, type); |
| 300 |
} |
388 |
} |
| 301 |
|
389 |
|
| 302 |
function genericParseLeft(texts, nextParser, constructor) |
390 |
function genericParseLeft(texts, nextParser, constructor) |
| 303 |
{ |
391 |
{ |
| 304 |
let left = nextParser(); |
392 |
let left = nextParser(); |
|
|
393 |
if (left instanceof WSyntaxError) |
| 394 |
return left; |
| 305 |
let token; |
395 |
let token; |
| 306 |
while (token = tryConsume(...texts)) |
396 |
while (token = tryConsume(...texts)) |
| 307 |
left = constructor(token, left, nextParser()); |
397 |
left = constructor(token, left, nextParser()); |
| 308 |
return left; |
398 |
return left; |
| 309 |
} |
399 |
} |
| 310 |
|
400 |
|
| 311 |
function parseLeftOperatorCall(texts, nextParser) |
401 |
function parseLeftOperatorCall(texts, nextParser) |
| 312 |
{ |
402 |
{ |
| 313 |
return genericParseLeft( |
403 |
return genericParseLeft( |
|
Lines 315-338
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec11
|
| 315 |
(token, left, right) => |
405 |
(token, left, right) => |
| 316 |
new CallExpression(token, "operator" + token.text, [left, right])); |
406 |
new CallExpression(token, "operator" + token.text, [left, right])); |
| 317 |
} |
407 |
} |
| 318 |
|
408 |
|
| 319 |
function parseCallExpression() |
409 |
function parseCallExpression() |
| 320 |
{ |
410 |
{ |
| 321 |
let parseArguments = function(origin, callName) { |
411 |
let parseArguments = function(origin, callName) { |
| 322 |
let argumentList = []; |
412 |
let argumentList = []; |
| 323 |
while (!test(")")) { |
413 |
while (!test(")")) { |
| 324 |
let argument = parsePossibleAssignment(); |
414 |
let argument = parsePossibleAssignment(); |
|
|
415 |
if (argument instanceof WSyntaxError) |
| 416 |
return argument; |
| 325 |
argumentList.push(argument); |
417 |
argumentList.push(argument); |
| 326 |
if (!tryConsume(",")) |
418 |
if (!tryConsume(",")) |
| 327 |
break; |
419 |
break; |
| 328 |
} |
420 |
} |
| 329 |
consume(")"); |
421 |
let maybeError = consume(")"); |
|
|
422 |
if (maybeError instanceof WSyntaxError) |
| 423 |
return maybeError; |
| 330 |
return new CallExpression(origin, callName, argumentList); |
424 |
return new CallExpression(origin, callName, argumentList); |
| 331 |
} |
425 |
} |
| 332 |
|
426 |
|
| 333 |
let name = lexer.backtrackingScope(() => { |
427 |
let name = backtrackingScope(() => { |
| 334 |
let name = consumeKind("identifier"); |
428 |
let name = consumeKind("identifier"); |
| 335 |
consume("("); |
429 |
if (name instanceof WSyntaxError) |
|
|
430 |
return name; |
| 431 |
let maybeError = consume("("); |
| 432 |
if (maybeError instanceof WSyntaxError) |
| 433 |
return maybeError; |
| 336 |
return name; |
434 |
return name; |
| 337 |
}); |
435 |
}); |
| 338 |
|
436 |
|
|
Lines 341-380
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec12
|
| 341 |
return result; |
439 |
return result; |
| 342 |
} else { |
440 |
} else { |
| 343 |
let returnType = parseType(); |
441 |
let returnType = parseType(); |
| 344 |
consume("("); |
442 |
if (returnType instanceof WSyntaxError) |
|
|
443 |
return returnType; |
| 444 |
let maybeError = consume("("); |
| 445 |
if (maybeError instanceof WSyntaxError) |
| 446 |
return maybeError; |
| 345 |
let result = parseArguments(returnType.origin, "operator cast"); |
447 |
let result = parseArguments(returnType.origin, "operator cast"); |
| 346 |
result.setCastData(returnType); |
448 |
result.setCastData(returnType); |
| 347 |
return result; |
449 |
return result; |
| 348 |
} |
450 |
} |
| 349 |
} |
451 |
} |
| 350 |
|
452 |
|
| 351 |
function isCallExpression() |
453 |
function isCallExpression() |
| 352 |
{ |
454 |
{ |
| 353 |
return lexer.testScope(() => { |
455 |
return testScope(() => { |
| 354 |
consumeKind("identifier"); |
456 |
let maybeError = consumeKind("identifier"); |
| 355 |
consume("("); |
457 |
if (maybeError instanceof WSyntaxError) |
| 356 |
}) || lexer.testScope(() => { |
458 |
return maybeError; |
| 357 |
parseType(); |
459 |
maybeError = consume("("); |
| 358 |
consume("("); |
460 |
if (maybeError instanceof WSyntaxError) |
|
|
461 |
return maybeError; |
| 462 |
}) || testScope(() => { |
| 463 |
let type = parseType(); |
| 464 |
if (type instanceof WSyntaxError) |
| 465 |
return type; |
| 466 |
let maybeError = consume("("); |
| 467 |
if (maybeError instanceof WSyntaxError) |
| 468 |
return maybeError; |
| 359 |
}); |
469 |
}); |
| 360 |
} |
470 |
} |
| 361 |
|
471 |
|
| 362 |
function emitIncrement(token, old, extraArg) |
472 |
function emitIncrement(token, old, extraArg) |
| 363 |
{ |
473 |
{ |
| 364 |
let args = [old]; |
474 |
let args = [old]; |
| 365 |
if (extraArg) |
475 |
if (extraArg) |
| 366 |
args.push(extraArg); |
476 |
args.push(extraArg); |
| 367 |
|
477 |
|
| 368 |
let name = "operator" + token.text; |
478 |
let name = "operator" + token.text; |
| 369 |
if (/=$/.test(name)) |
479 |
if (/=$/.test(name)) |
| 370 |
name = RegExp.leftContext; |
480 |
name = RegExp.leftContext; |
| 371 |
|
481 |
|
| 372 |
if (name == "operator") |
482 |
if (name == "operator") |
| 373 |
throw new Error("Invalid name: " + name); |
483 |
throw new Error("Invalid name: " + name); |
| 374 |
|
484 |
|
| 375 |
return new CallExpression(token, name, args); |
485 |
return new CallExpression(token, name, args); |
| 376 |
} |
486 |
} |
| 377 |
|
487 |
|
| 378 |
function finishParsingPostIncrement(token, left) |
488 |
function finishParsingPostIncrement(token, left) |
| 379 |
{ |
489 |
{ |
| 380 |
let readModifyWrite = new ReadModifyWriteExpression(token, left); |
490 |
let readModifyWrite = new ReadModifyWriteExpression(token, left); |
|
Lines 382-388
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec13
|
| 382 |
readModifyWrite.resultExp = readModifyWrite.oldValueRef(); |
492 |
readModifyWrite.resultExp = readModifyWrite.oldValueRef(); |
| 383 |
return readModifyWrite; |
493 |
return readModifyWrite; |
| 384 |
} |
494 |
} |
| 385 |
|
495 |
|
| 386 |
function parseSuffixOperator(left, acceptableOperators) |
496 |
function parseSuffixOperator(left, acceptableOperators) |
| 387 |
{ |
497 |
{ |
| 388 |
let token; |
498 |
let token; |
|
Lines 395-405
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec14
|
| 395 |
case "->": |
505 |
case "->": |
| 396 |
if (token.text == "->") |
506 |
if (token.text == "->") |
| 397 |
left = new DereferenceExpression(token, left); |
507 |
left = new DereferenceExpression(token, left); |
| 398 |
left = new DotExpression(token, left, consumeKind("identifier").text); |
508 |
let maybeError = consumeKind("identifier"); |
|
|
509 |
if (maybeError instanceof WSyntaxError) |
| 510 |
return maybeError; |
| 511 |
left = new DotExpression(token, left, maybeError.text); |
| 399 |
break; |
512 |
break; |
| 400 |
case "[": { |
513 |
case "[": { |
| 401 |
let index = parseExpression(); |
514 |
let index = parseExpression(); |
| 402 |
consume("]"); |
515 |
if (index instanceof WSyntaxError) |
|
|
516 |
return index; |
| 517 |
let maybeError = consume("]"); |
| 518 |
if (maybeError instanceof WSyntaxError) |
| 519 |
return maybeError; |
| 403 |
left = new IndexExpression(token, left, index); |
520 |
left = new IndexExpression(token, left, index); |
| 404 |
break; |
521 |
break; |
| 405 |
} |
522 |
} |
|
Lines 409-415
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec15
|
| 409 |
} |
526 |
} |
| 410 |
return left; |
527 |
return left; |
| 411 |
} |
528 |
} |
| 412 |
|
529 |
|
| 413 |
function parsePossibleSuffix() |
530 |
function parsePossibleSuffix() |
| 414 |
{ |
531 |
{ |
| 415 |
let acceptableOperators = ["++", "--", ".", "->", "["]; |
532 |
let acceptableOperators = ["++", "--", ".", "->", "["]; |
|
Lines 417-429
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec16
|
| 417 |
let left; |
534 |
let left; |
| 418 |
if (isCallExpression()) { |
535 |
if (isCallExpression()) { |
| 419 |
left = parseCallExpression(); |
536 |
left = parseCallExpression(); |
|
|
537 |
if (left instanceof WSyntaxError) |
| 538 |
return left; |
| 420 |
acceptableOperators = limitedOperators; |
539 |
acceptableOperators = limitedOperators; |
| 421 |
} else |
540 |
} else { |
| 422 |
left = parseTerm(); |
541 |
left = parseTerm(); |
| 423 |
|
542 |
if (left instanceof WSyntaxError) |
|
|
543 |
return left; |
| 544 |
} |
| 545 |
|
| 424 |
return parseSuffixOperator(left, acceptableOperators); |
546 |
return parseSuffixOperator(left, acceptableOperators); |
| 425 |
} |
547 |
} |
| 426 |
|
548 |
|
| 427 |
function finishParsingPreIncrement(token, left, extraArg) |
549 |
function finishParsingPreIncrement(token, left, extraArg) |
| 428 |
{ |
550 |
{ |
| 429 |
let readModifyWrite = new ReadModifyWriteExpression(token, left); |
551 |
let readModifyWrite = new ReadModifyWriteExpression(token, left); |
|
Lines 431-484
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec17
|
| 431 |
readModifyWrite.resultExp = readModifyWrite.newValueRef(); |
553 |
readModifyWrite.resultExp = readModifyWrite.newValueRef(); |
| 432 |
return readModifyWrite; |
554 |
return readModifyWrite; |
| 433 |
} |
555 |
} |
| 434 |
|
556 |
|
| 435 |
function parsePreIncrement() |
557 |
function parsePreIncrement() |
| 436 |
{ |
558 |
{ |
| 437 |
let token = consume("++", "--"); |
559 |
let token = consume("++", "--"); |
|
|
560 |
if (token instanceof WSyntaxError) |
| 561 |
return token; |
| 438 |
let left = parsePossiblePrefix(); |
562 |
let left = parsePossiblePrefix(); |
|
|
563 |
if (left instanceof WSyntaxError) |
| 564 |
return left; |
| 439 |
return finishParsingPreIncrement(token, left); |
565 |
return finishParsingPreIncrement(token, left); |
| 440 |
} |
566 |
} |
| 441 |
|
567 |
|
| 442 |
function parsePossiblePrefix() |
568 |
function parsePossiblePrefix() |
| 443 |
{ |
569 |
{ |
| 444 |
let token; |
570 |
let token; |
| 445 |
if (test("++", "--")) |
571 |
if (test("++", "--")) |
| 446 |
return parsePreIncrement(); |
572 |
return parsePreIncrement(); |
| 447 |
if (token = tryConsume("+", "-", "~")) |
573 |
if (token = tryConsume("+", "-", "~")) { |
| 448 |
return new CallExpression(token, "operator" + token.text, [parsePossiblePrefix()]); |
574 |
let possiblePrefix = parsePossiblePrefix(); |
| 449 |
if (token = tryConsume("*")) |
575 |
if (possiblePrefix instanceof WSyntaxError) |
| 450 |
return new DereferenceExpression(token, parsePossiblePrefix()); |
576 |
return WSyntaxError; |
| 451 |
if (token = tryConsume("&")) |
577 |
return new CallExpression(token, "operator" + token.text, [possiblePrefix]); |
| 452 |
return new MakePtrExpression(token, parsePossiblePrefix()); |
578 |
} if (token = tryConsume("*")) { |
| 453 |
if (token = tryConsume("@")) |
579 |
let possiblePrefix = parsePossiblePrefix(); |
| 454 |
return new MakeArrayRefExpression(token, parsePossiblePrefix()); |
580 |
if (possiblePrefix instanceof WSyntaxError) |
| 455 |
if (token = tryConsume("!")) { |
581 |
return WSyntaxError; |
|
|
582 |
return new DereferenceExpression(token, possiblePrefix); |
| 583 |
} if (token = tryConsume("&")) { |
| 584 |
let possiblePrefix = parsePossiblePrefix(); |
| 585 |
if (possiblePrefix instanceof WSyntaxError) |
| 586 |
return WSyntaxError; |
| 587 |
return new MakePtrExpression(token, possiblePrefix); |
| 588 |
} if (token = tryConsume("@")) { |
| 589 |
let possiblePrefix = parsePossiblePrefix(); |
| 590 |
if (possiblePrefix instanceof WSyntaxError) |
| 591 |
return WSyntaxError; |
| 592 |
return new MakeArrayRefExpression(token, possiblePrefix); |
| 593 |
} if (token = tryConsume("!")) { |
| 456 |
let remainder = parsePossiblePrefix(); |
594 |
let remainder = parsePossiblePrefix(); |
|
|
595 |
if (remainder instanceof WSyntaxError) |
| 596 |
return remainder; |
| 457 |
return new LogicalNot(token, new CallExpression(remainder.origin, "bool", [remainder])); |
597 |
return new LogicalNot(token, new CallExpression(remainder.origin, "bool", [remainder])); |
| 458 |
} |
598 |
} |
| 459 |
return parsePossibleSuffix(); |
599 |
return parsePossibleSuffix(); |
| 460 |
} |
600 |
} |
| 461 |
|
601 |
|
| 462 |
function parsePossibleProduct() |
602 |
function parsePossibleProduct() |
| 463 |
{ |
603 |
{ |
| 464 |
return parseLeftOperatorCall(["*", "/", "%"], parsePossiblePrefix); |
604 |
return parseLeftOperatorCall(["*", "/", "%"], parsePossiblePrefix); |
| 465 |
} |
605 |
} |
| 466 |
|
606 |
|
| 467 |
function parsePossibleSum() |
607 |
function parsePossibleSum() |
| 468 |
{ |
608 |
{ |
| 469 |
return parseLeftOperatorCall(["+", "-"], parsePossibleProduct); |
609 |
return parseLeftOperatorCall(["+", "-"], parsePossibleProduct); |
| 470 |
} |
610 |
} |
| 471 |
|
611 |
|
| 472 |
function parsePossibleShift() |
612 |
function parsePossibleShift() |
| 473 |
{ |
613 |
{ |
| 474 |
return parseLeftOperatorCall(["<<", ">>"], parsePossibleSum); |
614 |
return parseLeftOperatorCall(["<<", ">>"], parsePossibleSum); |
| 475 |
} |
615 |
} |
| 476 |
|
616 |
|
| 477 |
function parsePossibleRelationalInequality() |
617 |
function parsePossibleRelationalInequality() |
| 478 |
{ |
618 |
{ |
| 479 |
return parseLeftOperatorCall(["<", ">", "<=", ">="], parsePossibleShift); |
619 |
return parseLeftOperatorCall(["<", ">", "<=", ">="], parsePossibleShift); |
| 480 |
} |
620 |
} |
| 481 |
|
621 |
|
| 482 |
function parsePossibleRelationalEquality() |
622 |
function parsePossibleRelationalEquality() |
| 483 |
{ |
623 |
{ |
| 484 |
return genericParseLeft( |
624 |
return genericParseLeft( |
|
Lines 490-589
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec18
|
| 490 |
return result; |
630 |
return result; |
| 491 |
}); |
631 |
}); |
| 492 |
} |
632 |
} |
| 493 |
|
633 |
|
| 494 |
function parsePossibleBitwiseAnd() |
634 |
function parsePossibleBitwiseAnd() |
| 495 |
{ |
635 |
{ |
| 496 |
return parseLeftOperatorCall(["&"], parsePossibleRelationalEquality); |
636 |
return parseLeftOperatorCall(["&"], parsePossibleRelationalEquality); |
| 497 |
} |
637 |
} |
| 498 |
|
638 |
|
| 499 |
function parsePossibleBitwiseXor() |
639 |
function parsePossibleBitwiseXor() |
| 500 |
{ |
640 |
{ |
| 501 |
return parseLeftOperatorCall(["^"], parsePossibleBitwiseAnd); |
641 |
return parseLeftOperatorCall(["^"], parsePossibleBitwiseAnd); |
| 502 |
} |
642 |
} |
| 503 |
|
643 |
|
| 504 |
function parsePossibleBitwiseOr() |
644 |
function parsePossibleBitwiseOr() |
| 505 |
{ |
645 |
{ |
| 506 |
return parseLeftOperatorCall(["|"], parsePossibleBitwiseXor); |
646 |
return parseLeftOperatorCall(["|"], parsePossibleBitwiseXor); |
| 507 |
} |
647 |
} |
| 508 |
|
648 |
|
| 509 |
function parseLeftLogicalExpression(texts, nextParser) |
649 |
function parseLeftLogicalExpression(texts, nextParser) |
| 510 |
{ |
650 |
{ |
| 511 |
return genericParseLeft( |
651 |
return genericParseLeft( |
| 512 |
texts, nextParser, |
652 |
texts, nextParser, |
| 513 |
(token, left, right) => new LogicalExpression(token, token.text, new CallExpression(left.origin, "bool", [left]), new CallExpression(right.origin, "bool", [right]))); |
653 |
(token, left, right) => new LogicalExpression(token, token.text, new CallExpression(left.origin, "bool", [left]), new CallExpression(right.origin, "bool", [right]))); |
| 514 |
} |
654 |
} |
| 515 |
|
655 |
|
| 516 |
function parsePossibleLogicalAnd() |
656 |
function parsePossibleLogicalAnd() |
| 517 |
{ |
657 |
{ |
| 518 |
return parseLeftLogicalExpression(["&&"], parsePossibleBitwiseOr); |
658 |
return parseLeftLogicalExpression(["&&"], parsePossibleBitwiseOr); |
| 519 |
} |
659 |
} |
| 520 |
|
660 |
|
| 521 |
function parsePossibleLogicalOr() |
661 |
function parsePossibleLogicalOr() |
| 522 |
{ |
662 |
{ |
| 523 |
return parseLeftLogicalExpression(["||"], parsePossibleLogicalAnd); |
663 |
return parseLeftLogicalExpression(["||"], parsePossibleLogicalAnd); |
| 524 |
} |
664 |
} |
| 525 |
|
665 |
|
| 526 |
function parsePossibleTernaryConditional() |
666 |
function parsePossibleTernaryConditional() |
| 527 |
{ |
667 |
{ |
| 528 |
let predicate = parsePossibleLogicalOr(); |
668 |
let predicate = parsePossibleLogicalOr(); |
|
|
669 |
if (predicate instanceof WSyntaxError) |
| 670 |
return predicate; |
| 529 |
let operator = tryConsume("?"); |
671 |
let operator = tryConsume("?"); |
| 530 |
if (!operator) |
672 |
if (!operator) |
| 531 |
return predicate; |
673 |
return predicate; |
| 532 |
let bodyExpression = parsePossibleAssignment(); |
674 |
let bodyExpression = parsePossibleAssignment(); |
| 533 |
consume(":"); |
675 |
if (bodyExpression instanceof WSyntaxError) |
|
|
676 |
return bodyExpression; |
| 677 |
let maybeError = consume(":"); |
| 678 |
if (maybeError instanceof WSyntaxError) |
| 679 |
return maybeError; |
| 534 |
let elseExpression = parsePossibleAssignment(); |
680 |
let elseExpression = parsePossibleAssignment(); |
|
|
681 |
if (elseExpression instanceof WSyntaxError) |
| 682 |
return elseExpression; |
| 535 |
return new TernaryExpression(operator, predicate, bodyExpression, elseExpression); |
683 |
return new TernaryExpression(operator, predicate, bodyExpression, elseExpression); |
| 536 |
} |
684 |
} |
| 537 |
|
685 |
|
| 538 |
function parsePossibleAssignment(mode) |
686 |
function parsePossibleAssignment(mode) |
| 539 |
{ |
687 |
{ |
| 540 |
let lhs = parsePossibleTernaryConditional(); |
688 |
let lhs = parsePossibleTernaryConditional(); |
|
|
689 |
if (lhs instanceof WSyntaxError) |
| 690 |
return lhs; |
| 541 |
let operator = tryConsume("=", "+=", "-=", "*=", "/=", "%=", "^=", "|=", "&="); |
691 |
let operator = tryConsume("=", "+=", "-=", "*=", "/=", "%=", "^=", "|=", "&="); |
| 542 |
if (!operator) { |
692 |
if (!operator) { |
| 543 |
if (mode == "required") |
693 |
if (mode == "required") |
| 544 |
lexer.fail("Expected assignment: " + lexer._text.substring(lexer._index)); |
694 |
return fail("Expected assignment: " + lexer._text.substring(lexer._index)); |
| 545 |
return lhs; |
695 |
return lhs; |
| 546 |
} |
696 |
} |
| 547 |
if (operator.text == "=") |
697 |
if (operator.text == "=") { |
| 548 |
return new Assignment(operator, lhs, parsePossibleAssignment()); |
698 |
let innerAssignment = parsePossibleAssignment(); |
| 549 |
return finishParsingPreIncrement(operator, lhs, parsePossibleAssignment()); |
699 |
if (innerAssignment instanceof WSyntaxError) |
|
|
700 |
return innerAssignment; |
| 701 |
return new Assignment(operator, lhs, innerAssignment); |
| 702 |
} |
| 703 |
let innerAssignment = parsePossibleAssignment(); |
| 704 |
if (innerAssignment instanceof WSyntaxError) |
| 705 |
return innerAssignment; |
| 706 |
return finishParsingPreIncrement(operator, lhs, innerAssignment); |
| 550 |
} |
707 |
} |
| 551 |
|
708 |
|
| 552 |
function parseAssignment() |
709 |
function parseAssignment() |
| 553 |
{ |
710 |
{ |
| 554 |
return parsePossibleAssignment("required"); |
711 |
return parsePossibleAssignment("required"); |
| 555 |
} |
712 |
} |
| 556 |
|
713 |
|
| 557 |
function parsePostIncrement() |
714 |
function parsePostIncrement() |
| 558 |
{ |
715 |
{ |
| 559 |
let left = parseSuffixOperator(parseTerm(), ".", "->", "["); |
716 |
let term = parseTerm(); |
|
|
717 |
if (term instanceof WSyntaxError) |
| 718 |
return term; |
| 719 |
let left = parseSuffixOperator(term, ".", "->", "["); |
| 720 |
if (left instanceof WSyntaxError) |
| 721 |
return left; |
| 560 |
let token = consume("++", "--"); |
722 |
let token = consume("++", "--"); |
|
|
723 |
if (token instanceof WSyntaxError) |
| 724 |
return token; |
| 561 |
return finishParsingPostIncrement(token, left); |
725 |
return finishParsingPostIncrement(token, left); |
| 562 |
} |
726 |
} |
| 563 |
|
727 |
|
| 564 |
function parseEffectfulExpression() |
728 |
function parseEffectfulExpression() |
| 565 |
{ |
729 |
{ |
| 566 |
if (isCallExpression()) |
730 |
if (isCallExpression()) |
| 567 |
return parseCallExpression(); |
731 |
return parseCallExpression(); |
| 568 |
let preIncrement = lexer.backtrackingScope(parsePreIncrement); |
732 |
let preIncrement = backtrackingScope(parsePreIncrement); |
| 569 |
if (preIncrement) |
733 |
if (preIncrement) |
| 570 |
return preIncrement; |
734 |
return preIncrement; |
| 571 |
let postIncrement = lexer.backtrackingScope(parsePostIncrement); |
735 |
let postIncrement = backtrackingScope(parsePostIncrement); |
| 572 |
if (postIncrement) |
736 |
if (postIncrement) |
| 573 |
return postIncrement; |
737 |
return postIncrement; |
| 574 |
return parseAssignment(); |
738 |
return parseAssignment(); |
| 575 |
} |
739 |
} |
| 576 |
|
740 |
|
| 577 |
function genericParseCommaExpression(finalExpressionParser) |
741 |
function genericParseCommaExpression(finalExpressionParser) |
| 578 |
{ |
742 |
{ |
| 579 |
let list = []; |
743 |
let list = []; |
| 580 |
let origin = lexer.peek(); |
744 |
let origin = lexer.peek(); |
| 581 |
if (!origin) |
745 |
if (!origin) |
| 582 |
lexer.fail("Unexpected end of file"); |
746 |
return fail("Unexpected end of file"); |
| 583 |
for (;;) { |
747 |
for (;;) { |
| 584 |
let effectfulExpression = lexer.backtrackingScope(() => { |
748 |
let effectfulExpression = backtrackingScope(() => { |
| 585 |
parseEffectfulExpression(); |
749 |
let effectfulExpression = parseEffectfulExpression(); |
| 586 |
consume(","); |
750 |
if (effectfulExpression instanceof WSyntaxError) |
|
|
751 |
return effectfulExpression; |
| 752 |
let maybeError = consume(","); |
| 753 |
if (maybeError instanceof WSyntaxError) |
| 754 |
return maybeError; |
| 755 |
return effectfulExpression; |
| 587 |
}); |
756 |
}); |
| 588 |
if (!effectfulExpression) { |
757 |
if (!effectfulExpression) { |
| 589 |
let final = finalExpressionParser(); |
758 |
let final = finalExpressionParser(); |
|
Lines 598-686
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec19
|
| 598 |
return list[0]; |
767 |
return list[0]; |
| 599 |
return new CommaExpression(origin, list); |
768 |
return new CommaExpression(origin, list); |
| 600 |
} |
769 |
} |
| 601 |
|
770 |
|
| 602 |
function parseCommaExpression() |
771 |
function parseCommaExpression() |
| 603 |
{ |
772 |
{ |
| 604 |
return genericParseCommaExpression(parsePossibleAssignment); |
773 |
return genericParseCommaExpression(parsePossibleAssignment); |
| 605 |
} |
774 |
} |
| 606 |
|
775 |
|
| 607 |
function parseExpression() |
776 |
function parseExpression() |
| 608 |
{ |
777 |
{ |
| 609 |
return parseCommaExpression(); |
778 |
return parseCommaExpression(); |
| 610 |
} |
779 |
} |
| 611 |
|
780 |
|
| 612 |
function parseEffectfulStatement() |
781 |
function parseEffectfulStatement() |
| 613 |
{ |
782 |
{ |
| 614 |
let result = genericParseCommaExpression(parseEffectfulExpression); |
783 |
let result = genericParseCommaExpression(parseEffectfulExpression); |
| 615 |
consume(";"); |
784 |
if (result instanceof WSyntaxError) |
|
|
785 |
return result; |
| 786 |
let maybeError = consume(";"); |
| 787 |
if (maybeError instanceof WSyntaxError) |
| 788 |
return maybeError; |
| 616 |
return result; |
789 |
return result; |
| 617 |
} |
790 |
} |
| 618 |
|
791 |
|
| 619 |
function parseReturn() |
792 |
function parseReturn() |
| 620 |
{ |
793 |
{ |
| 621 |
let origin = consume("return"); |
794 |
let origin = consume("return"); |
|
|
795 |
if (origin instanceof WSyntaxError) |
| 796 |
return origin; |
| 622 |
if (tryConsume(";")) |
797 |
if (tryConsume(";")) |
| 623 |
return new Return(origin, null); |
798 |
return new Return(origin, null); |
| 624 |
let expression = parseExpression(); |
799 |
let expression = parseExpression(); |
| 625 |
consume(";"); |
800 |
if (expression instanceof WSyntaxError) |
|
|
801 |
return expression; |
| 802 |
let maybeError = consume(";"); |
| 803 |
if (maybeError instanceof WSyntaxError) |
| 804 |
return maybeError; |
| 626 |
return new Return(origin, expression); |
805 |
return new Return(origin, expression); |
| 627 |
} |
806 |
} |
| 628 |
|
807 |
|
| 629 |
function parseBreak() |
808 |
function parseBreak() |
| 630 |
{ |
809 |
{ |
| 631 |
let origin = consume("break"); |
810 |
let origin = consume("break"); |
| 632 |
consume(";"); |
811 |
if (origin instanceof WSyntaxError) |
|
|
812 |
return origin; |
| 813 |
let maybeError = consume(";"); |
| 814 |
if (maybeError instanceof WSyntaxError) |
| 815 |
return maybeError; |
| 633 |
return new Break(origin); |
816 |
return new Break(origin); |
| 634 |
} |
817 |
} |
| 635 |
|
818 |
|
| 636 |
function parseContinue() |
819 |
function parseContinue() |
| 637 |
{ |
820 |
{ |
| 638 |
let origin = consume("continue"); |
821 |
let origin = consume("continue"); |
| 639 |
consume(";"); |
822 |
if (origin instanceof WSyntaxError) |
|
|
823 |
return origin; |
| 824 |
let maybeError = consume(";"); |
| 825 |
if (maybeError instanceof WSyntaxError) |
| 826 |
return maybeError; |
| 640 |
return new Continue(origin); |
827 |
return new Continue(origin); |
| 641 |
} |
828 |
} |
| 642 |
|
829 |
|
| 643 |
function parseIfStatement() |
830 |
function parseIfStatement() |
| 644 |
{ |
831 |
{ |
| 645 |
let origin = consume("if"); |
832 |
let origin = consume("if"); |
| 646 |
consume("("); |
833 |
if (origin instanceof WSyntaxError) |
|
|
834 |
return origin; |
| 835 |
let maybeError = consume("("); |
| 836 |
if (maybeError instanceof WSyntaxError) |
| 837 |
return maybeError; |
| 647 |
let conditional = parseExpression(); |
838 |
let conditional = parseExpression(); |
| 648 |
consume(")"); |
839 |
if (conditional instanceof WSyntaxError) |
|
|
840 |
return conditional; |
| 841 |
maybeError = consume(")"); |
| 842 |
if (maybeError instanceof WSyntaxError) |
| 843 |
return maybeError; |
| 649 |
let body = parseStatement(); |
844 |
let body = parseStatement(); |
|
|
845 |
if (body instanceof WSyntaxError) |
| 846 |
return body; |
| 650 |
let elseBody; |
847 |
let elseBody; |
| 651 |
if (tryConsume("else")) |
848 |
if (tryConsume("else")) { |
| 652 |
elseBody = parseStatement(); |
849 |
elseBody = parseStatement(); |
|
|
850 |
if (elseBody instanceof WSyntaxError) |
| 851 |
return elseBody; |
| 852 |
} |
| 653 |
return new IfStatement(origin, new CallExpression(conditional.origin, "bool", [conditional]), body, elseBody); |
853 |
return new IfStatement(origin, new CallExpression(conditional.origin, "bool", [conditional]), body, elseBody); |
| 654 |
} |
854 |
} |
| 655 |
|
855 |
|
| 656 |
function parseWhile() |
856 |
function parseWhile() |
| 657 |
{ |
857 |
{ |
| 658 |
let origin = consume("while"); |
858 |
let origin = consume("while"); |
| 659 |
consume("("); |
859 |
if (origin instanceof WSyntaxError) |
|
|
860 |
return origin; |
| 861 |
let maybeError = consume("("); |
| 862 |
if (maybeError instanceof WSyntaxError) |
| 863 |
return maybeError; |
| 660 |
let conditional = parseExpression(); |
864 |
let conditional = parseExpression(); |
| 661 |
consume(")"); |
865 |
if (conditional instanceof WSyntaxError) |
|
|
866 |
return conditional; |
| 867 |
maybeError = consume(")"); |
| 868 |
if (maybeError instanceof WSyntaxError) |
| 869 |
return maybeError; |
| 662 |
let body = parseStatement(); |
870 |
let body = parseStatement(); |
|
|
871 |
if (body instanceof WSyntaxError) |
| 872 |
return body; |
| 663 |
return new WhileLoop(origin, new CallExpression(conditional.origin, "bool", [conditional]), body); |
873 |
return new WhileLoop(origin, new CallExpression(conditional.origin, "bool", [conditional]), body); |
| 664 |
} |
874 |
} |
| 665 |
|
875 |
|
| 666 |
function parseFor() |
876 |
function parseFor() |
| 667 |
{ |
877 |
{ |
| 668 |
let origin = consume("for"); |
878 |
let origin = consume("for"); |
| 669 |
consume("("); |
879 |
if (origin instanceof WSyntaxError) |
|
|
880 |
return origin; |
| 881 |
let maybeError = consume("("); |
| 882 |
if (maybeError instanceof WSyntaxError) |
| 883 |
return maybeError; |
| 670 |
let initialization; |
884 |
let initialization; |
| 671 |
if (tryConsume(";")) |
885 |
if (tryConsume(";")) |
| 672 |
initialization = undefined; |
886 |
initialization = undefined; |
| 673 |
else { |
887 |
else { |
| 674 |
initialization = lexer.backtrackingScope(parseVariableDecls); |
888 |
initialization = backtrackingScope(parseVariableDecls); |
| 675 |
if (!initialization) |
889 |
if (!initialization) { |
| 676 |
initialization = parseEffectfulStatement(); |
890 |
initialization = parseEffectfulStatement(); |
|
|
891 |
if (initialization instanceof WSyntaxError) |
| 892 |
return initialization; |
| 893 |
} |
| 677 |
} |
894 |
} |
| 678 |
let condition = tryConsume(";"); |
895 |
let condition = tryConsume(";"); |
| 679 |
if (condition) |
896 |
if (condition) |
| 680 |
condition = undefined; |
897 |
condition = undefined; |
| 681 |
else { |
898 |
else { |
| 682 |
condition = parseExpression(); |
899 |
condition = parseExpression(); |
| 683 |
consume(";"); |
900 |
if (condition instanceof WSyntaxError) |
|
|
901 |
return condition; |
| 902 |
maybeError = consume(";"); |
| 903 |
if (maybeError instanceof WSyntaxError) |
| 904 |
return maybeError; |
| 684 |
condition = new CallExpression(condition.origin, "bool", [condition]); |
905 |
condition = new CallExpression(condition.origin, "bool", [condition]); |
| 685 |
} |
906 |
} |
| 686 |
let increment; |
907 |
let increment; |
|
Lines 688-746
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec20
|
| 688 |
increment = undefined; |
909 |
increment = undefined; |
| 689 |
else { |
910 |
else { |
| 690 |
increment = parseExpression(); |
911 |
increment = parseExpression(); |
| 691 |
consume(")"); |
912 |
if (increment instanceof WSyntaxError) |
|
|
913 |
return increment; |
| 914 |
maybeError = consume(")"); |
| 915 |
if (maybeError instanceof WSyntaxError) |
| 916 |
return maybeError; |
| 692 |
} |
917 |
} |
| 693 |
let body = parseStatement(); |
918 |
let body = parseStatement(); |
|
|
919 |
if (body instanceof WSyntaxError) |
| 920 |
return body; |
| 694 |
return new ForLoop(origin, initialization, condition, increment, body); |
921 |
return new ForLoop(origin, initialization, condition, increment, body); |
| 695 |
} |
922 |
} |
| 696 |
|
923 |
|
| 697 |
function parseDo() |
924 |
function parseDo() |
| 698 |
{ |
925 |
{ |
| 699 |
let origin = consume("do"); |
926 |
let origin = consume("do"); |
|
|
927 |
if (origin instanceof WSyntaxError) |
| 928 |
return origin; |
| 700 |
let body = parseStatement(); |
929 |
let body = parseStatement(); |
| 701 |
consume("while"); |
930 |
if (body instanceof WSyntaxError) |
| 702 |
consume("("); |
931 |
return body; |
|
|
932 |
let maybeError = consume("while"); |
| 933 |
if (maybeError instanceof WSyntaxError) |
| 934 |
return maybeError; |
| 935 |
maybeError = consume("("); |
| 936 |
if (maybeError instanceof WSyntaxError) |
| 937 |
return maybeError; |
| 703 |
let conditional = parseExpression(); |
938 |
let conditional = parseExpression(); |
| 704 |
consume(")"); |
939 |
if (conditional instanceof WSyntaxError) |
|
|
940 |
return conditional; |
| 941 |
maybeError = consume(")"); |
| 942 |
if (maybeError instanceof WSyntaxError) |
| 943 |
return maybeError; |
| 705 |
return new DoWhileLoop(origin, body, new CallExpression(conditional.origin, "bool", [conditional])); |
944 |
return new DoWhileLoop(origin, body, new CallExpression(conditional.origin, "bool", [conditional])); |
| 706 |
} |
945 |
} |
| 707 |
|
946 |
|
| 708 |
function parseVariableDecls() |
947 |
function parseVariableDecls() |
| 709 |
{ |
948 |
{ |
| 710 |
let type = parseType(); |
949 |
let type = parseType(); |
|
|
950 |
if (type instanceof WSyntaxError) |
| 951 |
return type; |
| 711 |
let list = []; |
952 |
let list = []; |
| 712 |
do { |
953 |
do { |
| 713 |
let name = consumeKind("identifier"); |
954 |
let name = consumeKind("identifier"); |
|
|
955 |
if (name instanceof WSyntaxError) |
| 956 |
return name; |
| 714 |
let initializer = tryConsume("=") ? parseExpression() : null; |
957 |
let initializer = tryConsume("=") ? parseExpression() : null; |
|
|
958 |
if (initializer instanceof WSyntaxError) |
| 959 |
return initializer; |
| 715 |
list.push(new VariableDecl(name, name.text, type, initializer)); |
960 |
list.push(new VariableDecl(name, name.text, type, initializer)); |
| 716 |
} while (consume(",", ";").text == ","); |
961 |
let maybeError = consume(",", ";"); |
|
|
962 |
if (maybeError instanceof WSyntaxError) |
| 963 |
return maybeError; |
| 964 |
if (maybeError.text != ",") |
| 965 |
break; |
| 966 |
} while (true); |
| 717 |
return new CommaExpression(type.origin, list); |
967 |
return new CommaExpression(type.origin, list); |
| 718 |
} |
968 |
} |
| 719 |
|
969 |
|
| 720 |
function parseSwitchCase() |
970 |
function parseSwitchCase() |
| 721 |
{ |
971 |
{ |
| 722 |
let token = consume("default", "case"); |
972 |
let token = consume("default", "case"); |
|
|
973 |
if (token instanceof WSyntaxError) |
| 974 |
return token; |
| 723 |
let value; |
975 |
let value; |
| 724 |
if (token.text == "case") |
976 |
if (token.text == "case") { |
| 725 |
value = parseConstexpr(); |
977 |
value = parseConstexpr(); |
| 726 |
consume(":"); |
978 |
if (value instanceof WSyntaxError) |
|
|
979 |
return value; |
| 980 |
} |
| 981 |
let maybeError = consume(":"); |
| 982 |
if (maybeError instanceof WSyntaxError) |
| 983 |
return maybeError; |
| 727 |
let body = parseBlockBody("}", "default", "case"); |
984 |
let body = parseBlockBody("}", "default", "case"); |
|
|
985 |
if (body instanceof WSyntaxError) |
| 986 |
return body; |
| 728 |
return new SwitchCase(token, value, body); |
987 |
return new SwitchCase(token, value, body); |
| 729 |
} |
988 |
} |
| 730 |
|
989 |
|
| 731 |
function parseSwitchStatement() |
990 |
function parseSwitchStatement() |
| 732 |
{ |
991 |
{ |
| 733 |
let origin = consume("switch"); |
992 |
let origin = consume("switch"); |
| 734 |
consume("("); |
993 |
if (origin instanceof WSyntaxError) |
|
|
994 |
return origin; |
| 995 |
let maybeError = consume("("); |
| 996 |
if (maybeError instanceof WSyntaxError) |
| 997 |
return maybeError; |
| 735 |
let value = parseExpression(); |
998 |
let value = parseExpression(); |
| 736 |
consume(")"); |
999 |
if (value instanceof WSyntaxError) |
| 737 |
consume("{"); |
1000 |
return value; |
|
|
1001 |
maybeError = consume(")"); |
| 1002 |
if (maybeError instanceof WSyntaxError) |
| 1003 |
return maybeError; |
| 1004 |
maybeError = consume("{"); |
| 1005 |
if (maybeError instanceof WSyntaxError) |
| 1006 |
return maybeError; |
| 738 |
let result = new SwitchStatement(origin, value); |
1007 |
let result = new SwitchStatement(origin, value); |
| 739 |
while (!tryConsume("}")) |
1008 |
while (!tryConsume("}")) { |
| 740 |
result.add(parseSwitchCase()); |
1009 |
let switchCase = parseSwitchCase(); |
|
|
1010 |
if (switchCase instanceof WSyntaxError) |
| 1011 |
return switchCase; |
| 1012 |
result.add(switchCase); |
| 1013 |
} |
| 741 |
return result; |
1014 |
return result; |
| 742 |
} |
1015 |
} |
| 743 |
|
1016 |
|
| 744 |
function parseStatement() |
1017 |
function parseStatement() |
| 745 |
{ |
1018 |
{ |
| 746 |
let token = lexer.peek(); |
1019 |
let token = lexer.peek(); |
|
Lines 766-842
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec21
|
| 766 |
return parseSwitchStatement(); |
1039 |
return parseSwitchStatement(); |
| 767 |
if (token.text == "trap") { |
1040 |
if (token.text == "trap") { |
| 768 |
let origin = consume("trap"); |
1041 |
let origin = consume("trap"); |
|
|
1042 |
if (origin instanceof WSyntaxError) |
| 1043 |
return origin; |
| 769 |
consume(";"); |
1044 |
consume(";"); |
| 770 |
return new TrapStatement(origin); |
1045 |
return new TrapStatement(origin); |
| 771 |
} |
1046 |
} |
| 772 |
if (token.text == "{") |
1047 |
if (token.text == "{") |
| 773 |
return parseBlock(); |
1048 |
return parseBlock(); |
| 774 |
let variableDecl = lexer.backtrackingScope(parseVariableDecls); |
1049 |
let variableDecl = backtrackingScope(parseVariableDecls); |
| 775 |
if (variableDecl) |
1050 |
if (variableDecl) |
| 776 |
return variableDecl; |
1051 |
return variableDecl; |
| 777 |
return parseEffectfulStatement(); |
1052 |
return parseEffectfulStatement(); |
| 778 |
} |
1053 |
} |
| 779 |
|
1054 |
|
| 780 |
function parseBlockBody(...terminators) |
1055 |
function parseBlockBody(...terminators) |
| 781 |
{ |
1056 |
{ |
| 782 |
let block = new Block(origin); |
1057 |
let block = new Block(origin); |
| 783 |
while (!test(...terminators)) { |
1058 |
while (!test(...terminators)) { |
| 784 |
let statement = parseStatement(); |
1059 |
let statement = parseStatement(); |
|
|
1060 |
if (statement instanceof WSyntaxError) |
| 1061 |
return statement; |
| 785 |
if (statement) |
1062 |
if (statement) |
| 786 |
block.add(statement); |
1063 |
block.add(statement); |
| 787 |
} |
1064 |
} |
| 788 |
return block; |
1065 |
return block; |
| 789 |
} |
1066 |
} |
| 790 |
|
1067 |
|
| 791 |
function parseBlock() |
1068 |
function parseBlock() |
| 792 |
{ |
1069 |
{ |
| 793 |
let origin = consume("{"); |
1070 |
let origin = consume("{"); |
|
|
1071 |
if (origin instanceof WSyntaxError) |
| 1072 |
return origin; |
| 794 |
let block = parseBlockBody("}"); |
1073 |
let block = parseBlockBody("}"); |
| 795 |
consume("}"); |
1074 |
if (block instanceof WSyntaxError) |
|
|
1075 |
return block; |
| 1076 |
let maybeError = consume("}"); |
| 1077 |
if (maybeError instanceof WSyntaxError) |
| 1078 |
return maybeError; |
| 796 |
return block; |
1079 |
return block; |
| 797 |
} |
1080 |
} |
| 798 |
|
1081 |
|
| 799 |
function parseParameter() |
1082 |
function parseParameter() |
| 800 |
{ |
1083 |
{ |
| 801 |
let type = parseType(); |
1084 |
let type = parseType(); |
|
|
1085 |
if (type instanceof WSyntaxError) |
| 1086 |
return type; |
| 802 |
let name = tryConsumeKind("identifier"); |
1087 |
let name = tryConsumeKind("identifier"); |
| 803 |
return new FuncParameter(type.origin, name ? name.text : null, type); |
1088 |
return new FuncParameter(type.origin, name ? name.text : null, type); |
| 804 |
} |
1089 |
} |
| 805 |
|
1090 |
|
| 806 |
function parseParameters() |
1091 |
function parseParameters() |
| 807 |
{ |
1092 |
{ |
| 808 |
consume("("); |
1093 |
let maybeError = consume("("); |
|
|
1094 |
if (maybeError instanceof WSyntaxError) |
| 1095 |
return maybeError; |
| 809 |
let parameters = []; |
1096 |
let parameters = []; |
| 810 |
while (!test(")")) { |
1097 |
while (!test(")")) { |
| 811 |
parameters.push(parseParameter()); |
1098 |
let parameter = parseParameter(); |
|
|
1099 |
if (parameter instanceof WSyntaxError) |
| 1100 |
return parameter; |
| 1101 |
parameters.push(parameter); |
| 812 |
if (!tryConsume(",")) |
1102 |
if (!tryConsume(",")) |
| 813 |
break; |
1103 |
break; |
| 814 |
} |
1104 |
} |
| 815 |
consume(")"); |
1105 |
maybeError = consume(")"); |
|
|
1106 |
if (maybeError instanceof WSyntaxError) |
| 1107 |
return maybeError; |
| 816 |
return parameters; |
1108 |
return parameters; |
| 817 |
} |
1109 |
} |
| 818 |
|
1110 |
|
| 819 |
function parseFuncName() |
1111 |
function parseFuncName() |
| 820 |
{ |
1112 |
{ |
| 821 |
if (tryConsume("operator")) { |
1113 |
if (tryConsume("operator")) { |
| 822 |
let token = consume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "==", "++", "--", ".", "~", "<<", ">>", "["); |
1114 |
let token = consume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "==", "++", "--", ".", "~", "<<", ">>", "["); |
|
|
1115 |
if (token instanceof WSyntaxError) |
| 1116 |
return token; |
| 823 |
if (token.text == "&") { |
1117 |
if (token.text == "&") { |
| 824 |
if (tryConsume("[")) { |
1118 |
if (tryConsume("[")) { |
| 825 |
consume("]"); |
1119 |
let maybeError = consume("]"); |
|
|
1120 |
if (maybeError instanceof WSyntaxError) |
| 1121 |
return maybeError; |
| 826 |
return "operator&[]"; |
1122 |
return "operator&[]"; |
| 827 |
} |
1123 |
} |
| 828 |
if (tryConsume(".")) |
1124 |
if (tryConsume(".")) { |
| 829 |
return "operator&." + consumeKind("identifier").text; |
1125 |
let maybeError = consumeKind("identifier"); |
|
|
1126 |
if (maybeError instanceof WSyntaxError) |
| 1127 |
return maybeError; |
| 1128 |
return "operator&." + maybeError.text; |
| 1129 |
} |
| 830 |
return "operator&"; |
1130 |
return "operator&"; |
| 831 |
} |
1131 |
} |
| 832 |
if (token.text == ".") { |
1132 |
if (token.text == ".") { |
| 833 |
let result = "operator." + consumeKind("identifier").text; |
1133 |
let maybeError = consumeKind("identifier"); |
|
|
1134 |
if (maybeError instanceof WSyntaxError) |
| 1135 |
return maybeError; |
| 1136 |
let result = "operator." + maybeError.text; |
| 834 |
if (tryConsume("=")) |
1137 |
if (tryConsume("=")) |
| 835 |
result += "="; |
1138 |
result += "="; |
| 836 |
return result; |
1139 |
return result; |
| 837 |
} |
1140 |
} |
| 838 |
if (token.text == "[") { |
1141 |
if (token.text == "[") { |
| 839 |
consume("]"); |
1142 |
let maybeError = consume("]"); |
|
|
1143 |
if (maybeError instanceof WSyntaxError) |
| 1144 |
return maybeError; |
| 840 |
let result = "operator[]"; |
1145 |
let result = "operator[]"; |
| 841 |
if (tryConsume("=")) |
1146 |
if (tryConsume("=")) |
| 842 |
result += "="; |
1147 |
result += "="; |
|
Lines 844-850
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec22
|
| 844 |
} |
1149 |
} |
| 845 |
return "operator" + token.text; |
1150 |
return "operator" + token.text; |
| 846 |
} |
1151 |
} |
| 847 |
return consumeKind("identifier").text; |
1152 |
let maybeError = consumeKind("identifier"); |
|
|
1153 |
if (maybeError instanceof WSyntaxError) |
| 1154 |
return maybeError; |
| 1155 |
return maybeError.text; |
| 848 |
} |
1156 |
} |
| 849 |
|
1157 |
|
| 850 |
function parseFuncDecl() |
1158 |
function parseFuncDecl() |
|
Lines 858-984
function parse(program, origin, originKind, lineNumberOffset, text)
a/Tools/WebGPUShadingLanguageRI/Parse.js_sec23
|
| 858 |
if (operatorToken) { |
1166 |
if (operatorToken) { |
| 859 |
origin = operatorToken; |
1167 |
origin = operatorToken; |
| 860 |
returnType = parseType(); |
1168 |
returnType = parseType(); |
|
|
1169 |
if (returnType instanceof WSyntaxError) |
| 1170 |
return returnType; |
| 861 |
name = "operator cast"; |
1171 |
name = "operator cast"; |
| 862 |
isCast = true; |
1172 |
isCast = true; |
| 863 |
} else { |
1173 |
} else { |
| 864 |
shaderType = tryConsume("vertex", "fragment"); |
1174 |
shaderType = tryConsume("vertex", "fragment"); |
| 865 |
returnType = parseType(); |
1175 |
returnType = parseType(); |
|
|
1176 |
if (returnType instanceof WSyntaxError) |
| 1177 |
return returnType; |
| 866 |
if (shaderType) { |
1178 |
if (shaderType) { |
| 867 |
origin = shaderType; |
1179 |
origin = shaderType; |
| 868 |
shaderType = shaderType.text; |
1180 |
shaderType = shaderType.text; |
| 869 |
} else |
1181 |
} else |
| 870 |
origin = returnType.origin; |
1182 |
origin = returnType.origin; |
| 871 |
name = parseFuncName(); |
1183 |
name = parseFuncName(); |
|
|
1184 |
if (name instanceof WSyntaxError) |
| 1185 |
return name; |
| 872 |
isCast = false; |
1186 |
isCast = false; |
| 873 |
} |
1187 |
} |
| 874 |
let parameters = parseParameters(); |
1188 |
let parameters = parseParameters(); |
|
|
1189 |
if (parameters instanceof WSyntaxError) |
| 1190 |
return parameters; |
| 875 |
return new Func(origin, name, returnType, parameters, isCast, shaderType); |
1191 |
return new Func(origin, name, returnType, parameters, isCast, shaderType); |
| 876 |
} |
1192 |
} |
| 877 |
|
1193 |
|
| 878 |
function parseFuncDef() |
1194 |
function parseFuncDef() |
| 879 |
{ |
1195 |
{ |
| 880 |
let func = parseFuncDecl(); |
1196 |
let func = parseFuncDecl(); |
|
|
1197 |
if (func instanceof WSyntaxError) |
| 1198 |
return func; |
| 881 |
let body = parseBlock(); |
1199 |
let body = parseBlock(); |
|
|
1200 |
if (body instanceof WSyntaxError) |
| 1201 |
return body; |
| 882 |
return new FuncDef(func.origin, func.name, func.returnType, func.parameters, body, func.isCast, func.shaderType); |
1202 |
return new FuncDef(func.origin, func.name, func.returnType, func.parameters, body, func.isCast, func.shaderType); |
| 883 |
} |
1203 |
} |
| 884 |
|
1204 |
|
| 885 |
function parseField() |
1205 |
function parseField() |
| 886 |
{ |
1206 |
{ |
| 887 |
let type = parseType(); |
1207 |
let type = parseType(); |
|
|
1208 |
if (type instanceof WSyntaxError) |
| 1209 |
return type; |
| 888 |
let name = consumeKind("identifier"); |
1210 |
let name = consumeKind("identifier"); |
| 889 |
consume(";"); |
1211 |
if (name instanceof WSyntaxError) |
|
|
1212 |
return name; |
| 1213 |
let maybeError = consume(";"); |
| 1214 |
if (maybeError instanceof WSyntaxError) |
| 1215 |
return maybeError; |
| 890 |
return new Field(name, name.text, type); |
1216 |
return new Field(name, name.text, type); |
| 891 |
} |
1217 |
} |
| 892 |
|
1218 |
|
| 893 |
function parseStructType() |
1219 |
function parseStructType() |
| 894 |
{ |
1220 |
{ |
| 895 |
let origin = consume("struct"); |
1221 |
let origin = consume("struct"); |
| 896 |
let name = consumeKind("identifier").text; |
1222 |
if (origin instanceof WSyntaxError) |
| 897 |
let result = new StructType(origin, name); |
1223 |
return origin; |
| 898 |
consume("{"); |
1224 |
let name = consumeKind("identifier"); |
| 899 |
while (!tryConsume("}")) |
1225 |
if (name instanceof WSyntaxError) |
| 900 |
result.add(parseField()); |
1226 |
return name; |
|
|
1227 |
let result = new StructType(origin, name.text); |
| 1228 |
let maybeError = consume("{"); |
| 1229 |
if (maybeError instanceof WSyntaxError) |
| 1230 |
return maybeError; |
| 1231 |
while (!tryConsume("}")) { |
| 1232 |
let field = parseField(); |
| 1233 |
if (field instanceof WSyntaxError) |
| 1234 |
return field; |
| 1235 |
result.add(field); |
| 1236 |
} |
| 901 |
return result; |
1237 |
return result; |
| 902 |
} |
1238 |
} |
| 903 |
|
1239 |
|
| 904 |
function parseNativeFunc() |
1240 |
function parseNativeFunc() |
| 905 |
{ |
1241 |
{ |
| 906 |
let func = parseFuncDecl(); |
1242 |
let func = parseFuncDecl(); |
| 907 |
consume(";"); |
1243 |
if (func instanceof WSyntaxError) |
|
|
1244 |
return func; |
| 1245 |
let maybeError = consume(";"); |
| 1246 |
if (maybeError instanceof WSyntaxError) |
| 1247 |
return maybeError; |
| 908 |
return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType); |
1248 |
return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType); |
| 909 |
} |
1249 |
} |
| 910 |
|
1250 |
|
| 911 |
function parseNative() |
1251 |
function parseNative() |
| 912 |
{ |
1252 |
{ |
| 913 |
let origin = consume("native"); |
1253 |
let origin = consume("native"); |
|
|
1254 |
if (origin instanceof WSyntaxError) |
| 1255 |
return origin; |
| 914 |
if (tryConsume("typedef")) { |
1256 |
if (tryConsume("typedef")) { |
| 915 |
let name = consumeKind("identifier"); |
1257 |
let name = consumeKind("identifier"); |
|
|
1258 |
if (name instanceof WSyntaxError) |
| 1259 |
return name; |
| 916 |
let args = parseTypeArguments(); |
1260 |
let args = parseTypeArguments(); |
| 917 |
consume(";"); |
1261 |
if (args instanceof WSyntaxError) |
|
|
1262 |
return args; |
| 1263 |
let maybeError = consume(";"); |
| 1264 |
if (maybeError instanceof WSyntaxError) |
| 1265 |
return maybeError; |
| 918 |
return NativeType.create(origin, name.text, args); |
1266 |
return NativeType.create(origin, name.text, args); |
| 919 |
} |
1267 |
} |
| 920 |
return parseNativeFunc(); |
1268 |
return parseNativeFunc(); |
| 921 |
} |
1269 |
} |
| 922 |
|
1270 |
|
| 923 |
function parseRestrictedFuncDef() |
1271 |
function parseRestrictedFuncDef() |
| 924 |
{ |
1272 |
{ |
| 925 |
consume("restricted"); |
1273 |
let maybeError = consume("restricted"); |
|
|
1274 |
if (maybeError instanceof WSyntaxError) |
| 1275 |
return maybeError; |
| 926 |
let result; |
1276 |
let result; |
| 927 |
if (tryConsume("native")) |
1277 |
if (tryConsume("native")) { |
| 928 |
result = parseNativeFunc(); |
1278 |
result = parseNativeFunc(); |
| 929 |
else |
1279 |
if (result instanceof WSyntaxError) |
|
|
1280 |
return result; |
| 1281 |
} else { |
| 930 |
result = parseFuncDef(); |
1282 |
result = parseFuncDef(); |
|
|
1283 |
if (result instanceof WSyntaxError) |
| 1284 |
return result; |
| 1285 |
} |
| 931 |
result.isRestricted = true; |
1286 |
result.isRestricted = true; |
| 932 |
return result; |
1287 |
return result; |
| 933 |
} |
1288 |
} |
| 934 |
|
1289 |
|
| 935 |
function parseEnumMember() |
1290 |
function parseEnumMember() |
| 936 |
{ |
1291 |
{ |
| 937 |
let name = consumeKind("identifier"); |
1292 |
let name = consumeKind("identifier"); |
|
|
1293 |
if (name instanceof WSyntaxError) |
| 1294 |
return name; |
| 938 |
let value = null; |
1295 |
let value = null; |
| 939 |
if (tryConsume("=")) |
1296 |
if (tryConsume("=")) { |
| 940 |
value = parseConstexpr(); |
1297 |
value = parseConstexpr(); |
|
|
1298 |
if (value instanceof WSyntaxError) |
| 1299 |
return value; |
| 1300 |
} |
| 941 |
return new EnumMember(name, name.text, value); |
1301 |
return new EnumMember(name, name.text, value); |
| 942 |
} |
1302 |
} |
| 943 |
|
1303 |
|
| 944 |
function parseEnumType() |
1304 |
function parseEnumType() |
| 945 |
{ |
1305 |
{ |
| 946 |
consume("enum"); |
1306 |
let maybeError = consume("enum"); |
|
|
1307 |
if (maybeError instanceof WSyntaxError) |
| 1308 |
return maybeError; |
| 947 |
let name = consumeKind("identifier"); |
1309 |
let name = consumeKind("identifier"); |
|
|
1310 |
if (name instanceof WSyntaxError) |
| 1311 |
return name; |
| 948 |
let baseType; |
1312 |
let baseType; |
| 949 |
if (tryConsume(":")) |
1313 |
if (tryConsume(":")) { |
| 950 |
baseType = parseType(); |
1314 |
baseType = parseType(); |
| 951 |
else |
1315 |
if (baseType instanceof WSyntaxError) |
|
|
1316 |
return baseType; |
| 1317 |
} else |
| 952 |
baseType = new TypeRef(name, "int"); |
1318 |
baseType = new TypeRef(name, "int"); |
| 953 |
consume("{"); |
1319 |
maybeError = consume("{"); |
|
|
1320 |
if (maybeError instanceof WSyntaxError) |
| 1321 |
return maybeError; |
| 954 |
let result = new EnumType(name, name.text, baseType); |
1322 |
let result = new EnumType(name, name.text, baseType); |
| 955 |
while (!test("}")) { |
1323 |
while (!test("}")) { |
| 956 |
result.add(parseEnumMember()); |
1324 |
let enumMember = parseEnumMember(); |
|
|
1325 |
if (enumMember instanceof WSyntaxError) |
| 1326 |
return enumMember; |
| 1327 |
result.add(enumMember); |
| 957 |
if (!tryConsume(",")) |
1328 |
if (!tryConsume(",")) |
| 958 |
break; |
1329 |
break; |
| 959 |
} |
1330 |
} |
| 960 |
consume("}"); |
1331 |
maybeError = consume("}"); |
|
|
1332 |
if (maybeError instanceof WSyntaxError) |
| 1333 |
return maybeError; |
| 961 |
return result; |
1334 |
return result; |
| 962 |
} |
1335 |
} |
| 963 |
|
1336 |
|
| 964 |
for (;;) { |
1337 |
for (;;) { |
| 965 |
let token = lexer.peek(); |
1338 |
let token = lexer.peek(); |
| 966 |
if (!token) |
1339 |
if (!token) |
| 967 |
return; |
1340 |
return; |
| 968 |
if (token.text == ";") |
1341 |
if (token.text == ";") |
| 969 |
lexer.next(); |
1342 |
lexer.next(); |
| 970 |
else if (token.text == "typedef") |
1343 |
else if (token.text == "typedef") { |
| 971 |
program.add(parseTypeDef()); |
1344 |
let typeDef = parseTypeDef(); |
| 972 |
else if (originKind == "native" && token.text == "native") |
1345 |
if (typeDef instanceof WSyntaxError) |
| 973 |
program.add(parseNative()); |
1346 |
throw typeDef; |
| 974 |
else if (originKind == "native" && token.text == "restricted") |
1347 |
program.add(typeDef); |
| 975 |
program.add(parseRestrictedFuncDef()); |
1348 |
} else if (originKind == "native" && token.text == "native") { |
| 976 |
else if (token.text == "struct") |
1349 |
let native = parseNative(); |
| 977 |
program.add(parseStructType()); |
1350 |
if (native instanceof WSyntaxError) |
| 978 |
else if (token.text == "enum") |
1351 |
throw native; |
| 979 |
program.add(parseEnumType()); |
1352 |
program.add(native); |
| 980 |
else |
1353 |
} else if (originKind == "native" && token.text == "restricted") { |
| 981 |
program.add(parseFuncDef()); |
1354 |
let restrictedFuncDef = parseRestrictedFuncDef(); |
|
|
1355 |
if (restrictedFuncDef instanceof WSyntaxError) |
| 1356 |
throw restrictedFuncDef; |
| 1357 |
program.add(restrictedFuncDef); |
| 1358 |
} else if (token.text == "struct") { |
| 1359 |
let struct = parseStructType(); |
| 1360 |
if (struct instanceof WSyntaxError) |
| 1361 |
throw struct; |
| 1362 |
program.add(struct); |
| 1363 |
} else if (token.text == "enum") { |
| 1364 |
let enumType = parseEnumType(); |
| 1365 |
if (enumType instanceof WSyntaxError) |
| 1366 |
throw enumType; |
| 1367 |
program.add(enumType); |
| 1368 |
} else { |
| 1369 |
let funcDef = parseFuncDef(); |
| 1370 |
if (funcDef instanceof WSyntaxError) |
| 1371 |
throw funcDef; |
| 1372 |
program.add(funcDef); |
| 1373 |
} |
| 982 |
} |
1374 |
} |
| 983 |
} |
1375 |
} |
| 984 |
|
1376 |
|