blob: ae978190266ace07530aa8b34dc22b914eb125ba [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
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600109// | 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 Kessenich5bc4d9a2016-06-20 01:22:38 -0600176// control_declaration
177// : fully_specified_type identifier EQUAL expression
178//
179bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
180{
181 node = nullptr;
182
183 // fully_specified_type
184 TType type;
185 if (! acceptFullySpecifiedType(type))
186 return false;
187
188 // identifier
189 HlslToken idToken;
190 if (! acceptIdentifier(idToken)) {
191 expected("identifier");
192 return false;
193 }
194
195 // EQUAL
196 TIntermTyped* expressionNode = nullptr;
197 if (! acceptTokenClass(EHTokAssign)) {
198 expected("=");
199 return false;
200 }
201
202 // expression
203 if (! acceptExpression(expressionNode)) {
204 expected("initializer");
205 return false;
206 }
207
208 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
209
210 return true;
211}
212
John Kessenich87142c72016-03-12 20:24:24 -0700213// fully_specified_type
214// : type_specifier
215// | type_qualifier type_specifier
216//
217bool HlslGrammar::acceptFullySpecifiedType(TType& type)
218{
219 // type_qualifier
220 TQualifier qualifier;
221 qualifier.clear();
222 acceptQualifier(qualifier);
223
224 // type_specifier
225 if (! acceptType(type))
226 return false;
227 type.getQualifier() = qualifier;
228
229 return true;
230}
231
John Kessenich630dd7d2016-06-12 23:52:12 -0600232// type_qualifier
233// : qualifier qualifier ...
234//
235// Zero or more of these, so this can't return false.
236//
John Kessenich87142c72016-03-12 20:24:24 -0700237void HlslGrammar::acceptQualifier(TQualifier& qualifier)
238{
John Kessenich630dd7d2016-06-12 23:52:12 -0600239 do {
240 switch (peek()) {
241 case EHTokStatic:
242 // normal glslang default
243 break;
244 case EHTokExtern:
245 // TODO: no meaning in glslang?
246 break;
247 case EHTokShared:
248 // TODO: hint
249 break;
250 case EHTokGroupShared:
251 qualifier.storage = EvqShared;
252 break;
253 case EHTokUniform:
254 qualifier.storage = EvqUniform;
255 break;
256 case EHTokConst:
257 qualifier.storage = EvqConst;
258 break;
259 case EHTokVolatile:
260 qualifier.volatil = true;
261 break;
262 case EHTokLinear:
263 qualifier.storage = EvqVaryingIn;
264 qualifier.smooth = true;
265 break;
266 case EHTokCentroid:
267 qualifier.centroid = true;
268 break;
269 case EHTokNointerpolation:
270 qualifier.flat = true;
271 break;
272 case EHTokNoperspective:
273 qualifier.nopersp = true;
274 break;
275 case EHTokSample:
276 qualifier.sample = true;
277 break;
278 case EHTokRowMajor:
279 qualifier.layoutMatrix = ElmRowMajor;
280 break;
281 case EHTokColumnMajor:
282 qualifier.layoutMatrix = ElmColumnMajor;
283 break;
284 case EHTokPrecise:
285 qualifier.noContraction = true;
286 break;
287 default:
288 return;
289 }
290 advanceToken();
291 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700292}
293
294// If token is for a type, update 'type' with the type information,
295// and return true and advance.
296// Otherwise, return false, and don't advance
297bool HlslGrammar::acceptType(TType& type)
298{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600299 switch (peek()) {
John Kesseniche6e74942016-06-11 16:43:14 -0600300 case EHTokStruct:
301 return acceptStruct(type);
302 break;
303
304 case EHTokIdentifier:
305 // An identifier could be for a user-defined type.
306 // Note we cache the symbol table lookup, to save for a later rule
307 // when this is not a type.
308 token.symbol = parseContext.symbolTable.find(*token.string);
309 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
310 type.shallowCopy(token.symbol->getType());
311 advanceToken();
312 return true;
313 } else
314 return false;
315
John Kessenich71351de2016-06-08 12:50:56 -0600316 case EHTokVoid:
317 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700318 break;
John Kessenich71351de2016-06-08 12:50:56 -0600319
John Kessenich87142c72016-03-12 20:24:24 -0700320 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600321 new(&type) TType(EbtFloat);
322 break;
John Kessenich87142c72016-03-12 20:24:24 -0700323 case EHTokFloat1:
324 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600325 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700326 break;
John Kessenich87142c72016-03-12 20:24:24 -0700327 case EHTokFloat2:
328 new(&type) TType(EbtFloat, EvqTemporary, 2);
329 break;
330 case EHTokFloat3:
331 new(&type) TType(EbtFloat, EvqTemporary, 3);
332 break;
333 case EHTokFloat4:
334 new(&type) TType(EbtFloat, EvqTemporary, 4);
335 break;
336
John Kessenich71351de2016-06-08 12:50:56 -0600337 case EHTokDouble:
338 new(&type) TType(EbtDouble);
339 break;
340 case EHTokDouble1:
341 new(&type) TType(EbtDouble);
342 type.makeVector();
343 break;
344 case EHTokDouble2:
345 new(&type) TType(EbtDouble, EvqTemporary, 2);
346 break;
347 case EHTokDouble3:
348 new(&type) TType(EbtDouble, EvqTemporary, 3);
349 break;
350 case EHTokDouble4:
351 new(&type) TType(EbtDouble, EvqTemporary, 4);
352 break;
353
354 case EHTokInt:
355 case EHTokDword:
356 new(&type) TType(EbtInt);
357 break;
358 case EHTokInt1:
359 new(&type) TType(EbtInt);
360 type.makeVector();
361 break;
John Kessenich87142c72016-03-12 20:24:24 -0700362 case EHTokInt2:
363 new(&type) TType(EbtInt, EvqTemporary, 2);
364 break;
365 case EHTokInt3:
366 new(&type) TType(EbtInt, EvqTemporary, 3);
367 break;
368 case EHTokInt4:
369 new(&type) TType(EbtInt, EvqTemporary, 4);
370 break;
371
John Kessenich71351de2016-06-08 12:50:56 -0600372 case EHTokUint:
373 new(&type) TType(EbtUint);
374 break;
375 case EHTokUint1:
376 new(&type) TType(EbtUint);
377 type.makeVector();
378 break;
379 case EHTokUint2:
380 new(&type) TType(EbtUint, EvqTemporary, 2);
381 break;
382 case EHTokUint3:
383 new(&type) TType(EbtUint, EvqTemporary, 3);
384 break;
385 case EHTokUint4:
386 new(&type) TType(EbtUint, EvqTemporary, 4);
387 break;
388
389 case EHTokBool:
390 new(&type) TType(EbtBool);
391 break;
392 case EHTokBool1:
393 new(&type) TType(EbtBool);
394 type.makeVector();
395 break;
John Kessenich87142c72016-03-12 20:24:24 -0700396 case EHTokBool2:
397 new(&type) TType(EbtBool, EvqTemporary, 2);
398 break;
399 case EHTokBool3:
400 new(&type) TType(EbtBool, EvqTemporary, 3);
401 break;
402 case EHTokBool4:
403 new(&type) TType(EbtBool, EvqTemporary, 4);
404 break;
405
John Kessenich0133c122016-05-20 12:17:26 -0600406 case EHTokInt1x1:
407 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
408 break;
409 case EHTokInt1x2:
410 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
411 break;
412 case EHTokInt1x3:
413 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
414 break;
415 case EHTokInt1x4:
416 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
417 break;
418 case EHTokInt2x1:
419 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
420 break;
421 case EHTokInt2x2:
422 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
423 break;
424 case EHTokInt2x3:
425 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
426 break;
427 case EHTokInt2x4:
428 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
429 break;
430 case EHTokInt3x1:
431 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
432 break;
433 case EHTokInt3x2:
434 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
435 break;
436 case EHTokInt3x3:
437 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
438 break;
439 case EHTokInt3x4:
440 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
441 break;
442 case EHTokInt4x1:
443 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
444 break;
445 case EHTokInt4x2:
446 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
447 break;
448 case EHTokInt4x3:
449 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
450 break;
451 case EHTokInt4x4:
452 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
453 break;
454
John Kessenich71351de2016-06-08 12:50:56 -0600455 case EHTokUint1x1:
456 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
457 break;
458 case EHTokUint1x2:
459 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
460 break;
461 case EHTokUint1x3:
462 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
463 break;
464 case EHTokUint1x4:
465 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
466 break;
467 case EHTokUint2x1:
468 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
469 break;
470 case EHTokUint2x2:
471 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
472 break;
473 case EHTokUint2x3:
474 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
475 break;
476 case EHTokUint2x4:
477 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
478 break;
479 case EHTokUint3x1:
480 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
481 break;
482 case EHTokUint3x2:
483 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
484 break;
485 case EHTokUint3x3:
486 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
487 break;
488 case EHTokUint3x4:
489 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
490 break;
491 case EHTokUint4x1:
492 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
493 break;
494 case EHTokUint4x2:
495 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
496 break;
497 case EHTokUint4x3:
498 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
499 break;
500 case EHTokUint4x4:
501 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
502 break;
503
504 case EHTokBool1x1:
505 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
506 break;
507 case EHTokBool1x2:
508 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
509 break;
510 case EHTokBool1x3:
511 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
512 break;
513 case EHTokBool1x4:
514 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
515 break;
516 case EHTokBool2x1:
517 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
518 break;
519 case EHTokBool2x2:
520 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
521 break;
522 case EHTokBool2x3:
523 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
524 break;
525 case EHTokBool2x4:
526 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
527 break;
528 case EHTokBool3x1:
529 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
530 break;
531 case EHTokBool3x2:
532 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
533 break;
534 case EHTokBool3x3:
535 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
536 break;
537 case EHTokBool3x4:
538 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
539 break;
540 case EHTokBool4x1:
541 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
542 break;
543 case EHTokBool4x2:
544 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
545 break;
546 case EHTokBool4x3:
547 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
548 break;
549 case EHTokBool4x4:
550 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
551 break;
552
John Kessenich0133c122016-05-20 12:17:26 -0600553 case EHTokFloat1x1:
554 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
555 break;
556 case EHTokFloat1x2:
557 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
558 break;
559 case EHTokFloat1x3:
560 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
561 break;
562 case EHTokFloat1x4:
563 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
564 break;
565 case EHTokFloat2x1:
566 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
567 break;
John Kessenich87142c72016-03-12 20:24:24 -0700568 case EHTokFloat2x2:
569 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
570 break;
571 case EHTokFloat2x3:
572 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
573 break;
574 case EHTokFloat2x4:
575 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
576 break;
John Kessenich0133c122016-05-20 12:17:26 -0600577 case EHTokFloat3x1:
578 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
579 break;
John Kessenich87142c72016-03-12 20:24:24 -0700580 case EHTokFloat3x2:
581 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
582 break;
583 case EHTokFloat3x3:
584 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
585 break;
586 case EHTokFloat3x4:
587 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
588 break;
John Kessenich0133c122016-05-20 12:17:26 -0600589 case EHTokFloat4x1:
590 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
591 break;
John Kessenich87142c72016-03-12 20:24:24 -0700592 case EHTokFloat4x2:
593 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
594 break;
595 case EHTokFloat4x3:
596 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
597 break;
598 case EHTokFloat4x4:
599 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
600 break;
601
John Kessenich0133c122016-05-20 12:17:26 -0600602 case EHTokDouble1x1:
603 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
604 break;
605 case EHTokDouble1x2:
606 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
607 break;
608 case EHTokDouble1x3:
609 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
610 break;
611 case EHTokDouble1x4:
612 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
613 break;
614 case EHTokDouble2x1:
615 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
616 break;
617 case EHTokDouble2x2:
618 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
619 break;
620 case EHTokDouble2x3:
621 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
622 break;
623 case EHTokDouble2x4:
624 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
625 break;
626 case EHTokDouble3x1:
627 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
628 break;
629 case EHTokDouble3x2:
630 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
631 break;
632 case EHTokDouble3x3:
633 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
634 break;
635 case EHTokDouble3x4:
636 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
637 break;
638 case EHTokDouble4x1:
639 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
640 break;
641 case EHTokDouble4x2:
642 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
643 break;
644 case EHTokDouble4x3:
645 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
646 break;
647 case EHTokDouble4x4:
648 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
649 break;
650
John Kessenich87142c72016-03-12 20:24:24 -0700651 default:
652 return false;
653 }
654
655 advanceToken();
656
657 return true;
658}
659
John Kesseniche6e74942016-06-11 16:43:14 -0600660// struct
661// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE
662// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE
663//
664bool HlslGrammar::acceptStruct(TType& type)
665{
666 // STRUCT
667 if (! acceptTokenClass(EHTokStruct))
668 return false;
669
670 // IDENTIFIER
671 TString structName = "";
672 if (peekTokenClass(EHTokIdentifier)) {
673 structName = *token.string;
674 advanceToken();
675 }
676
677 // LEFT_BRACE
678 if (! acceptTokenClass(EHTokLeftBrace)) {
679 expected("{");
680 return false;
681 }
682
683 // struct_declaration_list
684 TTypeList* typeList;
685 if (! acceptStructDeclarationList(typeList)) {
686 expected("struct member declarations");
687 return false;
688 }
689
690 // RIGHT_BRACE
691 if (! acceptTokenClass(EHTokRightBrace)) {
692 expected("}");
693 return false;
694 }
695
696 // create the user-defined type
697 new(&type) TType(typeList, structName);
698
699 // If it was named, which means it can be reused later, add
700 // it to the symbol table.
701 if (structName.size() > 0) {
702 TVariable* userTypeDef = new TVariable(&structName, type, true);
703 if (! parseContext.symbolTable.insert(*userTypeDef))
704 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
705 }
706
707 return true;
708}
709
710// struct_declaration_list
711// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
712//
713// struct_declaration
714// : fully_specified_type struct_declarator COMMA struct_declarator ...
715//
716// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -0600717// : IDENTIFIER post_decls
718// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -0600719//
720bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
721{
722 typeList = new TTypeList();
723
724 do {
725 // success on seeing the RIGHT_BRACE coming up
726 if (peekTokenClass(EHTokRightBrace))
727 return true;
728
729 // struct_declaration
730
731 // fully_specified_type
732 TType memberType;
733 if (! acceptFullySpecifiedType(memberType)) {
734 expected("member type");
735 return false;
736 }
737
738 // struct_declarator COMMA struct_declarator ...
739 do {
740 // peek IDENTIFIER
741 if (! peekTokenClass(EHTokIdentifier)) {
742 expected("member name");
743 return false;
744 }
745
746 // add it to the list of members
747 TTypeLoc member = { new TType(EbtVoid), token.loc };
748 member.type->shallowCopy(memberType);
749 member.type->setFieldName(*token.string);
750 typeList->push_back(member);
751
752 // accept IDENTIFIER
753 advanceToken();
754
755 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -0600756 TArraySizes* arraySizes = nullptr;
757 acceptArraySpecifier(arraySizes);
758 if (arraySizes)
759 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -0600760
John Kessenich630dd7d2016-06-12 23:52:12 -0600761 acceptPostDecls(*member.type);
762
John Kesseniche6e74942016-06-11 16:43:14 -0600763 // success on seeing the SEMICOLON coming up
764 if (peekTokenClass(EHTokSemicolon))
765 break;
766
767 // COMMA
768 if (! acceptTokenClass(EHTokComma)) {
769 expected(",");
770 return false;
771 }
772
773 } while (true);
774
775 // SEMI_COLON
776 if (! acceptTokenClass(EHTokSemicolon)) {
777 expected(";");
778 return false;
779 }
780
781 } while (true);
782}
783
John Kessenich5f934b02016-03-13 17:58:25 -0600784// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600785// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -0600786// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600787//
788bool HlslGrammar::acceptFunctionParameters(TFunction& function)
789{
John Kessenich078d7f22016-03-14 10:02:11 -0600790 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600791 if (! acceptTokenClass(EHTokLeftParen))
792 return false;
793
John Kessenich71351de2016-06-08 12:50:56 -0600794 // VOID RIGHT_PAREN
795 if (! acceptTokenClass(EHTokVoid)) {
796 do {
797 // parameter_declaration
798 if (! acceptParameterDeclaration(function))
799 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600800
John Kessenich71351de2016-06-08 12:50:56 -0600801 // COMMA
802 if (! acceptTokenClass(EHTokComma))
803 break;
804 } while (true);
805 }
John Kessenich5f934b02016-03-13 17:58:25 -0600806
John Kessenich078d7f22016-03-14 10:02:11 -0600807 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600808 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600809 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -0600810 return false;
811 }
812
813 return true;
814}
815
816// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -0600817// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -0600818// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -0600819//
820bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
821{
822 // fully_specified_type
823 TType* type = new TType;
824 if (! acceptFullySpecifiedType(*type))
825 return false;
826
827 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600828 HlslToken idToken;
829 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600830
John Kessenich19b92ff2016-06-19 11:50:34 -0600831 // array_specifier
832 TArraySizes* arraySizes = nullptr;
833 acceptArraySpecifier(arraySizes);
834 if (arraySizes)
835 type->newArraySizes(*arraySizes);
836
837 // post_decls
John Kessenichc3387d32016-06-17 14:21:02 -0600838 acceptPostDecls(*type);
839
John Kessenich5aa59e22016-06-17 15:50:47 -0600840 parseContext.paramFix(*type);
841
John Kessenichaecd4972016-03-14 10:46:34 -0600842 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600843 function.addParameter(param);
844
845 return true;
846}
847
848// Do the work to create the function definition in addition to
849// parsing the body (compound_statement).
850bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
851{
852 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
853
John Kessenich077e0522016-06-09 02:02:17 -0600854 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600855 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
856
857 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600858 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600859 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600860 node = intermediate.growAggregate(node, functionBody);
861 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600862 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600863 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600864
865 return true;
866 }
867
868 return false;
869}
870
John Kessenich0d2b6de2016-06-05 11:23:11 -0600871// Accept an expression with parenthesis around it, where
872// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600873// syntactically required ones like in "if ( expression )".
874//
875// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -0600876//
877// Note this one is not set up to be speculative; as it gives
878// errors if not found.
879//
880bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
881{
882 // LEFT_PAREN
883 if (! acceptTokenClass(EHTokLeftParen))
884 expected("(");
885
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600886 bool decl = false;
887 TIntermNode* declNode = nullptr;
888 decl = acceptControlDeclaration(declNode);
889 if (decl) {
890 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
891 expected("initialized declaration");
892 return false;
893 } else
894 expression = declNode->getAsTyped();
895 } else {
896 // no declaration
897 if (! acceptExpression(expression)) {
898 expected("expression");
899 return false;
900 }
John Kessenich0d2b6de2016-06-05 11:23:11 -0600901 }
902
903 // RIGHT_PAREN
904 if (! acceptTokenClass(EHTokRightParen))
905 expected(")");
906
907 return true;
908}
909
John Kessenich34fb0362016-05-03 23:17:20 -0600910// The top-level full expression recognizer.
911//
John Kessenich87142c72016-03-12 20:24:24 -0700912// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600913// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700914//
915bool HlslGrammar::acceptExpression(TIntermTyped*& node)
916{
LoopDawgef764a22016-06-03 09:17:51 -0600917 node = nullptr;
918
John Kessenich34fb0362016-05-03 23:17:20 -0600919 // assignment_expression
920 if (! acceptAssignmentExpression(node))
921 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600922
John Kessenich34fb0362016-05-03 23:17:20 -0600923 if (! peekTokenClass(EHTokComma))
924 return true;
925
926 do {
927 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600928 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600929 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600930
John Kessenich34fb0362016-05-03 23:17:20 -0600931 // ... assignment_expression
932 TIntermTyped* rightNode = nullptr;
933 if (! acceptAssignmentExpression(rightNode)) {
934 expected("assignment expression");
935 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600936 }
937
John Kessenich34fb0362016-05-03 23:17:20 -0600938 node = intermediate.addComma(node, rightNode, loc);
939
940 if (! peekTokenClass(EHTokComma))
941 return true;
942 } while (true);
943}
944
945// Accept an assignment expression, where assignment operations
946// associate right-to-left. This is, it is implicit, for example
947//
948// a op (b op (c op d))
949//
950// assigment_expression
951// : binary_expression op binary_expression op binary_expression ...
952//
953bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
954{
955 if (! acceptBinaryExpression(node, PlLogicalOr))
956 return false;
957
958 TOperator assignOp = HlslOpMap::assignment(peek());
959 if (assignOp == EOpNull)
960 return true;
961
962 // ... op
963 TSourceLoc loc = token.loc;
964 advanceToken();
965
966 // ... binary_expression
967 // But, done by recursing this function, which automatically
968 // gets the right-to-left associativity.
969 TIntermTyped* rightNode = nullptr;
970 if (! acceptAssignmentExpression(rightNode)) {
971 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600972 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700973 }
974
John Kessenich34fb0362016-05-03 23:17:20 -0600975 node = intermediate.addAssign(assignOp, node, rightNode, loc);
976
977 if (! peekTokenClass(EHTokComma))
978 return true;
979
980 return true;
981}
982
983// Accept a binary expression, for binary operations that
984// associate left-to-right. This is, it is implicit, for example
985//
986// ((a op b) op c) op d
987//
988// binary_expression
989// : expression op expression op expression ...
990//
991// where 'expression' is the next higher level in precedence.
992//
993bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
994{
995 if (precedenceLevel > PlMul)
996 return acceptUnaryExpression(node);
997
998 // assignment_expression
999 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1000 return false;
1001
1002 TOperator op = HlslOpMap::binary(peek());
1003 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1004 if (tokenLevel < precedenceLevel)
1005 return true;
1006
1007 do {
1008 // ... op
1009 TSourceLoc loc = token.loc;
1010 advanceToken();
1011
1012 // ... expression
1013 TIntermTyped* rightNode = nullptr;
1014 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1015 expected("expression");
1016 return false;
1017 }
1018
1019 node = intermediate.addBinaryMath(op, node, rightNode, loc);
1020
1021 if (! peekTokenClass(EHTokComma))
1022 return true;
1023 } while (true);
1024}
1025
1026// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001027// : (type) unary_expression
1028// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001029// | - unary_expression
1030// | ! unary_expression
1031// | ~ unary_expression
1032// | ++ unary_expression
1033// | -- unary_expression
1034// | postfix_expression
1035//
1036bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1037{
John Kessenich1cc1a282016-06-03 16:55:49 -06001038 // (type) unary_expression
1039 // Have to look two steps ahead, because this could be, e.g., a
1040 // postfix_expression instead, since that also starts with at "(".
1041 if (acceptTokenClass(EHTokLeftParen)) {
1042 TType castType;
1043 if (acceptType(castType)) {
1044 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001045 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -06001046 return false;
1047 }
1048
1049 // We've matched "(type)" now, get the expression to cast
1050 TSourceLoc loc = token.loc;
1051 if (! acceptUnaryExpression(node))
1052 return false;
1053
1054 // Hook it up like a constructor
1055 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1056 if (constructorFunction == nullptr) {
1057 expected("type that can be constructed");
1058 return false;
1059 }
1060 TIntermTyped* arguments = nullptr;
1061 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1062 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1063
1064 return true;
1065 } else {
1066 // This isn't a type cast, but it still started "(", so if it is a
1067 // unary expression, it can only be a postfix_expression, so try that.
1068 // Back it up first.
1069 recedeToken();
1070 return acceptPostfixExpression(node);
1071 }
1072 }
1073
1074 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001075 TOperator unaryOp = HlslOpMap::preUnary(peek());
1076
John Kessenich1cc1a282016-06-03 16:55:49 -06001077 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001078 if (unaryOp == EOpNull)
1079 return acceptPostfixExpression(node);
1080
1081 // op unary_expression
1082 TSourceLoc loc = token.loc;
1083 advanceToken();
1084 if (! acceptUnaryExpression(node))
1085 return false;
1086
1087 // + is a no-op
1088 if (unaryOp == EOpAdd)
1089 return true;
1090
1091 node = intermediate.addUnaryMath(unaryOp, node, loc);
1092
1093 return node != nullptr;
1094}
1095
1096// postfix_expression
1097// : LEFT_PAREN expression RIGHT_PAREN
1098// | literal
1099// | constructor
1100// | identifier
1101// | function_call
1102// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1103// | postfix_expression DOT IDENTIFIER
1104// | postfix_expression INC_OP
1105// | postfix_expression DEC_OP
1106//
1107bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1108{
1109 // Not implemented as self-recursive:
1110 // The logical "right recursion" is done with an loop at the end
1111
1112 // idToken will pick up either a variable or a function name in a function call
1113 HlslToken idToken;
1114
John Kessenich21472ae2016-06-04 11:46:33 -06001115 // Find something before the postfix operations, as they can't operate
1116 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001117 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001118 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001119 if (! acceptExpression(node)) {
1120 expected("expression");
1121 return false;
1122 }
1123 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001124 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001125 return false;
1126 }
John Kessenich34fb0362016-05-03 23:17:20 -06001127 } else if (acceptLiteral(node)) {
1128 // literal (nothing else to do yet), go on to the
1129 } else if (acceptConstructor(node)) {
1130 // constructor (nothing else to do yet)
1131 } else if (acceptIdentifier(idToken)) {
1132 // identifier or function_call name
1133 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001134 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001135 } else if (acceptFunctionCall(idToken, node)) {
1136 // function_call (nothing else to do yet)
1137 } else {
1138 expected("function call arguments");
1139 return false;
1140 }
John Kessenich21472ae2016-06-04 11:46:33 -06001141 } else {
1142 // nothing found, can't post operate
1143 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001144 }
1145
John Kessenich21472ae2016-06-04 11:46:33 -06001146 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001147 do {
1148 TSourceLoc loc = token.loc;
1149 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001150
John Kessenich34fb0362016-05-03 23:17:20 -06001151 // Consume only a valid post-unary operator, otherwise we are done.
1152 switch (postOp) {
1153 case EOpIndexDirectStruct:
1154 case EOpIndexIndirect:
1155 case EOpPostIncrement:
1156 case EOpPostDecrement:
1157 advanceToken();
1158 break;
1159 default:
1160 return true;
1161 }
John Kessenich87142c72016-03-12 20:24:24 -07001162
John Kessenich34fb0362016-05-03 23:17:20 -06001163 // We have a valid post-unary operator, process it.
1164 switch (postOp) {
1165 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001166 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001167 // DOT IDENTIFIER
1168 // includes swizzles and struct members
1169 // TODO: possibly includes "method" syntax
John Kessenich93a162a2016-06-17 17:16:27 -06001170 HlslToken field;
1171 if (! acceptIdentifier(field)) {
1172 expected("swizzle or member");
1173 return false;
1174 }
1175 node = parseContext.handleDotDereference(field.loc, node, *field.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001176 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001177 }
John Kessenich34fb0362016-05-03 23:17:20 -06001178 case EOpIndexIndirect:
1179 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001180 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001181 TIntermTyped* indexNode = nullptr;
1182 if (! acceptExpression(indexNode) ||
1183 ! peekTokenClass(EHTokRightBracket)) {
1184 expected("expression followed by ']'");
1185 return false;
1186 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001187 advanceToken();
1188 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1189 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001190 }
1191 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001192 // INC_OP
1193 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001194 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001195 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001196 node = intermediate.addUnaryMath(postOp, node, loc);
1197 break;
1198 default:
1199 assert(0);
1200 break;
1201 }
1202 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001203}
1204
John Kessenichd016be12016-03-13 11:24:20 -06001205// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001206// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001207//
1208bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1209{
1210 // type
1211 TType type;
1212 if (acceptType(type)) {
1213 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1214 if (constructorFunction == nullptr)
1215 return false;
1216
1217 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001218 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001219 if (! acceptArguments(constructorFunction, arguments)) {
1220 expected("constructor arguments");
1221 return false;
1222 }
1223
1224 // hook it up
1225 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1226
1227 return true;
1228 }
1229
1230 return false;
1231}
1232
John Kessenich34fb0362016-05-03 23:17:20 -06001233// The function_call identifier was already recognized, and passed in as idToken.
1234//
1235// function_call
1236// : [idToken] arguments
1237//
John Kessenich4678ca92016-05-13 09:33:42 -06001238bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001239{
John Kessenich4678ca92016-05-13 09:33:42 -06001240 // arguments
1241 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1242 TIntermTyped* arguments = nullptr;
1243 if (! acceptArguments(function, arguments))
1244 return false;
1245
1246 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1247
1248 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001249}
1250
John Kessenich87142c72016-03-12 20:24:24 -07001251// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001252// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001253//
John Kessenichd016be12016-03-13 11:24:20 -06001254// The arguments are pushed onto the 'function' argument list and
1255// onto the 'arguments' aggregate.
1256//
John Kessenich4678ca92016-05-13 09:33:42 -06001257bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001258{
John Kessenich078d7f22016-03-14 10:02:11 -06001259 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001260 if (! acceptTokenClass(EHTokLeftParen))
1261 return false;
1262
1263 do {
John Kessenichd016be12016-03-13 11:24:20 -06001264 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001265 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001266 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001267 break;
John Kessenichd016be12016-03-13 11:24:20 -06001268
1269 // hook it up
1270 parseContext.handleFunctionArgument(function, arguments, arg);
1271
John Kessenich078d7f22016-03-14 10:02:11 -06001272 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001273 if (! acceptTokenClass(EHTokComma))
1274 break;
1275 } while (true);
1276
John Kessenich078d7f22016-03-14 10:02:11 -06001277 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001278 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001279 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001280 return false;
1281 }
1282
1283 return true;
1284}
1285
1286bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1287{
1288 switch (token.tokenClass) {
1289 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001290 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001291 break;
1292 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001293 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001294 break;
1295 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001296 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001297 break;
1298 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001299 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001300 break;
1301
1302 default:
1303 return false;
1304 }
1305
1306 advanceToken();
1307
1308 return true;
1309}
1310
John Kessenich5f934b02016-03-13 17:58:25 -06001311// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001312// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001313//
John Kessenich21472ae2016-06-04 11:46:33 -06001314bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001315{
John Kessenich21472ae2016-06-04 11:46:33 -06001316 TIntermAggregate* compoundStatement = nullptr;
1317
John Kessenich34fb0362016-05-03 23:17:20 -06001318 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001319 if (! acceptTokenClass(EHTokLeftBrace))
1320 return false;
1321
1322 // statement statement ...
1323 TIntermNode* statement = nullptr;
1324 while (acceptStatement(statement)) {
1325 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001326 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001327 }
John Kessenich34fb0362016-05-03 23:17:20 -06001328 if (compoundStatement)
1329 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001330
John Kessenich21472ae2016-06-04 11:46:33 -06001331 retStatement = compoundStatement;
1332
John Kessenich34fb0362016-05-03 23:17:20 -06001333 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001334 return acceptTokenClass(EHTokRightBrace);
1335}
1336
John Kessenich0d2b6de2016-06-05 11:23:11 -06001337bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1338{
1339 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001340 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001341 parseContext.popScope();
1342
1343 return result;
1344}
1345
John Kessenich077e0522016-06-09 02:02:17 -06001346bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001347{
John Kessenich077e0522016-06-09 02:02:17 -06001348 parseContext.pushScope();
1349 bool result = acceptCompoundStatement(statement);
1350 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001351
1352 return result;
1353}
1354
John Kessenich5f934b02016-03-13 17:58:25 -06001355// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001356// : attributes attributed_statement
1357//
1358// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001359// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001360// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001361// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001362// | declaration_statement
1363// | selection_statement
1364// | switch_statement
1365// | case_label
1366// | iteration_statement
1367// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001368//
1369bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1370{
John Kessenich21472ae2016-06-04 11:46:33 -06001371 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001372
John Kessenich21472ae2016-06-04 11:46:33 -06001373 // attributes
1374 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001375
John Kessenich21472ae2016-06-04 11:46:33 -06001376 // attributed_statement
1377 switch (peek()) {
1378 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001379 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001380
John Kessenich21472ae2016-06-04 11:46:33 -06001381 case EHTokIf:
1382 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001383
John Kessenich21472ae2016-06-04 11:46:33 -06001384 case EHTokSwitch:
1385 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001386
John Kessenich21472ae2016-06-04 11:46:33 -06001387 case EHTokFor:
1388 case EHTokDo:
1389 case EHTokWhile:
1390 return acceptIterationStatement(statement);
1391
1392 case EHTokContinue:
1393 case EHTokBreak:
1394 case EHTokDiscard:
1395 case EHTokReturn:
1396 return acceptJumpStatement(statement);
1397
1398 case EHTokCase:
1399 return acceptCaseLabel(statement);
1400
1401 case EHTokSemicolon:
1402 return acceptTokenClass(EHTokSemicolon);
1403
1404 case EHTokRightBrace:
1405 // Performance: not strictly necessary, but stops a bunch of hunting early,
1406 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001407 return false;
1408
John Kessenich21472ae2016-06-04 11:46:33 -06001409 default:
1410 {
1411 // declaration
1412 if (acceptDeclaration(statement))
1413 return true;
1414
1415 // expression
1416 TIntermTyped* node;
1417 if (acceptExpression(node))
1418 statement = node;
1419 else
1420 return false;
1421
1422 // SEMICOLON (following an expression)
1423 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001424 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001425 return false;
1426 }
1427 }
1428 }
1429
John Kessenich5f934b02016-03-13 17:58:25 -06001430 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001431}
1432
John Kessenich21472ae2016-06-04 11:46:33 -06001433// attributes
1434// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1435//
1436// attribute:
1437// : UNROLL
1438// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1439// | FASTOPT
1440// | ALLOW_UAV_CONDITION
1441// | BRANCH
1442// | FLATTEN
1443// | FORCECASE
1444// | CALL
1445//
1446void HlslGrammar::acceptAttributes()
1447{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001448 // For now, accept the [ XXX(X) ] syntax, but drop.
1449 // TODO: subset to correct set? Pass on?
1450 do {
1451 // LEFT_BRACKET?
1452 if (! acceptTokenClass(EHTokLeftBracket))
1453 return;
1454
1455 // attribute
1456 if (peekTokenClass(EHTokIdentifier)) {
1457 // 'token.string' is the attribute
1458 advanceToken();
1459 } else if (! peekTokenClass(EHTokRightBracket)) {
1460 expected("identifier");
1461 advanceToken();
1462 }
1463
1464 // (x)
1465 if (acceptTokenClass(EHTokLeftParen)) {
1466 TIntermTyped* node;
1467 if (! acceptLiteral(node))
1468 expected("literal");
1469 // 'node' has the literal in it
1470 if (! acceptTokenClass(EHTokRightParen))
1471 expected(")");
1472 }
1473
1474 // RIGHT_BRACKET
1475 if (acceptTokenClass(EHTokRightBracket))
1476 continue;
1477
1478 expected("]");
1479 return;
1480
1481 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001482}
1483
John Kessenich0d2b6de2016-06-05 11:23:11 -06001484// selection_statement
1485// : IF LEFT_PAREN expression RIGHT_PAREN statement
1486// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1487//
John Kessenich21472ae2016-06-04 11:46:33 -06001488bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1489{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001490 TSourceLoc loc = token.loc;
1491
1492 // IF
1493 if (! acceptTokenClass(EHTokIf))
1494 return false;
1495
1496 // so that something declared in the condition is scoped to the lifetimes
1497 // of the then-else statements
1498 parseContext.pushScope();
1499
1500 // LEFT_PAREN expression RIGHT_PAREN
1501 TIntermTyped* condition;
1502 if (! acceptParenExpression(condition))
1503 return false;
1504
1505 // create the child statements
1506 TIntermNodePair thenElse = { nullptr, nullptr };
1507
1508 // then statement
1509 if (! acceptScopedStatement(thenElse.node1)) {
1510 expected("then statement");
1511 return false;
1512 }
1513
1514 // ELSE
1515 if (acceptTokenClass(EHTokElse)) {
1516 // else statement
1517 if (! acceptScopedStatement(thenElse.node2)) {
1518 expected("else statement");
1519 return false;
1520 }
1521 }
1522
1523 // Put the pieces together
1524 statement = intermediate.addSelection(condition, thenElse, loc);
1525 parseContext.popScope();
1526
1527 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001528}
1529
1530bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1531{
1532 return false;
1533}
1534
John Kessenich119f8f62016-06-05 15:44:07 -06001535// iteration_statement
1536// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1537// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1538// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1539//
1540// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001541bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1542{
John Kessenich119f8f62016-06-05 15:44:07 -06001543 TSourceLoc loc = token.loc;
1544 TIntermTyped* condition = nullptr;
1545
1546 EHlslTokenClass loop = peek();
1547 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1548
1549 // WHILE or DO or FOR
1550 advanceToken();
1551
1552 switch (loop) {
1553 case EHTokWhile:
1554 // so that something declared in the condition is scoped to the lifetime
1555 // of the while sub-statement
1556 parseContext.pushScope();
1557 parseContext.nestLooping();
1558
1559 // LEFT_PAREN condition RIGHT_PAREN
1560 if (! acceptParenExpression(condition))
1561 return false;
1562
1563 // statement
1564 if (! acceptScopedStatement(statement)) {
1565 expected("while sub-statement");
1566 return false;
1567 }
1568
1569 parseContext.unnestLooping();
1570 parseContext.popScope();
1571
1572 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1573
1574 return true;
1575
1576 case EHTokDo:
1577 parseContext.nestLooping();
1578
1579 if (! acceptTokenClass(EHTokLeftBrace))
1580 expected("{");
1581
1582 // statement
1583 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1584 expected("do sub-statement");
1585 return false;
1586 }
1587
1588 if (! acceptTokenClass(EHTokRightBrace))
1589 expected("}");
1590
1591 // WHILE
1592 if (! acceptTokenClass(EHTokWhile)) {
1593 expected("while");
1594 return false;
1595 }
1596
1597 // LEFT_PAREN condition RIGHT_PAREN
1598 TIntermTyped* condition;
1599 if (! acceptParenExpression(condition))
1600 return false;
1601
1602 if (! acceptTokenClass(EHTokSemicolon))
1603 expected(";");
1604
1605 parseContext.unnestLooping();
1606
1607 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1608
1609 return true;
1610
1611 case EHTokFor:
1612 {
1613 // LEFT_PAREN
1614 if (! acceptTokenClass(EHTokLeftParen))
1615 expected("(");
1616
1617 // so that something declared in the condition is scoped to the lifetime
1618 // of the for sub-statement
1619 parseContext.pushScope();
1620
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001621 // initializer
1622 TIntermNode* initNode = nullptr;
1623 if (! acceptControlDeclaration(initNode)) {
1624 TIntermTyped* initExpr = nullptr;
1625 acceptExpression(initExpr);
1626 initNode = initExpr;
1627 }
1628 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06001629 if (! acceptTokenClass(EHTokSemicolon))
1630 expected(";");
1631
1632 parseContext.nestLooping();
1633
1634 // condition SEMI_COLON
1635 acceptExpression(condition);
1636 if (! acceptTokenClass(EHTokSemicolon))
1637 expected(";");
1638
1639 // iterator SEMI_COLON
1640 TIntermTyped* iterator = nullptr;
1641 acceptExpression(iterator);
1642 if (! acceptTokenClass(EHTokRightParen))
1643 expected(")");
1644
1645 // statement
1646 if (! acceptScopedStatement(statement)) {
1647 expected("for sub-statement");
1648 return false;
1649 }
1650
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001651 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06001652
1653 parseContext.popScope();
1654 parseContext.unnestLooping();
1655
1656 return true;
1657 }
1658
1659 default:
1660 return false;
1661 }
John Kessenich21472ae2016-06-04 11:46:33 -06001662}
1663
1664// jump_statement
1665// : CONTINUE SEMICOLON
1666// | BREAK SEMICOLON
1667// | DISCARD SEMICOLON
1668// | RETURN SEMICOLON
1669// | RETURN expression SEMICOLON
1670//
1671bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1672{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001673 EHlslTokenClass jump = peek();
1674 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06001675 case EHTokContinue:
1676 case EHTokBreak:
1677 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06001678 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001679 advanceToken();
1680 break;
John Kessenich21472ae2016-06-04 11:46:33 -06001681 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001682 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06001683 return false;
1684 }
John Kessenich21472ae2016-06-04 11:46:33 -06001685
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001686 switch (jump) {
1687 case EHTokContinue:
1688 statement = intermediate.addBranch(EOpContinue, token.loc);
1689 break;
1690 case EHTokBreak:
1691 statement = intermediate.addBranch(EOpBreak, token.loc);
1692 break;
1693 case EHTokDiscard:
1694 statement = intermediate.addBranch(EOpKill, token.loc);
1695 break;
1696
1697 case EHTokReturn:
1698 {
1699 // expression
1700 TIntermTyped* node;
1701 if (acceptExpression(node)) {
1702 // hook it up
1703 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1704 } else
1705 statement = intermediate.addBranch(EOpReturn, token.loc);
1706 break;
1707 }
1708
1709 default:
1710 assert(0);
1711 return false;
1712 }
1713
1714 // SEMICOLON
1715 if (! acceptTokenClass(EHTokSemicolon))
1716 expected(";");
1717
1718 return true;
1719}
John Kessenich21472ae2016-06-04 11:46:33 -06001720
1721bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1722{
1723 return false;
1724}
1725
John Kessenich19b92ff2016-06-19 11:50:34 -06001726// array_specifier
1727// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
1728//
1729void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
1730{
1731 arraySizes = nullptr;
1732
1733 if (! acceptTokenClass(EHTokLeftBracket))
1734 return;
1735
1736 TSourceLoc loc = token.loc;
1737 TIntermTyped* sizeExpr;
1738 if (! acceptAssignmentExpression(sizeExpr)) {
1739 expected("array-sizing expression");
1740 return;
1741 }
1742
1743 if (! acceptTokenClass(EHTokRightBracket)) {
1744 expected("]");
1745 return;
1746 }
1747
1748 TArraySize arraySize;
1749 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
1750 arraySizes = new TArraySizes;
1751 arraySizes->addInnerSize(arraySize);
1752}
1753
John Kessenich630dd7d2016-06-12 23:52:12 -06001754// post_decls
1755// : COLON semantic // optional
1756// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1757// COLON REGISTER // optional
1758// annotations // optional
1759//
1760void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06001761{
John Kessenich630dd7d2016-06-12 23:52:12 -06001762 do {
1763 // COLON
1764 if (acceptTokenClass(EHTokColon)) {
1765 HlslToken idToken;
1766 if (acceptTokenClass(EHTokPackOffset)) {
1767 if (! acceptTokenClass(EHTokLeftParen)) {
1768 expected("(");
1769 return;
1770 }
1771 acceptTokenClass(EHTokIdentifier);
1772 acceptTokenClass(EHTokDot);
1773 acceptTokenClass(EHTokIdentifier);
1774 if (! acceptTokenClass(EHTokRightParen)) {
1775 expected(")");
1776 break;
1777 }
1778 // TODO: process the packoffset information
1779 } else if (! acceptIdentifier(idToken)) {
1780 expected("semantic or packoffset or register");
1781 return;
1782 } else if (*idToken.string == "register") {
1783 if (! acceptTokenClass(EHTokLeftParen)) {
1784 expected("(");
1785 return;
1786 }
1787 acceptTokenClass(EHTokIdentifier);
1788 acceptTokenClass(EHTokComma);
1789 acceptTokenClass(EHTokIdentifier);
1790 acceptTokenClass(EHTokLeftBracket);
1791 if (peekTokenClass(EHTokIntConstant))
1792 advanceToken();
1793 acceptTokenClass(EHTokRightBracket);
1794 if (! acceptTokenClass(EHTokRightParen)) {
1795 expected(")");
1796 break;
1797 }
1798 // TODO: process the register information
1799 } else {
1800 // semantic, in idToken.string
1801 parseContext.handleSemantic(type, *idToken.string);
1802 }
1803 } else if (acceptTokenClass(EHTokLeftAngle)) {
1804 // TODO: process annotations, just accepting them for now
1805 do {
1806 if (peekTokenClass(EHTokNone))
1807 return;
1808 if (acceptTokenClass(EHTokRightAngle))
1809 break;
1810 advanceToken();
1811 } while (true);
1812 } else
1813 break;
John Kessenich078d7f22016-03-14 10:02:11 -06001814
John Kessenich630dd7d2016-06-12 23:52:12 -06001815 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06001816}
1817
John Kesseniche01a9bc2016-03-12 20:11:22 -07001818} // end namespace glslang