blob: 17ec82083d1d70413adca05f91cedeca0a196e06 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
2//Copyright (C) 2016 Google, Inc.
3//
4//All rights reserved.
5//
6//Redistribution and use in source and binary forms, with or without
7//modification, are permitted provided that the following conditions
8//are met:
9//
10// Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//
13// Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following
15// disclaimer in the documentation and/or other materials provided
16// with the distribution.
17//
18// Neither the name of Google, Inc., nor the names of its
19// contributors may be used to endorse or promote products derived
20// from this software without specific prior written permission.
21//
22//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33//POSSIBILITY OF SUCH DAMAGE.
34//
35
John Kessenichd016be12016-03-13 11:24:20 -060036//
37// This is a set of mutually recursive methods implementing the HLSL grammar.
38// Generally, each returns
39// - through an argument: a type specifically appropriate to which rule it
40// recognized
41// - through the return value: true/false to indicate whether or not it
42// recognized its rule
43//
44// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060045// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060046// will build the AST.
47//
48// The next token, yet to be "accepted" is always sitting in 'token'.
49// When a method says it accepts a rule, that means all tokens involved
50// in the rule will have been consumed, and none left in 'token'.
51//
52
John Kesseniche01a9bc2016-03-12 20:11:22 -070053#include "hlslTokens.h"
54#include "hlslGrammar.h"
55
56namespace glslang {
57
58// Root entry point to this recursive decent parser.
59// Return true if compilation unit was successfully accepted.
60bool HlslGrammar::parse()
61{
62 advanceToken();
63 return acceptCompilationUnit();
64}
65
66void HlslGrammar::expected(const char* syntax)
67{
68 parseContext.error(token.loc, "Expected", syntax, "");
69}
70
John Kessenichaecd4972016-03-14 10:46:34 -060071// Only process the next token if it is an identifier.
72// Return true if it was an identifier.
73bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
74{
75 if (peekTokenClass(EHTokIdentifier)) {
76 idToken = token;
77 advanceToken();
78 return true;
79 }
80
81 return false;
82}
83
John Kesseniche01a9bc2016-03-12 20:11:22 -070084// compilationUnit
85// : list of externalDeclaration
86//
87bool HlslGrammar::acceptCompilationUnit()
88{
John Kessenichd016be12016-03-13 11:24:20 -060089 TIntermNode* unitNode = nullptr;
90
John Kessenich9c86c6a2016-05-03 22:49:24 -060091 while (! peekTokenClass(EHTokNone)) {
John Kessenichd016be12016-03-13 11:24:20 -060092 // externalDeclaration
93 TIntermNode* declarationNode;
94 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -070095 return false;
John Kessenichd016be12016-03-13 11:24:20 -060096
97 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -060098 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -070099 }
100
John Kessenichd016be12016-03-13 11:24:20 -0600101 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600102 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600103
John Kesseniche01a9bc2016-03-12 20:11:22 -0700104 return true;
105}
106
107// declaration
John Kessenich078d7f22016-03-14 10:02:11 -0600108// : SEMICOLON
109// : fully_specified_type SEMICOLON
John Kessenich19b92ff2016-06-19 11:50:34 -0600110// | fully_specified_type identifier array_specifier post_decls (EQUAL expression)opt SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600111// | fully_specified_type identifier function_parameters post_decls SEMICOLON // function prototype
112// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
John Kessenich87142c72016-03-12 20:24:24 -0700113//
John Kessenichd016be12016-03-13 11:24:20 -0600114// 'node' could get created if the declaration creates code, like an initializer
115// or a function body.
116//
117bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700118{
John Kessenichd016be12016-03-13 11:24:20 -0600119 node = nullptr;
120
John Kessenich87142c72016-03-12 20:24:24 -0700121 // fully_specified_type
122 TType type;
123 if (! acceptFullySpecifiedType(type))
124 return false;
125
126 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600127 HlslToken idToken;
128 if (acceptIdentifier(idToken)) {
John Kessenich19b92ff2016-06-19 11:50:34 -0600129 // array_specifier
130 TArraySizes* arraySizes = nullptr;
131 acceptArraySpecifier(arraySizes);
132
133 // post_decls
John Kessenich630dd7d2016-06-12 23:52:12 -0600134 acceptPostDecls(type);
John Kessenich19b92ff2016-06-19 11:50:34 -0600135
136 // EQUAL expression
John Kessenich87142c72016-03-12 20:24:24 -0700137 TIntermTyped* expressionNode = nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -0600138 if (acceptTokenClass(EHTokAssign)) {
John Kessenich87142c72016-03-12 20:24:24 -0700139 if (! acceptExpression(expressionNode)) {
140 expected("initializer");
141 return false;
142 }
143 }
144
John Kessenich078d7f22016-03-14 10:02:11 -0600145 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700146 if (acceptTokenClass(EHTokSemicolon)) {
John Kessenich19b92ff2016-06-19 11:50:34 -0600147 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, arraySizes, expressionNode);
John Kessenich87142c72016-03-12 20:24:24 -0700148 return true;
149 }
John Kessenich5f934b02016-03-13 17:58:25 -0600150
151 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600152 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600153 if (acceptFunctionParameters(*function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600154 // post_decls
155 acceptPostDecls(type);
John Kessenich078d7f22016-03-14 10:02:11 -0600156
John Kessenich5f934b02016-03-13 17:58:25 -0600157 // compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600158 if (peekTokenClass(EHTokLeftBrace))
John Kessenich5f934b02016-03-13 17:58:25 -0600159 return acceptFunctionDefinition(*function, node);
160
John Kessenich078d7f22016-03-14 10:02:11 -0600161 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600162 if (acceptTokenClass(EHTokSemicolon))
163 return true;
164
165 return false;
166 }
John Kessenich87142c72016-03-12 20:24:24 -0700167 }
168
John Kessenich078d7f22016-03-14 10:02:11 -0600169 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700170 if (acceptTokenClass(EHTokSemicolon))
171 return true;
172
John Kesseniche01a9bc2016-03-12 20:11:22 -0700173 return true;
174}
175
John Kessenich87142c72016-03-12 20:24:24 -0700176// fully_specified_type
177// : type_specifier
178// | type_qualifier type_specifier
179//
180bool HlslGrammar::acceptFullySpecifiedType(TType& type)
181{
182 // type_qualifier
183 TQualifier qualifier;
184 qualifier.clear();
185 acceptQualifier(qualifier);
186
187 // type_specifier
188 if (! acceptType(type))
189 return false;
190 type.getQualifier() = qualifier;
191
192 return true;
193}
194
John Kessenich630dd7d2016-06-12 23:52:12 -0600195// type_qualifier
196// : qualifier qualifier ...
197//
198// Zero or more of these, so this can't return false.
199//
John Kessenich87142c72016-03-12 20:24:24 -0700200void HlslGrammar::acceptQualifier(TQualifier& qualifier)
201{
John Kessenich630dd7d2016-06-12 23:52:12 -0600202 do {
203 switch (peek()) {
204 case EHTokStatic:
205 // normal glslang default
206 break;
207 case EHTokExtern:
208 // TODO: no meaning in glslang?
209 break;
210 case EHTokShared:
211 // TODO: hint
212 break;
213 case EHTokGroupShared:
214 qualifier.storage = EvqShared;
215 break;
216 case EHTokUniform:
217 qualifier.storage = EvqUniform;
218 break;
219 case EHTokConst:
220 qualifier.storage = EvqConst;
221 break;
222 case EHTokVolatile:
223 qualifier.volatil = true;
224 break;
225 case EHTokLinear:
226 qualifier.storage = EvqVaryingIn;
227 qualifier.smooth = true;
228 break;
229 case EHTokCentroid:
230 qualifier.centroid = true;
231 break;
232 case EHTokNointerpolation:
233 qualifier.flat = true;
234 break;
235 case EHTokNoperspective:
236 qualifier.nopersp = true;
237 break;
238 case EHTokSample:
239 qualifier.sample = true;
240 break;
241 case EHTokRowMajor:
242 qualifier.layoutMatrix = ElmRowMajor;
243 break;
244 case EHTokColumnMajor:
245 qualifier.layoutMatrix = ElmColumnMajor;
246 break;
247 case EHTokPrecise:
248 qualifier.noContraction = true;
249 break;
250 default:
251 return;
252 }
253 advanceToken();
254 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700255}
256
257// If token is for a type, update 'type' with the type information,
258// and return true and advance.
259// Otherwise, return false, and don't advance
260bool HlslGrammar::acceptType(TType& type)
261{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600262 switch (peek()) {
John Kesseniche6e74942016-06-11 16:43:14 -0600263 case EHTokStruct:
264 return acceptStruct(type);
265 break;
266
267 case EHTokIdentifier:
268 // An identifier could be for a user-defined type.
269 // Note we cache the symbol table lookup, to save for a later rule
270 // when this is not a type.
271 token.symbol = parseContext.symbolTable.find(*token.string);
272 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
273 type.shallowCopy(token.symbol->getType());
274 advanceToken();
275 return true;
276 } else
277 return false;
278
John Kessenich71351de2016-06-08 12:50:56 -0600279 case EHTokVoid:
280 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700281 break;
John Kessenich71351de2016-06-08 12:50:56 -0600282
John Kessenich87142c72016-03-12 20:24:24 -0700283 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600284 new(&type) TType(EbtFloat);
285 break;
John Kessenich87142c72016-03-12 20:24:24 -0700286 case EHTokFloat1:
287 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600288 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700289 break;
John Kessenich87142c72016-03-12 20:24:24 -0700290 case EHTokFloat2:
291 new(&type) TType(EbtFloat, EvqTemporary, 2);
292 break;
293 case EHTokFloat3:
294 new(&type) TType(EbtFloat, EvqTemporary, 3);
295 break;
296 case EHTokFloat4:
297 new(&type) TType(EbtFloat, EvqTemporary, 4);
298 break;
299
John Kessenich71351de2016-06-08 12:50:56 -0600300 case EHTokDouble:
301 new(&type) TType(EbtDouble);
302 break;
303 case EHTokDouble1:
304 new(&type) TType(EbtDouble);
305 type.makeVector();
306 break;
307 case EHTokDouble2:
308 new(&type) TType(EbtDouble, EvqTemporary, 2);
309 break;
310 case EHTokDouble3:
311 new(&type) TType(EbtDouble, EvqTemporary, 3);
312 break;
313 case EHTokDouble4:
314 new(&type) TType(EbtDouble, EvqTemporary, 4);
315 break;
316
317 case EHTokInt:
318 case EHTokDword:
319 new(&type) TType(EbtInt);
320 break;
321 case EHTokInt1:
322 new(&type) TType(EbtInt);
323 type.makeVector();
324 break;
John Kessenich87142c72016-03-12 20:24:24 -0700325 case EHTokInt2:
326 new(&type) TType(EbtInt, EvqTemporary, 2);
327 break;
328 case EHTokInt3:
329 new(&type) TType(EbtInt, EvqTemporary, 3);
330 break;
331 case EHTokInt4:
332 new(&type) TType(EbtInt, EvqTemporary, 4);
333 break;
334
John Kessenich71351de2016-06-08 12:50:56 -0600335 case EHTokUint:
336 new(&type) TType(EbtUint);
337 break;
338 case EHTokUint1:
339 new(&type) TType(EbtUint);
340 type.makeVector();
341 break;
342 case EHTokUint2:
343 new(&type) TType(EbtUint, EvqTemporary, 2);
344 break;
345 case EHTokUint3:
346 new(&type) TType(EbtUint, EvqTemporary, 3);
347 break;
348 case EHTokUint4:
349 new(&type) TType(EbtUint, EvqTemporary, 4);
350 break;
351
352 case EHTokBool:
353 new(&type) TType(EbtBool);
354 break;
355 case EHTokBool1:
356 new(&type) TType(EbtBool);
357 type.makeVector();
358 break;
John Kessenich87142c72016-03-12 20:24:24 -0700359 case EHTokBool2:
360 new(&type) TType(EbtBool, EvqTemporary, 2);
361 break;
362 case EHTokBool3:
363 new(&type) TType(EbtBool, EvqTemporary, 3);
364 break;
365 case EHTokBool4:
366 new(&type) TType(EbtBool, EvqTemporary, 4);
367 break;
368
John Kessenich0133c122016-05-20 12:17:26 -0600369 case EHTokInt1x1:
370 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
371 break;
372 case EHTokInt1x2:
373 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
374 break;
375 case EHTokInt1x3:
376 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
377 break;
378 case EHTokInt1x4:
379 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
380 break;
381 case EHTokInt2x1:
382 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
383 break;
384 case EHTokInt2x2:
385 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
386 break;
387 case EHTokInt2x3:
388 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
389 break;
390 case EHTokInt2x4:
391 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
392 break;
393 case EHTokInt3x1:
394 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
395 break;
396 case EHTokInt3x2:
397 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
398 break;
399 case EHTokInt3x3:
400 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
401 break;
402 case EHTokInt3x4:
403 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
404 break;
405 case EHTokInt4x1:
406 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
407 break;
408 case EHTokInt4x2:
409 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
410 break;
411 case EHTokInt4x3:
412 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
413 break;
414 case EHTokInt4x4:
415 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
416 break;
417
John Kessenich71351de2016-06-08 12:50:56 -0600418 case EHTokUint1x1:
419 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
420 break;
421 case EHTokUint1x2:
422 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
423 break;
424 case EHTokUint1x3:
425 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
426 break;
427 case EHTokUint1x4:
428 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
429 break;
430 case EHTokUint2x1:
431 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
432 break;
433 case EHTokUint2x2:
434 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
435 break;
436 case EHTokUint2x3:
437 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
438 break;
439 case EHTokUint2x4:
440 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
441 break;
442 case EHTokUint3x1:
443 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
444 break;
445 case EHTokUint3x2:
446 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
447 break;
448 case EHTokUint3x3:
449 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
450 break;
451 case EHTokUint3x4:
452 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
453 break;
454 case EHTokUint4x1:
455 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
456 break;
457 case EHTokUint4x2:
458 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
459 break;
460 case EHTokUint4x3:
461 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
462 break;
463 case EHTokUint4x4:
464 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
465 break;
466
467 case EHTokBool1x1:
468 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
469 break;
470 case EHTokBool1x2:
471 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
472 break;
473 case EHTokBool1x3:
474 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
475 break;
476 case EHTokBool1x4:
477 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
478 break;
479 case EHTokBool2x1:
480 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
481 break;
482 case EHTokBool2x2:
483 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
484 break;
485 case EHTokBool2x3:
486 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
487 break;
488 case EHTokBool2x4:
489 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
490 break;
491 case EHTokBool3x1:
492 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
493 break;
494 case EHTokBool3x2:
495 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
496 break;
497 case EHTokBool3x3:
498 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
499 break;
500 case EHTokBool3x4:
501 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
502 break;
503 case EHTokBool4x1:
504 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
505 break;
506 case EHTokBool4x2:
507 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
508 break;
509 case EHTokBool4x3:
510 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
511 break;
512 case EHTokBool4x4:
513 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
514 break;
515
John Kessenich0133c122016-05-20 12:17:26 -0600516 case EHTokFloat1x1:
517 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
518 break;
519 case EHTokFloat1x2:
520 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
521 break;
522 case EHTokFloat1x3:
523 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
524 break;
525 case EHTokFloat1x4:
526 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
527 break;
528 case EHTokFloat2x1:
529 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
530 break;
John Kessenich87142c72016-03-12 20:24:24 -0700531 case EHTokFloat2x2:
532 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
533 break;
534 case EHTokFloat2x3:
535 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
536 break;
537 case EHTokFloat2x4:
538 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
539 break;
John Kessenich0133c122016-05-20 12:17:26 -0600540 case EHTokFloat3x1:
541 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
542 break;
John Kessenich87142c72016-03-12 20:24:24 -0700543 case EHTokFloat3x2:
544 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
545 break;
546 case EHTokFloat3x3:
547 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
548 break;
549 case EHTokFloat3x4:
550 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
551 break;
John Kessenich0133c122016-05-20 12:17:26 -0600552 case EHTokFloat4x1:
553 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
554 break;
John Kessenich87142c72016-03-12 20:24:24 -0700555 case EHTokFloat4x2:
556 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
557 break;
558 case EHTokFloat4x3:
559 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
560 break;
561 case EHTokFloat4x4:
562 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
563 break;
564
John Kessenich0133c122016-05-20 12:17:26 -0600565 case EHTokDouble1x1:
566 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
567 break;
568 case EHTokDouble1x2:
569 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
570 break;
571 case EHTokDouble1x3:
572 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
573 break;
574 case EHTokDouble1x4:
575 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
576 break;
577 case EHTokDouble2x1:
578 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
579 break;
580 case EHTokDouble2x2:
581 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
582 break;
583 case EHTokDouble2x3:
584 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
585 break;
586 case EHTokDouble2x4:
587 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
588 break;
589 case EHTokDouble3x1:
590 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
591 break;
592 case EHTokDouble3x2:
593 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
594 break;
595 case EHTokDouble3x3:
596 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
597 break;
598 case EHTokDouble3x4:
599 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
600 break;
601 case EHTokDouble4x1:
602 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
603 break;
604 case EHTokDouble4x2:
605 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
606 break;
607 case EHTokDouble4x3:
608 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
609 break;
610 case EHTokDouble4x4:
611 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
612 break;
613
John Kessenich87142c72016-03-12 20:24:24 -0700614 default:
615 return false;
616 }
617
618 advanceToken();
619
620 return true;
621}
622
John Kesseniche6e74942016-06-11 16:43:14 -0600623// struct
624// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE
625// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE
626//
627bool HlslGrammar::acceptStruct(TType& type)
628{
629 // STRUCT
630 if (! acceptTokenClass(EHTokStruct))
631 return false;
632
633 // IDENTIFIER
634 TString structName = "";
635 if (peekTokenClass(EHTokIdentifier)) {
636 structName = *token.string;
637 advanceToken();
638 }
639
640 // LEFT_BRACE
641 if (! acceptTokenClass(EHTokLeftBrace)) {
642 expected("{");
643 return false;
644 }
645
646 // struct_declaration_list
647 TTypeList* typeList;
648 if (! acceptStructDeclarationList(typeList)) {
649 expected("struct member declarations");
650 return false;
651 }
652
653 // RIGHT_BRACE
654 if (! acceptTokenClass(EHTokRightBrace)) {
655 expected("}");
656 return false;
657 }
658
659 // create the user-defined type
660 new(&type) TType(typeList, structName);
661
662 // If it was named, which means it can be reused later, add
663 // it to the symbol table.
664 if (structName.size() > 0) {
665 TVariable* userTypeDef = new TVariable(&structName, type, true);
666 if (! parseContext.symbolTable.insert(*userTypeDef))
667 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
668 }
669
670 return true;
671}
672
673// struct_declaration_list
674// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
675//
676// struct_declaration
677// : fully_specified_type struct_declarator COMMA struct_declarator ...
678//
679// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -0600680// : IDENTIFIER post_decls
681// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -0600682//
683bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
684{
685 typeList = new TTypeList();
686
687 do {
688 // success on seeing the RIGHT_BRACE coming up
689 if (peekTokenClass(EHTokRightBrace))
690 return true;
691
692 // struct_declaration
693
694 // fully_specified_type
695 TType memberType;
696 if (! acceptFullySpecifiedType(memberType)) {
697 expected("member type");
698 return false;
699 }
700
701 // struct_declarator COMMA struct_declarator ...
702 do {
703 // peek IDENTIFIER
704 if (! peekTokenClass(EHTokIdentifier)) {
705 expected("member name");
706 return false;
707 }
708
709 // add it to the list of members
710 TTypeLoc member = { new TType(EbtVoid), token.loc };
711 member.type->shallowCopy(memberType);
712 member.type->setFieldName(*token.string);
713 typeList->push_back(member);
714
715 // accept IDENTIFIER
716 advanceToken();
717
718 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -0600719 TArraySizes* arraySizes = nullptr;
720 acceptArraySpecifier(arraySizes);
721 if (arraySizes)
722 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -0600723
John Kessenich630dd7d2016-06-12 23:52:12 -0600724 acceptPostDecls(*member.type);
725
John Kesseniche6e74942016-06-11 16:43:14 -0600726 // success on seeing the SEMICOLON coming up
727 if (peekTokenClass(EHTokSemicolon))
728 break;
729
730 // COMMA
731 if (! acceptTokenClass(EHTokComma)) {
732 expected(",");
733 return false;
734 }
735
736 } while (true);
737
738 // SEMI_COLON
739 if (! acceptTokenClass(EHTokSemicolon)) {
740 expected(";");
741 return false;
742 }
743
744 } while (true);
745}
746
John Kessenich5f934b02016-03-13 17:58:25 -0600747// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600748// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -0600749// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600750//
751bool HlslGrammar::acceptFunctionParameters(TFunction& function)
752{
John Kessenich078d7f22016-03-14 10:02:11 -0600753 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600754 if (! acceptTokenClass(EHTokLeftParen))
755 return false;
756
John Kessenich71351de2016-06-08 12:50:56 -0600757 // VOID RIGHT_PAREN
758 if (! acceptTokenClass(EHTokVoid)) {
759 do {
760 // parameter_declaration
761 if (! acceptParameterDeclaration(function))
762 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600763
John Kessenich71351de2016-06-08 12:50:56 -0600764 // COMMA
765 if (! acceptTokenClass(EHTokComma))
766 break;
767 } while (true);
768 }
John Kessenich5f934b02016-03-13 17:58:25 -0600769
John Kessenich078d7f22016-03-14 10:02:11 -0600770 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600771 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600772 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -0600773 return false;
774 }
775
776 return true;
777}
778
779// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -0600780// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -0600781// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -0600782//
783bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
784{
785 // fully_specified_type
786 TType* type = new TType;
787 if (! acceptFullySpecifiedType(*type))
788 return false;
789
790 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600791 HlslToken idToken;
792 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600793
John Kessenich19b92ff2016-06-19 11:50:34 -0600794 // array_specifier
795 TArraySizes* arraySizes = nullptr;
796 acceptArraySpecifier(arraySizes);
797 if (arraySizes)
798 type->newArraySizes(*arraySizes);
799
800 // post_decls
John Kessenichc3387d32016-06-17 14:21:02 -0600801 acceptPostDecls(*type);
802
John Kessenich5aa59e22016-06-17 15:50:47 -0600803 parseContext.paramFix(*type);
804
John Kessenichaecd4972016-03-14 10:46:34 -0600805 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600806 function.addParameter(param);
807
808 return true;
809}
810
811// Do the work to create the function definition in addition to
812// parsing the body (compound_statement).
813bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
814{
815 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
816
John Kessenich077e0522016-06-09 02:02:17 -0600817 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600818 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
819
820 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600821 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600822 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600823 node = intermediate.growAggregate(node, functionBody);
824 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600825 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600826 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600827
828 return true;
829 }
830
831 return false;
832}
833
John Kessenich0d2b6de2016-06-05 11:23:11 -0600834// Accept an expression with parenthesis around it, where
835// the parenthesis ARE NOT expression parenthesis, but the
836// syntactically required ones like in "if ( expression )"
837//
838// Note this one is not set up to be speculative; as it gives
839// errors if not found.
840//
841bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
842{
843 // LEFT_PAREN
844 if (! acceptTokenClass(EHTokLeftParen))
845 expected("(");
846
847 if (! acceptExpression(expression)) {
848 expected("expression");
849 return false;
850 }
851
852 // RIGHT_PAREN
853 if (! acceptTokenClass(EHTokRightParen))
854 expected(")");
855
856 return true;
857}
858
John Kessenich34fb0362016-05-03 23:17:20 -0600859// The top-level full expression recognizer.
860//
John Kessenich87142c72016-03-12 20:24:24 -0700861// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600862// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700863//
864bool HlslGrammar::acceptExpression(TIntermTyped*& node)
865{
LoopDawgef764a22016-06-03 09:17:51 -0600866 node = nullptr;
867
John Kessenich34fb0362016-05-03 23:17:20 -0600868 // assignment_expression
869 if (! acceptAssignmentExpression(node))
870 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600871
John Kessenich34fb0362016-05-03 23:17:20 -0600872 if (! peekTokenClass(EHTokComma))
873 return true;
874
875 do {
876 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600877 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600878 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600879
John Kessenich34fb0362016-05-03 23:17:20 -0600880 // ... assignment_expression
881 TIntermTyped* rightNode = nullptr;
882 if (! acceptAssignmentExpression(rightNode)) {
883 expected("assignment expression");
884 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600885 }
886
John Kessenich34fb0362016-05-03 23:17:20 -0600887 node = intermediate.addComma(node, rightNode, loc);
888
889 if (! peekTokenClass(EHTokComma))
890 return true;
891 } while (true);
892}
893
894// Accept an assignment expression, where assignment operations
895// associate right-to-left. This is, it is implicit, for example
896//
897// a op (b op (c op d))
898//
899// assigment_expression
900// : binary_expression op binary_expression op binary_expression ...
901//
902bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
903{
904 if (! acceptBinaryExpression(node, PlLogicalOr))
905 return false;
906
907 TOperator assignOp = HlslOpMap::assignment(peek());
908 if (assignOp == EOpNull)
909 return true;
910
911 // ... op
912 TSourceLoc loc = token.loc;
913 advanceToken();
914
915 // ... binary_expression
916 // But, done by recursing this function, which automatically
917 // gets the right-to-left associativity.
918 TIntermTyped* rightNode = nullptr;
919 if (! acceptAssignmentExpression(rightNode)) {
920 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600921 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700922 }
923
John Kessenich34fb0362016-05-03 23:17:20 -0600924 node = intermediate.addAssign(assignOp, node, rightNode, loc);
925
926 if (! peekTokenClass(EHTokComma))
927 return true;
928
929 return true;
930}
931
932// Accept a binary expression, for binary operations that
933// associate left-to-right. This is, it is implicit, for example
934//
935// ((a op b) op c) op d
936//
937// binary_expression
938// : expression op expression op expression ...
939//
940// where 'expression' is the next higher level in precedence.
941//
942bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
943{
944 if (precedenceLevel > PlMul)
945 return acceptUnaryExpression(node);
946
947 // assignment_expression
948 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
949 return false;
950
951 TOperator op = HlslOpMap::binary(peek());
952 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
953 if (tokenLevel < precedenceLevel)
954 return true;
955
956 do {
957 // ... op
958 TSourceLoc loc = token.loc;
959 advanceToken();
960
961 // ... expression
962 TIntermTyped* rightNode = nullptr;
963 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
964 expected("expression");
965 return false;
966 }
967
968 node = intermediate.addBinaryMath(op, node, rightNode, loc);
969
970 if (! peekTokenClass(EHTokComma))
971 return true;
972 } while (true);
973}
974
975// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -0600976// : (type) unary_expression
977// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -0600978// | - unary_expression
979// | ! unary_expression
980// | ~ unary_expression
981// | ++ unary_expression
982// | -- unary_expression
983// | postfix_expression
984//
985bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
986{
John Kessenich1cc1a282016-06-03 16:55:49 -0600987 // (type) unary_expression
988 // Have to look two steps ahead, because this could be, e.g., a
989 // postfix_expression instead, since that also starts with at "(".
990 if (acceptTokenClass(EHTokLeftParen)) {
991 TType castType;
992 if (acceptType(castType)) {
993 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600994 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -0600995 return false;
996 }
997
998 // We've matched "(type)" now, get the expression to cast
999 TSourceLoc loc = token.loc;
1000 if (! acceptUnaryExpression(node))
1001 return false;
1002
1003 // Hook it up like a constructor
1004 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1005 if (constructorFunction == nullptr) {
1006 expected("type that can be constructed");
1007 return false;
1008 }
1009 TIntermTyped* arguments = nullptr;
1010 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1011 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1012
1013 return true;
1014 } else {
1015 // This isn't a type cast, but it still started "(", so if it is a
1016 // unary expression, it can only be a postfix_expression, so try that.
1017 // Back it up first.
1018 recedeToken();
1019 return acceptPostfixExpression(node);
1020 }
1021 }
1022
1023 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001024 TOperator unaryOp = HlslOpMap::preUnary(peek());
1025
John Kessenich1cc1a282016-06-03 16:55:49 -06001026 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001027 if (unaryOp == EOpNull)
1028 return acceptPostfixExpression(node);
1029
1030 // op unary_expression
1031 TSourceLoc loc = token.loc;
1032 advanceToken();
1033 if (! acceptUnaryExpression(node))
1034 return false;
1035
1036 // + is a no-op
1037 if (unaryOp == EOpAdd)
1038 return true;
1039
1040 node = intermediate.addUnaryMath(unaryOp, node, loc);
1041
1042 return node != nullptr;
1043}
1044
1045// postfix_expression
1046// : LEFT_PAREN expression RIGHT_PAREN
1047// | literal
1048// | constructor
1049// | identifier
1050// | function_call
1051// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1052// | postfix_expression DOT IDENTIFIER
1053// | postfix_expression INC_OP
1054// | postfix_expression DEC_OP
1055//
1056bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1057{
1058 // Not implemented as self-recursive:
1059 // The logical "right recursion" is done with an loop at the end
1060
1061 // idToken will pick up either a variable or a function name in a function call
1062 HlslToken idToken;
1063
John Kessenich21472ae2016-06-04 11:46:33 -06001064 // Find something before the postfix operations, as they can't operate
1065 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001066 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001067 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001068 if (! acceptExpression(node)) {
1069 expected("expression");
1070 return false;
1071 }
1072 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001073 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001074 return false;
1075 }
John Kessenich34fb0362016-05-03 23:17:20 -06001076 } else if (acceptLiteral(node)) {
1077 // literal (nothing else to do yet), go on to the
1078 } else if (acceptConstructor(node)) {
1079 // constructor (nothing else to do yet)
1080 } else if (acceptIdentifier(idToken)) {
1081 // identifier or function_call name
1082 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001083 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001084 } else if (acceptFunctionCall(idToken, node)) {
1085 // function_call (nothing else to do yet)
1086 } else {
1087 expected("function call arguments");
1088 return false;
1089 }
John Kessenich21472ae2016-06-04 11:46:33 -06001090 } else {
1091 // nothing found, can't post operate
1092 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001093 }
1094
John Kessenich21472ae2016-06-04 11:46:33 -06001095 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001096 do {
1097 TSourceLoc loc = token.loc;
1098 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001099
John Kessenich34fb0362016-05-03 23:17:20 -06001100 // Consume only a valid post-unary operator, otherwise we are done.
1101 switch (postOp) {
1102 case EOpIndexDirectStruct:
1103 case EOpIndexIndirect:
1104 case EOpPostIncrement:
1105 case EOpPostDecrement:
1106 advanceToken();
1107 break;
1108 default:
1109 return true;
1110 }
John Kessenich87142c72016-03-12 20:24:24 -07001111
John Kessenich34fb0362016-05-03 23:17:20 -06001112 // We have a valid post-unary operator, process it.
1113 switch (postOp) {
1114 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001115 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001116 // DOT IDENTIFIER
1117 // includes swizzles and struct members
1118 // TODO: possibly includes "method" syntax
John Kessenich93a162a2016-06-17 17:16:27 -06001119 HlslToken field;
1120 if (! acceptIdentifier(field)) {
1121 expected("swizzle or member");
1122 return false;
1123 }
1124 node = parseContext.handleDotDereference(field.loc, node, *field.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001125 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001126 }
John Kessenich34fb0362016-05-03 23:17:20 -06001127 case EOpIndexIndirect:
1128 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001129 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001130 TIntermTyped* indexNode = nullptr;
1131 if (! acceptExpression(indexNode) ||
1132 ! peekTokenClass(EHTokRightBracket)) {
1133 expected("expression followed by ']'");
1134 return false;
1135 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001136 advanceToken();
1137 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1138 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001139 }
1140 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001141 // INC_OP
1142 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001143 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001144 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001145 node = intermediate.addUnaryMath(postOp, node, loc);
1146 break;
1147 default:
1148 assert(0);
1149 break;
1150 }
1151 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001152}
1153
John Kessenichd016be12016-03-13 11:24:20 -06001154// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001155// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001156//
1157bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1158{
1159 // type
1160 TType type;
1161 if (acceptType(type)) {
1162 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1163 if (constructorFunction == nullptr)
1164 return false;
1165
1166 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001167 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001168 if (! acceptArguments(constructorFunction, arguments)) {
1169 expected("constructor arguments");
1170 return false;
1171 }
1172
1173 // hook it up
1174 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1175
1176 return true;
1177 }
1178
1179 return false;
1180}
1181
John Kessenich34fb0362016-05-03 23:17:20 -06001182// The function_call identifier was already recognized, and passed in as idToken.
1183//
1184// function_call
1185// : [idToken] arguments
1186//
John Kessenich4678ca92016-05-13 09:33:42 -06001187bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001188{
John Kessenich4678ca92016-05-13 09:33:42 -06001189 // arguments
1190 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1191 TIntermTyped* arguments = nullptr;
1192 if (! acceptArguments(function, arguments))
1193 return false;
1194
1195 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1196
1197 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001198}
1199
John Kessenich87142c72016-03-12 20:24:24 -07001200// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001201// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001202//
John Kessenichd016be12016-03-13 11:24:20 -06001203// The arguments are pushed onto the 'function' argument list and
1204// onto the 'arguments' aggregate.
1205//
John Kessenich4678ca92016-05-13 09:33:42 -06001206bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001207{
John Kessenich078d7f22016-03-14 10:02:11 -06001208 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001209 if (! acceptTokenClass(EHTokLeftParen))
1210 return false;
1211
1212 do {
John Kessenichd016be12016-03-13 11:24:20 -06001213 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001214 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001215 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001216 break;
John Kessenichd016be12016-03-13 11:24:20 -06001217
1218 // hook it up
1219 parseContext.handleFunctionArgument(function, arguments, arg);
1220
John Kessenich078d7f22016-03-14 10:02:11 -06001221 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001222 if (! acceptTokenClass(EHTokComma))
1223 break;
1224 } while (true);
1225
John Kessenich078d7f22016-03-14 10:02:11 -06001226 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001227 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001228 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001229 return false;
1230 }
1231
1232 return true;
1233}
1234
1235bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1236{
1237 switch (token.tokenClass) {
1238 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001239 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001240 break;
1241 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001242 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001243 break;
1244 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001245 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001246 break;
1247 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001248 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001249 break;
1250
1251 default:
1252 return false;
1253 }
1254
1255 advanceToken();
1256
1257 return true;
1258}
1259
John Kessenich5f934b02016-03-13 17:58:25 -06001260// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001261// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001262//
John Kessenich21472ae2016-06-04 11:46:33 -06001263bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001264{
John Kessenich21472ae2016-06-04 11:46:33 -06001265 TIntermAggregate* compoundStatement = nullptr;
1266
John Kessenich34fb0362016-05-03 23:17:20 -06001267 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001268 if (! acceptTokenClass(EHTokLeftBrace))
1269 return false;
1270
1271 // statement statement ...
1272 TIntermNode* statement = nullptr;
1273 while (acceptStatement(statement)) {
1274 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001275 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001276 }
John Kessenich34fb0362016-05-03 23:17:20 -06001277 if (compoundStatement)
1278 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001279
John Kessenich21472ae2016-06-04 11:46:33 -06001280 retStatement = compoundStatement;
1281
John Kessenich34fb0362016-05-03 23:17:20 -06001282 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001283 return acceptTokenClass(EHTokRightBrace);
1284}
1285
John Kessenich0d2b6de2016-06-05 11:23:11 -06001286bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1287{
1288 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001289 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001290 parseContext.popScope();
1291
1292 return result;
1293}
1294
John Kessenich077e0522016-06-09 02:02:17 -06001295bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001296{
John Kessenich077e0522016-06-09 02:02:17 -06001297 parseContext.pushScope();
1298 bool result = acceptCompoundStatement(statement);
1299 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001300
1301 return result;
1302}
1303
John Kessenich5f934b02016-03-13 17:58:25 -06001304// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001305// : attributes attributed_statement
1306//
1307// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001308// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001309// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001310// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001311// | declaration_statement
1312// | selection_statement
1313// | switch_statement
1314// | case_label
1315// | iteration_statement
1316// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001317//
1318bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1319{
John Kessenich21472ae2016-06-04 11:46:33 -06001320 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001321
John Kessenich21472ae2016-06-04 11:46:33 -06001322 // attributes
1323 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001324
John Kessenich21472ae2016-06-04 11:46:33 -06001325 // attributed_statement
1326 switch (peek()) {
1327 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001328 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001329
John Kessenich21472ae2016-06-04 11:46:33 -06001330 case EHTokIf:
1331 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001332
John Kessenich21472ae2016-06-04 11:46:33 -06001333 case EHTokSwitch:
1334 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001335
John Kessenich21472ae2016-06-04 11:46:33 -06001336 case EHTokFor:
1337 case EHTokDo:
1338 case EHTokWhile:
1339 return acceptIterationStatement(statement);
1340
1341 case EHTokContinue:
1342 case EHTokBreak:
1343 case EHTokDiscard:
1344 case EHTokReturn:
1345 return acceptJumpStatement(statement);
1346
1347 case EHTokCase:
1348 return acceptCaseLabel(statement);
1349
1350 case EHTokSemicolon:
1351 return acceptTokenClass(EHTokSemicolon);
1352
1353 case EHTokRightBrace:
1354 // Performance: not strictly necessary, but stops a bunch of hunting early,
1355 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001356 return false;
1357
John Kessenich21472ae2016-06-04 11:46:33 -06001358 default:
1359 {
1360 // declaration
1361 if (acceptDeclaration(statement))
1362 return true;
1363
1364 // expression
1365 TIntermTyped* node;
1366 if (acceptExpression(node))
1367 statement = node;
1368 else
1369 return false;
1370
1371 // SEMICOLON (following an expression)
1372 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001373 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001374 return false;
1375 }
1376 }
1377 }
1378
John Kessenich5f934b02016-03-13 17:58:25 -06001379 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001380}
1381
John Kessenich21472ae2016-06-04 11:46:33 -06001382// attributes
1383// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1384//
1385// attribute:
1386// : UNROLL
1387// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1388// | FASTOPT
1389// | ALLOW_UAV_CONDITION
1390// | BRANCH
1391// | FLATTEN
1392// | FORCECASE
1393// | CALL
1394//
1395void HlslGrammar::acceptAttributes()
1396{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001397 // For now, accept the [ XXX(X) ] syntax, but drop.
1398 // TODO: subset to correct set? Pass on?
1399 do {
1400 // LEFT_BRACKET?
1401 if (! acceptTokenClass(EHTokLeftBracket))
1402 return;
1403
1404 // attribute
1405 if (peekTokenClass(EHTokIdentifier)) {
1406 // 'token.string' is the attribute
1407 advanceToken();
1408 } else if (! peekTokenClass(EHTokRightBracket)) {
1409 expected("identifier");
1410 advanceToken();
1411 }
1412
1413 // (x)
1414 if (acceptTokenClass(EHTokLeftParen)) {
1415 TIntermTyped* node;
1416 if (! acceptLiteral(node))
1417 expected("literal");
1418 // 'node' has the literal in it
1419 if (! acceptTokenClass(EHTokRightParen))
1420 expected(")");
1421 }
1422
1423 // RIGHT_BRACKET
1424 if (acceptTokenClass(EHTokRightBracket))
1425 continue;
1426
1427 expected("]");
1428 return;
1429
1430 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001431}
1432
John Kessenich0d2b6de2016-06-05 11:23:11 -06001433// selection_statement
1434// : IF LEFT_PAREN expression RIGHT_PAREN statement
1435// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1436//
John Kessenich21472ae2016-06-04 11:46:33 -06001437bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1438{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001439 TSourceLoc loc = token.loc;
1440
1441 // IF
1442 if (! acceptTokenClass(EHTokIf))
1443 return false;
1444
1445 // so that something declared in the condition is scoped to the lifetimes
1446 // of the then-else statements
1447 parseContext.pushScope();
1448
1449 // LEFT_PAREN expression RIGHT_PAREN
1450 TIntermTyped* condition;
1451 if (! acceptParenExpression(condition))
1452 return false;
1453
1454 // create the child statements
1455 TIntermNodePair thenElse = { nullptr, nullptr };
1456
1457 // then statement
1458 if (! acceptScopedStatement(thenElse.node1)) {
1459 expected("then statement");
1460 return false;
1461 }
1462
1463 // ELSE
1464 if (acceptTokenClass(EHTokElse)) {
1465 // else statement
1466 if (! acceptScopedStatement(thenElse.node2)) {
1467 expected("else statement");
1468 return false;
1469 }
1470 }
1471
1472 // Put the pieces together
1473 statement = intermediate.addSelection(condition, thenElse, loc);
1474 parseContext.popScope();
1475
1476 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001477}
1478
1479bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1480{
1481 return false;
1482}
1483
John Kessenich119f8f62016-06-05 15:44:07 -06001484// iteration_statement
1485// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1486// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1487// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1488//
1489// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001490bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1491{
John Kessenich119f8f62016-06-05 15:44:07 -06001492 TSourceLoc loc = token.loc;
1493 TIntermTyped* condition = nullptr;
1494
1495 EHlslTokenClass loop = peek();
1496 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1497
1498 // WHILE or DO or FOR
1499 advanceToken();
1500
1501 switch (loop) {
1502 case EHTokWhile:
1503 // so that something declared in the condition is scoped to the lifetime
1504 // of the while sub-statement
1505 parseContext.pushScope();
1506 parseContext.nestLooping();
1507
1508 // LEFT_PAREN condition RIGHT_PAREN
1509 if (! acceptParenExpression(condition))
1510 return false;
1511
1512 // statement
1513 if (! acceptScopedStatement(statement)) {
1514 expected("while sub-statement");
1515 return false;
1516 }
1517
1518 parseContext.unnestLooping();
1519 parseContext.popScope();
1520
1521 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1522
1523 return true;
1524
1525 case EHTokDo:
1526 parseContext.nestLooping();
1527
1528 if (! acceptTokenClass(EHTokLeftBrace))
1529 expected("{");
1530
1531 // statement
1532 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1533 expected("do sub-statement");
1534 return false;
1535 }
1536
1537 if (! acceptTokenClass(EHTokRightBrace))
1538 expected("}");
1539
1540 // WHILE
1541 if (! acceptTokenClass(EHTokWhile)) {
1542 expected("while");
1543 return false;
1544 }
1545
1546 // LEFT_PAREN condition RIGHT_PAREN
1547 TIntermTyped* condition;
1548 if (! acceptParenExpression(condition))
1549 return false;
1550
1551 if (! acceptTokenClass(EHTokSemicolon))
1552 expected(";");
1553
1554 parseContext.unnestLooping();
1555
1556 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1557
1558 return true;
1559
1560 case EHTokFor:
1561 {
1562 // LEFT_PAREN
1563 if (! acceptTokenClass(EHTokLeftParen))
1564 expected("(");
1565
1566 // so that something declared in the condition is scoped to the lifetime
1567 // of the for sub-statement
1568 parseContext.pushScope();
1569
1570 // initializer SEMI_COLON
1571 TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
1572 acceptExpression(initializer);
1573 if (! acceptTokenClass(EHTokSemicolon))
1574 expected(";");
1575
1576 parseContext.nestLooping();
1577
1578 // condition SEMI_COLON
1579 acceptExpression(condition);
1580 if (! acceptTokenClass(EHTokSemicolon))
1581 expected(";");
1582
1583 // iterator SEMI_COLON
1584 TIntermTyped* iterator = nullptr;
1585 acceptExpression(iterator);
1586 if (! acceptTokenClass(EHTokRightParen))
1587 expected(")");
1588
1589 // statement
1590 if (! acceptScopedStatement(statement)) {
1591 expected("for sub-statement");
1592 return false;
1593 }
1594
1595 statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
1596
1597 parseContext.popScope();
1598 parseContext.unnestLooping();
1599
1600 return true;
1601 }
1602
1603 default:
1604 return false;
1605 }
John Kessenich21472ae2016-06-04 11:46:33 -06001606}
1607
1608// jump_statement
1609// : CONTINUE SEMICOLON
1610// | BREAK SEMICOLON
1611// | DISCARD SEMICOLON
1612// | RETURN SEMICOLON
1613// | RETURN expression SEMICOLON
1614//
1615bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1616{
1617 switch (peek()) {
1618 case EHTokContinue:
1619 case EHTokBreak:
1620 case EHTokDiscard:
1621 // TODO
1622 return false;
1623
1624 case EHTokReturn:
1625 // return
1626 if (acceptTokenClass(EHTokReturn)) {
1627 // expression
1628 TIntermTyped* node;
1629 if (acceptExpression(node)) {
1630 // hook it up
1631 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1632 } else
1633 statement = intermediate.addBranch(EOpReturn, token.loc);
1634
1635 // SEMICOLON
1636 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001637 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001638 return false;
1639 }
1640
1641 return true;
1642 }
1643
1644 default:
1645 return false;
1646 }
1647}
1648
1649
1650bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1651{
1652 return false;
1653}
1654
John Kessenich19b92ff2016-06-19 11:50:34 -06001655// array_specifier
1656// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
1657//
1658void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
1659{
1660 arraySizes = nullptr;
1661
1662 if (! acceptTokenClass(EHTokLeftBracket))
1663 return;
1664
1665 TSourceLoc loc = token.loc;
1666 TIntermTyped* sizeExpr;
1667 if (! acceptAssignmentExpression(sizeExpr)) {
1668 expected("array-sizing expression");
1669 return;
1670 }
1671
1672 if (! acceptTokenClass(EHTokRightBracket)) {
1673 expected("]");
1674 return;
1675 }
1676
1677 TArraySize arraySize;
1678 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
1679 arraySizes = new TArraySizes;
1680 arraySizes->addInnerSize(arraySize);
1681}
1682
John Kessenich630dd7d2016-06-12 23:52:12 -06001683// post_decls
1684// : COLON semantic // optional
1685// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1686// COLON REGISTER // optional
1687// annotations // optional
1688//
1689void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06001690{
John Kessenich630dd7d2016-06-12 23:52:12 -06001691 do {
1692 // COLON
1693 if (acceptTokenClass(EHTokColon)) {
1694 HlslToken idToken;
1695 if (acceptTokenClass(EHTokPackOffset)) {
1696 if (! acceptTokenClass(EHTokLeftParen)) {
1697 expected("(");
1698 return;
1699 }
1700 acceptTokenClass(EHTokIdentifier);
1701 acceptTokenClass(EHTokDot);
1702 acceptTokenClass(EHTokIdentifier);
1703 if (! acceptTokenClass(EHTokRightParen)) {
1704 expected(")");
1705 break;
1706 }
1707 // TODO: process the packoffset information
1708 } else if (! acceptIdentifier(idToken)) {
1709 expected("semantic or packoffset or register");
1710 return;
1711 } else if (*idToken.string == "register") {
1712 if (! acceptTokenClass(EHTokLeftParen)) {
1713 expected("(");
1714 return;
1715 }
1716 acceptTokenClass(EHTokIdentifier);
1717 acceptTokenClass(EHTokComma);
1718 acceptTokenClass(EHTokIdentifier);
1719 acceptTokenClass(EHTokLeftBracket);
1720 if (peekTokenClass(EHTokIntConstant))
1721 advanceToken();
1722 acceptTokenClass(EHTokRightBracket);
1723 if (! acceptTokenClass(EHTokRightParen)) {
1724 expected(")");
1725 break;
1726 }
1727 // TODO: process the register information
1728 } else {
1729 // semantic, in idToken.string
1730 parseContext.handleSemantic(type, *idToken.string);
1731 }
1732 } else if (acceptTokenClass(EHTokLeftAngle)) {
1733 // TODO: process annotations, just accepting them for now
1734 do {
1735 if (peekTokenClass(EHTokNone))
1736 return;
1737 if (acceptTokenClass(EHTokRightAngle))
1738 break;
1739 advanceToken();
1740 } while (true);
1741 } else
1742 break;
John Kessenich078d7f22016-03-14 10:02:11 -06001743
John Kessenich630dd7d2016-06-12 23:52:12 -06001744 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06001745}
1746
John Kesseniche01a9bc2016-03-12 20:11:22 -07001747} // end namespace glslang