blob: d269f0b1198ac98b864fe90678458a4d7befabb5 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
2//Copyright (C) 2016 Google, Inc.
LoopDawg6daaa4f2016-06-23 19:13:48 -06003//Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
5//All rights reserved.
6//
7//Redistribution and use in source and binary forms, with or without
8//modification, are permitted provided that the following conditions
9//are met:
10//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
23//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34//POSSIBILITY OF SUCH DAMAGE.
35//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
56
57namespace glslang {
58
59// Root entry point to this recursive decent parser.
60// Return true if compilation unit was successfully accepted.
61bool HlslGrammar::parse()
62{
63 advanceToken();
64 return acceptCompilationUnit();
65}
66
67void HlslGrammar::expected(const char* syntax)
68{
69 parseContext.error(token.loc, "Expected", syntax, "");
70}
71
John Kessenichaecd4972016-03-14 10:46:34 -060072// Only process the next token if it is an identifier.
73// Return true if it was an identifier.
74bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
75{
76 if (peekTokenClass(EHTokIdentifier)) {
77 idToken = token;
78 advanceToken();
79 return true;
80 }
81
82 return false;
83}
84
John Kesseniche01a9bc2016-03-12 20:11:22 -070085// compilationUnit
86// : list of externalDeclaration
87//
88bool HlslGrammar::acceptCompilationUnit()
89{
John Kessenichd016be12016-03-13 11:24:20 -060090 TIntermNode* unitNode = nullptr;
91
John Kessenich9c86c6a2016-05-03 22:49:24 -060092 while (! peekTokenClass(EHTokNone)) {
John Kessenichd016be12016-03-13 11:24:20 -060093 // externalDeclaration
94 TIntermNode* declarationNode;
95 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -070096 return false;
John Kessenichd016be12016-03-13 11:24:20 -060097
98 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -060099 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700100 }
101
John Kessenichd016be12016-03-13 11:24:20 -0600102 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600103 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600104
John Kesseniche01a9bc2016-03-12 20:11:22 -0700105 return true;
106}
107
108// declaration
John Kessenich078d7f22016-03-14 10:02:11 -0600109// : SEMICOLON
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600110// | fully_specified_type SEMICOLON
John Kessenich19b92ff2016-06-19 11:50:34 -0600111// | fully_specified_type identifier array_specifier post_decls (EQUAL expression)opt SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600112// | fully_specified_type identifier function_parameters post_decls SEMICOLON // function prototype
113// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
John Kessenich87142c72016-03-12 20:24:24 -0700114//
John Kessenichd016be12016-03-13 11:24:20 -0600115// 'node' could get created if the declaration creates code, like an initializer
116// or a function body.
117//
118bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700119{
John Kessenichd016be12016-03-13 11:24:20 -0600120 node = nullptr;
121
John Kessenich87142c72016-03-12 20:24:24 -0700122 // fully_specified_type
123 TType type;
124 if (! acceptFullySpecifiedType(type))
125 return false;
126
127 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600128 HlslToken idToken;
129 if (acceptIdentifier(idToken)) {
John Kessenich19b92ff2016-06-19 11:50:34 -0600130 // array_specifier
131 TArraySizes* arraySizes = nullptr;
132 acceptArraySpecifier(arraySizes);
133
134 // post_decls
John Kessenich630dd7d2016-06-12 23:52:12 -0600135 acceptPostDecls(type);
John Kessenich19b92ff2016-06-19 11:50:34 -0600136
137 // EQUAL expression
John Kessenich87142c72016-03-12 20:24:24 -0700138 TIntermTyped* expressionNode = nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -0600139 if (acceptTokenClass(EHTokAssign)) {
John Kessenich87142c72016-03-12 20:24:24 -0700140 if (! acceptExpression(expressionNode)) {
141 expected("initializer");
142 return false;
143 }
144 }
145
John Kessenich078d7f22016-03-14 10:02:11 -0600146 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700147 if (acceptTokenClass(EHTokSemicolon)) {
John Kessenich19b92ff2016-06-19 11:50:34 -0600148 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, arraySizes, expressionNode);
John Kessenich87142c72016-03-12 20:24:24 -0700149 return true;
150 }
John Kessenich5f934b02016-03-13 17:58:25 -0600151
152 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600153 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600154 if (acceptFunctionParameters(*function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600155 // post_decls
156 acceptPostDecls(type);
John Kessenich078d7f22016-03-14 10:02:11 -0600157
John Kessenich5f934b02016-03-13 17:58:25 -0600158 // compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600159 if (peekTokenClass(EHTokLeftBrace))
John Kessenich5f934b02016-03-13 17:58:25 -0600160 return acceptFunctionDefinition(*function, node);
161
John Kessenich078d7f22016-03-14 10:02:11 -0600162 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600163 if (acceptTokenClass(EHTokSemicolon))
164 return true;
165
166 return false;
167 }
John Kessenich87142c72016-03-12 20:24:24 -0700168 }
169
John Kessenich078d7f22016-03-14 10:02:11 -0600170 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700171 if (acceptTokenClass(EHTokSemicolon))
172 return true;
173
John Kesseniche01a9bc2016-03-12 20:11:22 -0700174 return true;
175}
176
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600177// control_declaration
178// : fully_specified_type identifier EQUAL expression
179//
180bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
181{
182 node = nullptr;
183
184 // fully_specified_type
185 TType type;
186 if (! acceptFullySpecifiedType(type))
187 return false;
188
189 // identifier
190 HlslToken idToken;
191 if (! acceptIdentifier(idToken)) {
192 expected("identifier");
193 return false;
194 }
195
196 // EQUAL
197 TIntermTyped* expressionNode = nullptr;
198 if (! acceptTokenClass(EHTokAssign)) {
199 expected("=");
200 return false;
201 }
202
203 // expression
204 if (! acceptExpression(expressionNode)) {
205 expected("initializer");
206 return false;
207 }
208
209 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
210
211 return true;
212}
213
John Kessenich87142c72016-03-12 20:24:24 -0700214// fully_specified_type
215// : type_specifier
216// | type_qualifier type_specifier
217//
218bool HlslGrammar::acceptFullySpecifiedType(TType& type)
219{
220 // type_qualifier
221 TQualifier qualifier;
222 qualifier.clear();
223 acceptQualifier(qualifier);
224
225 // type_specifier
226 if (! acceptType(type))
227 return false;
228 type.getQualifier() = qualifier;
229
230 return true;
231}
232
John Kessenich630dd7d2016-06-12 23:52:12 -0600233// type_qualifier
234// : qualifier qualifier ...
235//
236// Zero or more of these, so this can't return false.
237//
John Kessenich87142c72016-03-12 20:24:24 -0700238void HlslGrammar::acceptQualifier(TQualifier& qualifier)
239{
John Kessenich630dd7d2016-06-12 23:52:12 -0600240 do {
241 switch (peek()) {
242 case EHTokStatic:
243 // normal glslang default
244 break;
245 case EHTokExtern:
246 // TODO: no meaning in glslang?
247 break;
248 case EHTokShared:
249 // TODO: hint
250 break;
251 case EHTokGroupShared:
252 qualifier.storage = EvqShared;
253 break;
254 case EHTokUniform:
255 qualifier.storage = EvqUniform;
256 break;
257 case EHTokConst:
258 qualifier.storage = EvqConst;
259 break;
260 case EHTokVolatile:
261 qualifier.volatil = true;
262 break;
263 case EHTokLinear:
264 qualifier.storage = EvqVaryingIn;
265 qualifier.smooth = true;
266 break;
267 case EHTokCentroid:
268 qualifier.centroid = true;
269 break;
270 case EHTokNointerpolation:
271 qualifier.flat = true;
272 break;
273 case EHTokNoperspective:
274 qualifier.nopersp = true;
275 break;
276 case EHTokSample:
277 qualifier.sample = true;
278 break;
279 case EHTokRowMajor:
280 qualifier.layoutMatrix = ElmRowMajor;
281 break;
282 case EHTokColumnMajor:
283 qualifier.layoutMatrix = ElmColumnMajor;
284 break;
285 case EHTokPrecise:
286 qualifier.noContraction = true;
287 break;
288 default:
289 return;
290 }
291 advanceToken();
292 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700293}
294
LoopDawg6daaa4f2016-06-23 19:13:48 -0600295// template_type
296// : FLOAT
297// | DOUBLE
298// | INT
299// | DWORD
300// | UINT
301// | BOOL
302//
303bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
304{
305 switch (peek()) {
306 case EHTokFloat:
307 basicType = EbtFloat;
308 break;
309 case EHTokDouble:
310 basicType = EbtDouble;
311 break;
312 case EHTokInt:
313 case EHTokDword:
314 basicType = EbtInt;
315 break;
316 case EHTokUint:
317 basicType = EbtUint;
318 break;
319 case EHTokBool:
320 basicType = EbtBool;
321 break;
322 default:
323 return false;
324 }
325
326 advanceToken();
327
328 return true;
329}
330
331// vector_template_type
332// : VECTOR
333// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
334//
335bool HlslGrammar::acceptVectorTemplateType(TType& type)
336{
337 if (! acceptTokenClass(EHTokVector))
338 return false;
339
340 if (! acceptTokenClass(EHTokLeftAngle)) {
341 // in HLSL, 'vector' alone means float4.
342 new(&type) TType(EbtFloat, EvqTemporary, 4);
343 return true;
344 }
345
346 TBasicType basicType;
347 if (! acceptTemplateType(basicType)) {
348 expected("scalar type");
349 return false;
350 }
351
352 // COMMA
353 if (! acceptTokenClass(EHTokComma)) {
354 expected(",");
355 return false;
356 }
357
358 // integer
359 if (! peekTokenClass(EHTokIntConstant)) {
360 expected("literal integer");
361 return false;
362 }
363
364 TIntermTyped* vecSize;
365 if (! acceptLiteral(vecSize))
366 return false;
367
368 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
369
370 new(&type) TType(basicType, EvqTemporary, vecSizeI);
371
372 if (vecSizeI == 1)
373 type.makeVector();
374
375 if (!acceptTokenClass(EHTokRightAngle)) {
376 expected("right angle bracket");
377 return false;
378 }
379
380 return true;
381}
382
383// matrix_template_type
384// : MATRIX
385// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
386//
387bool HlslGrammar::acceptMatrixTemplateType(TType& type)
388{
389 if (! acceptTokenClass(EHTokMatrix))
390 return false;
391
392 if (! acceptTokenClass(EHTokLeftAngle)) {
393 // in HLSL, 'matrix' alone means float4x4.
394 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
395 return true;
396 }
397
398 TBasicType basicType;
399 if (! acceptTemplateType(basicType)) {
400 expected("scalar type");
401 return false;
402 }
403
404 // COMMA
405 if (! acceptTokenClass(EHTokComma)) {
406 expected(",");
407 return false;
408 }
409
410 // integer rows
411 if (! peekTokenClass(EHTokIntConstant)) {
412 expected("literal integer");
413 return false;
414 }
415
416 TIntermTyped* rows;
417 if (! acceptLiteral(rows))
418 return false;
419
420 // COMMA
421 if (! acceptTokenClass(EHTokComma)) {
422 expected(",");
423 return false;
424 }
425
426 // integer cols
427 if (! peekTokenClass(EHTokIntConstant)) {
428 expected("literal integer");
429 return false;
430 }
431
432 TIntermTyped* cols;
433 if (! acceptLiteral(cols))
434 return false;
435
436 new(&type) TType(basicType, EvqTemporary, 0,
437 cols->getAsConstantUnion()->getConstArray()[0].getIConst(),
438 rows->getAsConstantUnion()->getConstArray()[0].getIConst());
439
440 if (!acceptTokenClass(EHTokRightAngle)) {
441 expected("right angle bracket");
442 return false;
443 }
444
445 return true;
446}
447
448
John Kessenich87142c72016-03-12 20:24:24 -0700449// If token is for a type, update 'type' with the type information,
450// and return true and advance.
451// Otherwise, return false, and don't advance
452bool HlslGrammar::acceptType(TType& type)
453{
LoopDawg6daaa4f2016-06-23 19:13:48 -0600454 TBasicType basicType;
455
John Kessenich9c86c6a2016-05-03 22:49:24 -0600456 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600457 case EHTokVector:
458 return acceptVectorTemplateType(type);
459 break;
460
461 case EHTokMatrix:
462 return acceptMatrixTemplateType(type);
463 break;
464
John Kesseniche6e74942016-06-11 16:43:14 -0600465 case EHTokStruct:
466 return acceptStruct(type);
467 break;
468
469 case EHTokIdentifier:
470 // An identifier could be for a user-defined type.
471 // Note we cache the symbol table lookup, to save for a later rule
472 // when this is not a type.
473 token.symbol = parseContext.symbolTable.find(*token.string);
474 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
475 type.shallowCopy(token.symbol->getType());
476 advanceToken();
477 return true;
478 } else
479 return false;
480
John Kessenich71351de2016-06-08 12:50:56 -0600481 case EHTokVoid:
482 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700483 break;
John Kessenich71351de2016-06-08 12:50:56 -0600484
John Kessenich87142c72016-03-12 20:24:24 -0700485 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600486 new(&type) TType(EbtFloat);
487 break;
John Kessenich87142c72016-03-12 20:24:24 -0700488 case EHTokFloat1:
489 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600490 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700491 break;
John Kessenich87142c72016-03-12 20:24:24 -0700492 case EHTokFloat2:
493 new(&type) TType(EbtFloat, EvqTemporary, 2);
494 break;
495 case EHTokFloat3:
496 new(&type) TType(EbtFloat, EvqTemporary, 3);
497 break;
498 case EHTokFloat4:
499 new(&type) TType(EbtFloat, EvqTemporary, 4);
500 break;
501
John Kessenich71351de2016-06-08 12:50:56 -0600502 case EHTokDouble:
503 new(&type) TType(EbtDouble);
504 break;
505 case EHTokDouble1:
506 new(&type) TType(EbtDouble);
507 type.makeVector();
508 break;
509 case EHTokDouble2:
510 new(&type) TType(EbtDouble, EvqTemporary, 2);
511 break;
512 case EHTokDouble3:
513 new(&type) TType(EbtDouble, EvqTemporary, 3);
514 break;
515 case EHTokDouble4:
516 new(&type) TType(EbtDouble, EvqTemporary, 4);
517 break;
518
519 case EHTokInt:
520 case EHTokDword:
521 new(&type) TType(EbtInt);
522 break;
523 case EHTokInt1:
524 new(&type) TType(EbtInt);
525 type.makeVector();
526 break;
John Kessenich87142c72016-03-12 20:24:24 -0700527 case EHTokInt2:
528 new(&type) TType(EbtInt, EvqTemporary, 2);
529 break;
530 case EHTokInt3:
531 new(&type) TType(EbtInt, EvqTemporary, 3);
532 break;
533 case EHTokInt4:
534 new(&type) TType(EbtInt, EvqTemporary, 4);
535 break;
536
John Kessenich71351de2016-06-08 12:50:56 -0600537 case EHTokUint:
538 new(&type) TType(EbtUint);
539 break;
540 case EHTokUint1:
541 new(&type) TType(EbtUint);
542 type.makeVector();
543 break;
544 case EHTokUint2:
545 new(&type) TType(EbtUint, EvqTemporary, 2);
546 break;
547 case EHTokUint3:
548 new(&type) TType(EbtUint, EvqTemporary, 3);
549 break;
550 case EHTokUint4:
551 new(&type) TType(EbtUint, EvqTemporary, 4);
552 break;
553
LoopDawg6daaa4f2016-06-23 19:13:48 -0600554
John Kessenich71351de2016-06-08 12:50:56 -0600555 case EHTokBool:
556 new(&type) TType(EbtBool);
557 break;
558 case EHTokBool1:
559 new(&type) TType(EbtBool);
560 type.makeVector();
561 break;
John Kessenich87142c72016-03-12 20:24:24 -0700562 case EHTokBool2:
563 new(&type) TType(EbtBool, EvqTemporary, 2);
564 break;
565 case EHTokBool3:
566 new(&type) TType(EbtBool, EvqTemporary, 3);
567 break;
568 case EHTokBool4:
569 new(&type) TType(EbtBool, EvqTemporary, 4);
570 break;
571
John Kessenich0133c122016-05-20 12:17:26 -0600572 case EHTokInt1x1:
573 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
574 break;
575 case EHTokInt1x2:
576 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
577 break;
578 case EHTokInt1x3:
579 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
580 break;
581 case EHTokInt1x4:
582 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
583 break;
584 case EHTokInt2x1:
585 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
586 break;
587 case EHTokInt2x2:
588 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
589 break;
590 case EHTokInt2x3:
591 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
592 break;
593 case EHTokInt2x4:
594 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
595 break;
596 case EHTokInt3x1:
597 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
598 break;
599 case EHTokInt3x2:
600 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
601 break;
602 case EHTokInt3x3:
603 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
604 break;
605 case EHTokInt3x4:
606 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
607 break;
608 case EHTokInt4x1:
609 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
610 break;
611 case EHTokInt4x2:
612 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
613 break;
614 case EHTokInt4x3:
615 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
616 break;
617 case EHTokInt4x4:
618 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
619 break;
620
John Kessenich71351de2016-06-08 12:50:56 -0600621 case EHTokUint1x1:
622 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
623 break;
624 case EHTokUint1x2:
625 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
626 break;
627 case EHTokUint1x3:
628 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
629 break;
630 case EHTokUint1x4:
631 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
632 break;
633 case EHTokUint2x1:
634 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
635 break;
636 case EHTokUint2x2:
637 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
638 break;
639 case EHTokUint2x3:
640 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
641 break;
642 case EHTokUint2x4:
643 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
644 break;
645 case EHTokUint3x1:
646 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
647 break;
648 case EHTokUint3x2:
649 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
650 break;
651 case EHTokUint3x3:
652 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
653 break;
654 case EHTokUint3x4:
655 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
656 break;
657 case EHTokUint4x1:
658 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
659 break;
660 case EHTokUint4x2:
661 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
662 break;
663 case EHTokUint4x3:
664 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
665 break;
666 case EHTokUint4x4:
667 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
668 break;
669
670 case EHTokBool1x1:
671 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
672 break;
673 case EHTokBool1x2:
674 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
675 break;
676 case EHTokBool1x3:
677 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
678 break;
679 case EHTokBool1x4:
680 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
681 break;
682 case EHTokBool2x1:
683 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
684 break;
685 case EHTokBool2x2:
686 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
687 break;
688 case EHTokBool2x3:
689 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
690 break;
691 case EHTokBool2x4:
692 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
693 break;
694 case EHTokBool3x1:
695 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
696 break;
697 case EHTokBool3x2:
698 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
699 break;
700 case EHTokBool3x3:
701 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
702 break;
703 case EHTokBool3x4:
704 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
705 break;
706 case EHTokBool4x1:
707 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
708 break;
709 case EHTokBool4x2:
710 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
711 break;
712 case EHTokBool4x3:
713 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
714 break;
715 case EHTokBool4x4:
716 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
717 break;
718
John Kessenich0133c122016-05-20 12:17:26 -0600719 case EHTokFloat1x1:
720 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
721 break;
722 case EHTokFloat1x2:
723 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
724 break;
725 case EHTokFloat1x3:
726 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
727 break;
728 case EHTokFloat1x4:
729 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
730 break;
731 case EHTokFloat2x1:
732 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
733 break;
John Kessenich87142c72016-03-12 20:24:24 -0700734 case EHTokFloat2x2:
735 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
736 break;
737 case EHTokFloat2x3:
738 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
739 break;
740 case EHTokFloat2x4:
741 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
742 break;
John Kessenich0133c122016-05-20 12:17:26 -0600743 case EHTokFloat3x1:
744 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
745 break;
John Kessenich87142c72016-03-12 20:24:24 -0700746 case EHTokFloat3x2:
747 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
748 break;
749 case EHTokFloat3x3:
750 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
751 break;
752 case EHTokFloat3x4:
753 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
754 break;
John Kessenich0133c122016-05-20 12:17:26 -0600755 case EHTokFloat4x1:
756 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
757 break;
John Kessenich87142c72016-03-12 20:24:24 -0700758 case EHTokFloat4x2:
759 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
760 break;
761 case EHTokFloat4x3:
762 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
763 break;
764 case EHTokFloat4x4:
765 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
766 break;
767
John Kessenich0133c122016-05-20 12:17:26 -0600768 case EHTokDouble1x1:
769 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
770 break;
771 case EHTokDouble1x2:
772 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
773 break;
774 case EHTokDouble1x3:
775 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
776 break;
777 case EHTokDouble1x4:
778 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
779 break;
780 case EHTokDouble2x1:
781 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
782 break;
783 case EHTokDouble2x2:
784 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
785 break;
786 case EHTokDouble2x3:
787 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
788 break;
789 case EHTokDouble2x4:
790 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
791 break;
792 case EHTokDouble3x1:
793 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
794 break;
795 case EHTokDouble3x2:
796 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
797 break;
798 case EHTokDouble3x3:
799 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
800 break;
801 case EHTokDouble3x4:
802 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
803 break;
804 case EHTokDouble4x1:
805 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
806 break;
807 case EHTokDouble4x2:
808 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
809 break;
810 case EHTokDouble4x3:
811 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
812 break;
813 case EHTokDouble4x4:
814 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
815 break;
816
John Kessenich87142c72016-03-12 20:24:24 -0700817 default:
818 return false;
819 }
820
821 advanceToken();
822
823 return true;
824}
825
John Kesseniche6e74942016-06-11 16:43:14 -0600826// struct
827// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE
828// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE
829//
830bool HlslGrammar::acceptStruct(TType& type)
831{
832 // STRUCT
833 if (! acceptTokenClass(EHTokStruct))
834 return false;
835
836 // IDENTIFIER
837 TString structName = "";
838 if (peekTokenClass(EHTokIdentifier)) {
839 structName = *token.string;
840 advanceToken();
841 }
842
843 // LEFT_BRACE
844 if (! acceptTokenClass(EHTokLeftBrace)) {
845 expected("{");
846 return false;
847 }
848
849 // struct_declaration_list
850 TTypeList* typeList;
851 if (! acceptStructDeclarationList(typeList)) {
852 expected("struct member declarations");
853 return false;
854 }
855
856 // RIGHT_BRACE
857 if (! acceptTokenClass(EHTokRightBrace)) {
858 expected("}");
859 return false;
860 }
861
862 // create the user-defined type
863 new(&type) TType(typeList, structName);
864
865 // If it was named, which means it can be reused later, add
866 // it to the symbol table.
867 if (structName.size() > 0) {
868 TVariable* userTypeDef = new TVariable(&structName, type, true);
869 if (! parseContext.symbolTable.insert(*userTypeDef))
870 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
871 }
872
873 return true;
874}
875
876// struct_declaration_list
877// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
878//
879// struct_declaration
880// : fully_specified_type struct_declarator COMMA struct_declarator ...
881//
882// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -0600883// : IDENTIFIER post_decls
884// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -0600885//
886bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
887{
888 typeList = new TTypeList();
889
890 do {
891 // success on seeing the RIGHT_BRACE coming up
892 if (peekTokenClass(EHTokRightBrace))
893 return true;
894
895 // struct_declaration
896
897 // fully_specified_type
898 TType memberType;
899 if (! acceptFullySpecifiedType(memberType)) {
900 expected("member type");
901 return false;
902 }
903
904 // struct_declarator COMMA struct_declarator ...
905 do {
906 // peek IDENTIFIER
907 if (! peekTokenClass(EHTokIdentifier)) {
908 expected("member name");
909 return false;
910 }
911
912 // add it to the list of members
913 TTypeLoc member = { new TType(EbtVoid), token.loc };
914 member.type->shallowCopy(memberType);
915 member.type->setFieldName(*token.string);
916 typeList->push_back(member);
917
918 // accept IDENTIFIER
919 advanceToken();
920
921 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -0600922 TArraySizes* arraySizes = nullptr;
923 acceptArraySpecifier(arraySizes);
924 if (arraySizes)
925 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -0600926
John Kessenich630dd7d2016-06-12 23:52:12 -0600927 acceptPostDecls(*member.type);
928
John Kesseniche6e74942016-06-11 16:43:14 -0600929 // success on seeing the SEMICOLON coming up
930 if (peekTokenClass(EHTokSemicolon))
931 break;
932
933 // COMMA
934 if (! acceptTokenClass(EHTokComma)) {
935 expected(",");
936 return false;
937 }
938
939 } while (true);
940
941 // SEMI_COLON
942 if (! acceptTokenClass(EHTokSemicolon)) {
943 expected(";");
944 return false;
945 }
946
947 } while (true);
948}
949
John Kessenich5f934b02016-03-13 17:58:25 -0600950// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600951// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -0600952// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600953//
954bool HlslGrammar::acceptFunctionParameters(TFunction& function)
955{
John Kessenich078d7f22016-03-14 10:02:11 -0600956 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600957 if (! acceptTokenClass(EHTokLeftParen))
958 return false;
959
John Kessenich71351de2016-06-08 12:50:56 -0600960 // VOID RIGHT_PAREN
961 if (! acceptTokenClass(EHTokVoid)) {
962 do {
963 // parameter_declaration
964 if (! acceptParameterDeclaration(function))
965 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600966
John Kessenich71351de2016-06-08 12:50:56 -0600967 // COMMA
968 if (! acceptTokenClass(EHTokComma))
969 break;
970 } while (true);
971 }
John Kessenich5f934b02016-03-13 17:58:25 -0600972
John Kessenich078d7f22016-03-14 10:02:11 -0600973 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600974 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600975 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -0600976 return false;
977 }
978
979 return true;
980}
981
982// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -0600983// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -0600984// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -0600985//
986bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
987{
988 // fully_specified_type
989 TType* type = new TType;
990 if (! acceptFullySpecifiedType(*type))
991 return false;
992
993 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600994 HlslToken idToken;
995 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600996
John Kessenich19b92ff2016-06-19 11:50:34 -0600997 // array_specifier
998 TArraySizes* arraySizes = nullptr;
999 acceptArraySpecifier(arraySizes);
1000 if (arraySizes)
1001 type->newArraySizes(*arraySizes);
1002
1003 // post_decls
John Kessenichc3387d32016-06-17 14:21:02 -06001004 acceptPostDecls(*type);
1005
John Kessenich5aa59e22016-06-17 15:50:47 -06001006 parseContext.paramFix(*type);
1007
John Kessenichaecd4972016-03-14 10:46:34 -06001008 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001009 function.addParameter(param);
1010
1011 return true;
1012}
1013
1014// Do the work to create the function definition in addition to
1015// parsing the body (compound_statement).
1016bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1017{
1018 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
1019
John Kessenich077e0522016-06-09 02:02:17 -06001020 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -06001021 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
1022
1023 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001024 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001025 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -06001026 node = intermediate.growAggregate(node, functionBody);
1027 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -06001028 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -06001029 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -06001030
1031 return true;
1032 }
1033
1034 return false;
1035}
1036
John Kessenich0d2b6de2016-06-05 11:23:11 -06001037// Accept an expression with parenthesis around it, where
1038// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001039// syntactically required ones like in "if ( expression )".
1040//
1041// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001042//
1043// Note this one is not set up to be speculative; as it gives
1044// errors if not found.
1045//
1046bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1047{
1048 // LEFT_PAREN
1049 if (! acceptTokenClass(EHTokLeftParen))
1050 expected("(");
1051
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001052 bool decl = false;
1053 TIntermNode* declNode = nullptr;
1054 decl = acceptControlDeclaration(declNode);
1055 if (decl) {
1056 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1057 expected("initialized declaration");
1058 return false;
1059 } else
1060 expression = declNode->getAsTyped();
1061 } else {
1062 // no declaration
1063 if (! acceptExpression(expression)) {
1064 expected("expression");
1065 return false;
1066 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001067 }
1068
1069 // RIGHT_PAREN
1070 if (! acceptTokenClass(EHTokRightParen))
1071 expected(")");
1072
1073 return true;
1074}
1075
John Kessenich34fb0362016-05-03 23:17:20 -06001076// The top-level full expression recognizer.
1077//
John Kessenich87142c72016-03-12 20:24:24 -07001078// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001079// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001080//
1081bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1082{
LoopDawgef764a22016-06-03 09:17:51 -06001083 node = nullptr;
1084
John Kessenich34fb0362016-05-03 23:17:20 -06001085 // assignment_expression
1086 if (! acceptAssignmentExpression(node))
1087 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001088
John Kessenich34fb0362016-05-03 23:17:20 -06001089 if (! peekTokenClass(EHTokComma))
1090 return true;
1091
1092 do {
1093 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001094 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001095 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001096
John Kessenich34fb0362016-05-03 23:17:20 -06001097 // ... assignment_expression
1098 TIntermTyped* rightNode = nullptr;
1099 if (! acceptAssignmentExpression(rightNode)) {
1100 expected("assignment expression");
1101 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001102 }
1103
John Kessenich34fb0362016-05-03 23:17:20 -06001104 node = intermediate.addComma(node, rightNode, loc);
1105
1106 if (! peekTokenClass(EHTokComma))
1107 return true;
1108 } while (true);
1109}
1110
1111// Accept an assignment expression, where assignment operations
1112// associate right-to-left. This is, it is implicit, for example
1113//
1114// a op (b op (c op d))
1115//
1116// assigment_expression
1117// : binary_expression op binary_expression op binary_expression ...
1118//
1119bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1120{
1121 if (! acceptBinaryExpression(node, PlLogicalOr))
1122 return false;
1123
1124 TOperator assignOp = HlslOpMap::assignment(peek());
1125 if (assignOp == EOpNull)
1126 return true;
1127
1128 // ... op
1129 TSourceLoc loc = token.loc;
1130 advanceToken();
1131
1132 // ... binary_expression
1133 // But, done by recursing this function, which automatically
1134 // gets the right-to-left associativity.
1135 TIntermTyped* rightNode = nullptr;
1136 if (! acceptAssignmentExpression(rightNode)) {
1137 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001138 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001139 }
1140
John Kessenich34fb0362016-05-03 23:17:20 -06001141 node = intermediate.addAssign(assignOp, node, rightNode, loc);
1142
1143 if (! peekTokenClass(EHTokComma))
1144 return true;
1145
1146 return true;
1147}
1148
1149// Accept a binary expression, for binary operations that
1150// associate left-to-right. This is, it is implicit, for example
1151//
1152// ((a op b) op c) op d
1153//
1154// binary_expression
1155// : expression op expression op expression ...
1156//
1157// where 'expression' is the next higher level in precedence.
1158//
1159bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1160{
1161 if (precedenceLevel > PlMul)
1162 return acceptUnaryExpression(node);
1163
1164 // assignment_expression
1165 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1166 return false;
1167
1168 TOperator op = HlslOpMap::binary(peek());
1169 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1170 if (tokenLevel < precedenceLevel)
1171 return true;
1172
1173 do {
1174 // ... op
1175 TSourceLoc loc = token.loc;
1176 advanceToken();
1177
1178 // ... expression
1179 TIntermTyped* rightNode = nullptr;
1180 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1181 expected("expression");
1182 return false;
1183 }
1184
1185 node = intermediate.addBinaryMath(op, node, rightNode, loc);
1186
1187 if (! peekTokenClass(EHTokComma))
1188 return true;
1189 } while (true);
1190}
1191
1192// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001193// : (type) unary_expression
1194// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001195// | - unary_expression
1196// | ! unary_expression
1197// | ~ unary_expression
1198// | ++ unary_expression
1199// | -- unary_expression
1200// | postfix_expression
1201//
1202bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1203{
John Kessenich1cc1a282016-06-03 16:55:49 -06001204 // (type) unary_expression
1205 // Have to look two steps ahead, because this could be, e.g., a
1206 // postfix_expression instead, since that also starts with at "(".
1207 if (acceptTokenClass(EHTokLeftParen)) {
1208 TType castType;
1209 if (acceptType(castType)) {
1210 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001211 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -06001212 return false;
1213 }
1214
1215 // We've matched "(type)" now, get the expression to cast
1216 TSourceLoc loc = token.loc;
1217 if (! acceptUnaryExpression(node))
1218 return false;
1219
1220 // Hook it up like a constructor
1221 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1222 if (constructorFunction == nullptr) {
1223 expected("type that can be constructed");
1224 return false;
1225 }
1226 TIntermTyped* arguments = nullptr;
1227 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1228 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1229
1230 return true;
1231 } else {
1232 // This isn't a type cast, but it still started "(", so if it is a
1233 // unary expression, it can only be a postfix_expression, so try that.
1234 // Back it up first.
1235 recedeToken();
1236 return acceptPostfixExpression(node);
1237 }
1238 }
1239
1240 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001241 TOperator unaryOp = HlslOpMap::preUnary(peek());
1242
John Kessenich1cc1a282016-06-03 16:55:49 -06001243 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001244 if (unaryOp == EOpNull)
1245 return acceptPostfixExpression(node);
1246
1247 // op unary_expression
1248 TSourceLoc loc = token.loc;
1249 advanceToken();
1250 if (! acceptUnaryExpression(node))
1251 return false;
1252
1253 // + is a no-op
1254 if (unaryOp == EOpAdd)
1255 return true;
1256
1257 node = intermediate.addUnaryMath(unaryOp, node, loc);
1258
1259 return node != nullptr;
1260}
1261
1262// postfix_expression
1263// : LEFT_PAREN expression RIGHT_PAREN
1264// | literal
1265// | constructor
1266// | identifier
1267// | function_call
1268// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1269// | postfix_expression DOT IDENTIFIER
1270// | postfix_expression INC_OP
1271// | postfix_expression DEC_OP
1272//
1273bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1274{
1275 // Not implemented as self-recursive:
1276 // The logical "right recursion" is done with an loop at the end
1277
1278 // idToken will pick up either a variable or a function name in a function call
1279 HlslToken idToken;
1280
John Kessenich21472ae2016-06-04 11:46:33 -06001281 // Find something before the postfix operations, as they can't operate
1282 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001283 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001284 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001285 if (! acceptExpression(node)) {
1286 expected("expression");
1287 return false;
1288 }
1289 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001290 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001291 return false;
1292 }
John Kessenich34fb0362016-05-03 23:17:20 -06001293 } else if (acceptLiteral(node)) {
1294 // literal (nothing else to do yet), go on to the
1295 } else if (acceptConstructor(node)) {
1296 // constructor (nothing else to do yet)
1297 } else if (acceptIdentifier(idToken)) {
1298 // identifier or function_call name
1299 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001300 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001301 } else if (acceptFunctionCall(idToken, node)) {
1302 // function_call (nothing else to do yet)
1303 } else {
1304 expected("function call arguments");
1305 return false;
1306 }
John Kessenich21472ae2016-06-04 11:46:33 -06001307 } else {
1308 // nothing found, can't post operate
1309 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001310 }
1311
John Kessenich21472ae2016-06-04 11:46:33 -06001312 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001313 do {
1314 TSourceLoc loc = token.loc;
1315 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001316
John Kessenich34fb0362016-05-03 23:17:20 -06001317 // Consume only a valid post-unary operator, otherwise we are done.
1318 switch (postOp) {
1319 case EOpIndexDirectStruct:
1320 case EOpIndexIndirect:
1321 case EOpPostIncrement:
1322 case EOpPostDecrement:
1323 advanceToken();
1324 break;
1325 default:
1326 return true;
1327 }
John Kessenich87142c72016-03-12 20:24:24 -07001328
John Kessenich34fb0362016-05-03 23:17:20 -06001329 // We have a valid post-unary operator, process it.
1330 switch (postOp) {
1331 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001332 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001333 // DOT IDENTIFIER
1334 // includes swizzles and struct members
1335 // TODO: possibly includes "method" syntax
John Kessenich93a162a2016-06-17 17:16:27 -06001336 HlslToken field;
1337 if (! acceptIdentifier(field)) {
1338 expected("swizzle or member");
1339 return false;
1340 }
1341 node = parseContext.handleDotDereference(field.loc, node, *field.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001342 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001343 }
John Kessenich34fb0362016-05-03 23:17:20 -06001344 case EOpIndexIndirect:
1345 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001346 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001347 TIntermTyped* indexNode = nullptr;
1348 if (! acceptExpression(indexNode) ||
1349 ! peekTokenClass(EHTokRightBracket)) {
1350 expected("expression followed by ']'");
1351 return false;
1352 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001353 advanceToken();
1354 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1355 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001356 }
1357 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001358 // INC_OP
1359 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001360 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001361 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001362 node = intermediate.addUnaryMath(postOp, node, loc);
1363 break;
1364 default:
1365 assert(0);
1366 break;
1367 }
1368 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001369}
1370
John Kessenichd016be12016-03-13 11:24:20 -06001371// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001372// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001373//
1374bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1375{
1376 // type
1377 TType type;
1378 if (acceptType(type)) {
1379 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1380 if (constructorFunction == nullptr)
1381 return false;
1382
1383 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001384 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001385 if (! acceptArguments(constructorFunction, arguments)) {
1386 expected("constructor arguments");
1387 return false;
1388 }
1389
1390 // hook it up
1391 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1392
1393 return true;
1394 }
1395
1396 return false;
1397}
1398
John Kessenich34fb0362016-05-03 23:17:20 -06001399// The function_call identifier was already recognized, and passed in as idToken.
1400//
1401// function_call
1402// : [idToken] arguments
1403//
John Kessenich4678ca92016-05-13 09:33:42 -06001404bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001405{
John Kessenich4678ca92016-05-13 09:33:42 -06001406 // arguments
1407 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1408 TIntermTyped* arguments = nullptr;
1409 if (! acceptArguments(function, arguments))
1410 return false;
1411
1412 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1413
1414 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001415}
1416
John Kessenich87142c72016-03-12 20:24:24 -07001417// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001418// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001419//
John Kessenichd016be12016-03-13 11:24:20 -06001420// The arguments are pushed onto the 'function' argument list and
1421// onto the 'arguments' aggregate.
1422//
John Kessenich4678ca92016-05-13 09:33:42 -06001423bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001424{
John Kessenich078d7f22016-03-14 10:02:11 -06001425 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001426 if (! acceptTokenClass(EHTokLeftParen))
1427 return false;
1428
1429 do {
John Kessenichd016be12016-03-13 11:24:20 -06001430 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001431 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001432 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001433 break;
John Kessenichd016be12016-03-13 11:24:20 -06001434
1435 // hook it up
1436 parseContext.handleFunctionArgument(function, arguments, arg);
1437
John Kessenich078d7f22016-03-14 10:02:11 -06001438 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001439 if (! acceptTokenClass(EHTokComma))
1440 break;
1441 } while (true);
1442
John Kessenich078d7f22016-03-14 10:02:11 -06001443 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001444 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001445 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001446 return false;
1447 }
1448
1449 return true;
1450}
1451
1452bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1453{
1454 switch (token.tokenClass) {
1455 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001456 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001457 break;
1458 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001459 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001460 break;
1461 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001462 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001463 break;
1464 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001465 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001466 break;
1467
1468 default:
1469 return false;
1470 }
1471
1472 advanceToken();
1473
1474 return true;
1475}
1476
John Kessenich5f934b02016-03-13 17:58:25 -06001477// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001478// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001479//
John Kessenich21472ae2016-06-04 11:46:33 -06001480bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001481{
John Kessenich21472ae2016-06-04 11:46:33 -06001482 TIntermAggregate* compoundStatement = nullptr;
1483
John Kessenich34fb0362016-05-03 23:17:20 -06001484 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001485 if (! acceptTokenClass(EHTokLeftBrace))
1486 return false;
1487
1488 // statement statement ...
1489 TIntermNode* statement = nullptr;
1490 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06001491 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
1492 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
1493 branch->getFlowOp() == EOpDefault)) {
1494 // hook up individual subsequences within a switch statement
1495 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
1496 compoundStatement = nullptr;
1497 } else {
1498 // hook it up to the growing compound statement
1499 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
1500 }
John Kessenich5f934b02016-03-13 17:58:25 -06001501 }
John Kessenich34fb0362016-05-03 23:17:20 -06001502 if (compoundStatement)
1503 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001504
John Kessenich21472ae2016-06-04 11:46:33 -06001505 retStatement = compoundStatement;
1506
John Kessenich34fb0362016-05-03 23:17:20 -06001507 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001508 return acceptTokenClass(EHTokRightBrace);
1509}
1510
John Kessenich0d2b6de2016-06-05 11:23:11 -06001511bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1512{
1513 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001514 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001515 parseContext.popScope();
1516
1517 return result;
1518}
1519
John Kessenich077e0522016-06-09 02:02:17 -06001520bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001521{
John Kessenich077e0522016-06-09 02:02:17 -06001522 parseContext.pushScope();
1523 bool result = acceptCompoundStatement(statement);
1524 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001525
1526 return result;
1527}
1528
John Kessenich5f934b02016-03-13 17:58:25 -06001529// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001530// : attributes attributed_statement
1531//
1532// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001533// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001534// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001535// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001536// | declaration_statement
1537// | selection_statement
1538// | switch_statement
1539// | case_label
1540// | iteration_statement
1541// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001542//
1543bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1544{
John Kessenich21472ae2016-06-04 11:46:33 -06001545 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001546
John Kessenich21472ae2016-06-04 11:46:33 -06001547 // attributes
1548 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001549
John Kessenich21472ae2016-06-04 11:46:33 -06001550 // attributed_statement
1551 switch (peek()) {
1552 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001553 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001554
John Kessenich21472ae2016-06-04 11:46:33 -06001555 case EHTokIf:
1556 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001557
John Kessenich21472ae2016-06-04 11:46:33 -06001558 case EHTokSwitch:
1559 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001560
John Kessenich21472ae2016-06-04 11:46:33 -06001561 case EHTokFor:
1562 case EHTokDo:
1563 case EHTokWhile:
1564 return acceptIterationStatement(statement);
1565
1566 case EHTokContinue:
1567 case EHTokBreak:
1568 case EHTokDiscard:
1569 case EHTokReturn:
1570 return acceptJumpStatement(statement);
1571
1572 case EHTokCase:
1573 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06001574 case EHTokDefault:
1575 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06001576
1577 case EHTokSemicolon:
1578 return acceptTokenClass(EHTokSemicolon);
1579
1580 case EHTokRightBrace:
1581 // Performance: not strictly necessary, but stops a bunch of hunting early,
1582 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001583 return false;
1584
John Kessenich21472ae2016-06-04 11:46:33 -06001585 default:
1586 {
1587 // declaration
1588 if (acceptDeclaration(statement))
1589 return true;
1590
1591 // expression
1592 TIntermTyped* node;
1593 if (acceptExpression(node))
1594 statement = node;
1595 else
1596 return false;
1597
1598 // SEMICOLON (following an expression)
1599 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001600 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001601 return false;
1602 }
1603 }
1604 }
1605
John Kessenich5f934b02016-03-13 17:58:25 -06001606 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001607}
1608
John Kessenich21472ae2016-06-04 11:46:33 -06001609// attributes
1610// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1611//
1612// attribute:
1613// : UNROLL
1614// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1615// | FASTOPT
1616// | ALLOW_UAV_CONDITION
1617// | BRANCH
1618// | FLATTEN
1619// | FORCECASE
1620// | CALL
1621//
1622void HlslGrammar::acceptAttributes()
1623{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001624 // For now, accept the [ XXX(X) ] syntax, but drop.
1625 // TODO: subset to correct set? Pass on?
1626 do {
1627 // LEFT_BRACKET?
1628 if (! acceptTokenClass(EHTokLeftBracket))
1629 return;
1630
1631 // attribute
1632 if (peekTokenClass(EHTokIdentifier)) {
1633 // 'token.string' is the attribute
1634 advanceToken();
1635 } else if (! peekTokenClass(EHTokRightBracket)) {
1636 expected("identifier");
1637 advanceToken();
1638 }
1639
1640 // (x)
1641 if (acceptTokenClass(EHTokLeftParen)) {
1642 TIntermTyped* node;
1643 if (! acceptLiteral(node))
1644 expected("literal");
1645 // 'node' has the literal in it
1646 if (! acceptTokenClass(EHTokRightParen))
1647 expected(")");
1648 }
1649
1650 // RIGHT_BRACKET
1651 if (acceptTokenClass(EHTokRightBracket))
1652 continue;
1653
1654 expected("]");
1655 return;
1656
1657 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001658}
1659
John Kessenich0d2b6de2016-06-05 11:23:11 -06001660// selection_statement
1661// : IF LEFT_PAREN expression RIGHT_PAREN statement
1662// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1663//
John Kessenich21472ae2016-06-04 11:46:33 -06001664bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1665{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001666 TSourceLoc loc = token.loc;
1667
1668 // IF
1669 if (! acceptTokenClass(EHTokIf))
1670 return false;
1671
1672 // so that something declared in the condition is scoped to the lifetimes
1673 // of the then-else statements
1674 parseContext.pushScope();
1675
1676 // LEFT_PAREN expression RIGHT_PAREN
1677 TIntermTyped* condition;
1678 if (! acceptParenExpression(condition))
1679 return false;
1680
1681 // create the child statements
1682 TIntermNodePair thenElse = { nullptr, nullptr };
1683
1684 // then statement
1685 if (! acceptScopedStatement(thenElse.node1)) {
1686 expected("then statement");
1687 return false;
1688 }
1689
1690 // ELSE
1691 if (acceptTokenClass(EHTokElse)) {
1692 // else statement
1693 if (! acceptScopedStatement(thenElse.node2)) {
1694 expected("else statement");
1695 return false;
1696 }
1697 }
1698
1699 // Put the pieces together
1700 statement = intermediate.addSelection(condition, thenElse, loc);
1701 parseContext.popScope();
1702
1703 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001704}
1705
John Kessenichd02dc5d2016-07-01 00:04:11 -06001706// switch_statement
1707// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
1708//
John Kessenich21472ae2016-06-04 11:46:33 -06001709bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1710{
John Kessenichd02dc5d2016-07-01 00:04:11 -06001711 // SWITCH
1712 TSourceLoc loc = token.loc;
1713 if (! acceptTokenClass(EHTokSwitch))
1714 return false;
1715
1716 // LEFT_PAREN expression RIGHT_PAREN
1717 parseContext.pushScope();
1718 TIntermTyped* switchExpression;
1719 if (! acceptParenExpression(switchExpression)) {
1720 parseContext.popScope();
1721 return false;
1722 }
1723
1724 // compound_statement
1725 parseContext.pushSwitchSequence(new TIntermSequence);
1726 bool statementOkay = acceptCompoundStatement(statement);
1727 if (statementOkay)
1728 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
1729
1730 parseContext.popSwitchSequence();
1731 parseContext.popScope();
1732
1733 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06001734}
1735
John Kessenich119f8f62016-06-05 15:44:07 -06001736// iteration_statement
1737// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1738// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1739// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1740//
1741// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001742bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1743{
John Kessenich119f8f62016-06-05 15:44:07 -06001744 TSourceLoc loc = token.loc;
1745 TIntermTyped* condition = nullptr;
1746
1747 EHlslTokenClass loop = peek();
1748 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1749
1750 // WHILE or DO or FOR
1751 advanceToken();
1752
1753 switch (loop) {
1754 case EHTokWhile:
1755 // so that something declared in the condition is scoped to the lifetime
1756 // of the while sub-statement
1757 parseContext.pushScope();
1758 parseContext.nestLooping();
1759
1760 // LEFT_PAREN condition RIGHT_PAREN
1761 if (! acceptParenExpression(condition))
1762 return false;
1763
1764 // statement
1765 if (! acceptScopedStatement(statement)) {
1766 expected("while sub-statement");
1767 return false;
1768 }
1769
1770 parseContext.unnestLooping();
1771 parseContext.popScope();
1772
1773 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1774
1775 return true;
1776
1777 case EHTokDo:
1778 parseContext.nestLooping();
1779
1780 if (! acceptTokenClass(EHTokLeftBrace))
1781 expected("{");
1782
1783 // statement
1784 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1785 expected("do sub-statement");
1786 return false;
1787 }
1788
1789 if (! acceptTokenClass(EHTokRightBrace))
1790 expected("}");
1791
1792 // WHILE
1793 if (! acceptTokenClass(EHTokWhile)) {
1794 expected("while");
1795 return false;
1796 }
1797
1798 // LEFT_PAREN condition RIGHT_PAREN
1799 TIntermTyped* condition;
1800 if (! acceptParenExpression(condition))
1801 return false;
1802
1803 if (! acceptTokenClass(EHTokSemicolon))
1804 expected(";");
1805
1806 parseContext.unnestLooping();
1807
1808 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1809
1810 return true;
1811
1812 case EHTokFor:
1813 {
1814 // LEFT_PAREN
1815 if (! acceptTokenClass(EHTokLeftParen))
1816 expected("(");
1817
1818 // so that something declared in the condition is scoped to the lifetime
1819 // of the for sub-statement
1820 parseContext.pushScope();
1821
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001822 // initializer
1823 TIntermNode* initNode = nullptr;
1824 if (! acceptControlDeclaration(initNode)) {
1825 TIntermTyped* initExpr = nullptr;
1826 acceptExpression(initExpr);
1827 initNode = initExpr;
1828 }
1829 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06001830 if (! acceptTokenClass(EHTokSemicolon))
1831 expected(";");
1832
1833 parseContext.nestLooping();
1834
1835 // condition SEMI_COLON
1836 acceptExpression(condition);
1837 if (! acceptTokenClass(EHTokSemicolon))
1838 expected(";");
1839
1840 // iterator SEMI_COLON
1841 TIntermTyped* iterator = nullptr;
1842 acceptExpression(iterator);
1843 if (! acceptTokenClass(EHTokRightParen))
1844 expected(")");
1845
1846 // statement
1847 if (! acceptScopedStatement(statement)) {
1848 expected("for sub-statement");
1849 return false;
1850 }
1851
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001852 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06001853
1854 parseContext.popScope();
1855 parseContext.unnestLooping();
1856
1857 return true;
1858 }
1859
1860 default:
1861 return false;
1862 }
John Kessenich21472ae2016-06-04 11:46:33 -06001863}
1864
1865// jump_statement
1866// : CONTINUE SEMICOLON
1867// | BREAK SEMICOLON
1868// | DISCARD SEMICOLON
1869// | RETURN SEMICOLON
1870// | RETURN expression SEMICOLON
1871//
1872bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1873{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001874 EHlslTokenClass jump = peek();
1875 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06001876 case EHTokContinue:
1877 case EHTokBreak:
1878 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06001879 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001880 advanceToken();
1881 break;
John Kessenich21472ae2016-06-04 11:46:33 -06001882 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001883 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06001884 return false;
1885 }
John Kessenich21472ae2016-06-04 11:46:33 -06001886
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001887 switch (jump) {
1888 case EHTokContinue:
1889 statement = intermediate.addBranch(EOpContinue, token.loc);
1890 break;
1891 case EHTokBreak:
1892 statement = intermediate.addBranch(EOpBreak, token.loc);
1893 break;
1894 case EHTokDiscard:
1895 statement = intermediate.addBranch(EOpKill, token.loc);
1896 break;
1897
1898 case EHTokReturn:
1899 {
1900 // expression
1901 TIntermTyped* node;
1902 if (acceptExpression(node)) {
1903 // hook it up
1904 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1905 } else
1906 statement = intermediate.addBranch(EOpReturn, token.loc);
1907 break;
1908 }
1909
1910 default:
1911 assert(0);
1912 return false;
1913 }
1914
1915 // SEMICOLON
1916 if (! acceptTokenClass(EHTokSemicolon))
1917 expected(";");
1918
1919 return true;
1920}
John Kessenich21472ae2016-06-04 11:46:33 -06001921
John Kessenichd02dc5d2016-07-01 00:04:11 -06001922// case_label
1923// : CASE expression COLON
1924//
John Kessenich21472ae2016-06-04 11:46:33 -06001925bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1926{
John Kessenichd02dc5d2016-07-01 00:04:11 -06001927 TSourceLoc loc = token.loc;
1928 if (! acceptTokenClass(EHTokCase))
1929 return false;
1930
1931 TIntermTyped* expression;
1932 if (! acceptExpression(expression)) {
1933 expected("case expression");
1934 return false;
1935 }
1936
1937 if (! acceptTokenClass(EHTokColon)) {
1938 expected(":");
1939 return false;
1940 }
1941
1942 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
1943
1944 return true;
1945}
1946
1947// default_label
1948// : DEFAULT COLON
1949//
1950bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
1951{
1952 TSourceLoc loc = token.loc;
1953 if (! acceptTokenClass(EHTokDefault))
1954 return false;
1955
1956 if (! acceptTokenClass(EHTokColon)) {
1957 expected(":");
1958 return false;
1959 }
1960
1961 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
1962
1963 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001964}
1965
John Kessenich19b92ff2016-06-19 11:50:34 -06001966// array_specifier
1967// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
1968//
1969void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
1970{
1971 arraySizes = nullptr;
1972
1973 if (! acceptTokenClass(EHTokLeftBracket))
1974 return;
1975
1976 TSourceLoc loc = token.loc;
1977 TIntermTyped* sizeExpr;
1978 if (! acceptAssignmentExpression(sizeExpr)) {
1979 expected("array-sizing expression");
1980 return;
1981 }
1982
1983 if (! acceptTokenClass(EHTokRightBracket)) {
1984 expected("]");
1985 return;
1986 }
1987
1988 TArraySize arraySize;
1989 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
1990 arraySizes = new TArraySizes;
1991 arraySizes->addInnerSize(arraySize);
1992}
1993
John Kessenich630dd7d2016-06-12 23:52:12 -06001994// post_decls
1995// : COLON semantic // optional
1996// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1997// COLON REGISTER // optional
1998// annotations // optional
1999//
2000void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06002001{
John Kessenich630dd7d2016-06-12 23:52:12 -06002002 do {
2003 // COLON
2004 if (acceptTokenClass(EHTokColon)) {
2005 HlslToken idToken;
2006 if (acceptTokenClass(EHTokPackOffset)) {
2007 if (! acceptTokenClass(EHTokLeftParen)) {
2008 expected("(");
2009 return;
2010 }
2011 acceptTokenClass(EHTokIdentifier);
2012 acceptTokenClass(EHTokDot);
2013 acceptTokenClass(EHTokIdentifier);
2014 if (! acceptTokenClass(EHTokRightParen)) {
2015 expected(")");
2016 break;
2017 }
2018 // TODO: process the packoffset information
2019 } else if (! acceptIdentifier(idToken)) {
2020 expected("semantic or packoffset or register");
2021 return;
2022 } else if (*idToken.string == "register") {
2023 if (! acceptTokenClass(EHTokLeftParen)) {
2024 expected("(");
2025 return;
2026 }
2027 acceptTokenClass(EHTokIdentifier);
2028 acceptTokenClass(EHTokComma);
2029 acceptTokenClass(EHTokIdentifier);
2030 acceptTokenClass(EHTokLeftBracket);
2031 if (peekTokenClass(EHTokIntConstant))
2032 advanceToken();
2033 acceptTokenClass(EHTokRightBracket);
2034 if (! acceptTokenClass(EHTokRightParen)) {
2035 expected(")");
2036 break;
2037 }
2038 // TODO: process the register information
2039 } else {
2040 // semantic, in idToken.string
2041 parseContext.handleSemantic(type, *idToken.string);
2042 }
2043 } else if (acceptTokenClass(EHTokLeftAngle)) {
2044 // TODO: process annotations, just accepting them for now
2045 do {
2046 if (peekTokenClass(EHTokNone))
2047 return;
2048 if (acceptTokenClass(EHTokRightAngle))
2049 break;
2050 advanceToken();
2051 } while (true);
2052 } else
2053 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002054
John Kessenich630dd7d2016-06-12 23:52:12 -06002055 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002056}
2057
John Kesseniche01a9bc2016-03-12 20:11:22 -07002058} // end namespace glslang