blob: 1d08e158acf91dbe5c00d30105e57bb43f8c2a0a [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
LoopDawg4886f692016-06-29 10:58:58 -060072void HlslGrammar::unimplemented(const char* error)
73{
74 parseContext.error(token.loc, "Unimplemented", error, "");
75}
76
John Kessenichaecd4972016-03-14 10:46:34 -060077// Only process the next token if it is an identifier.
78// Return true if it was an identifier.
79bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
80{
81 if (peekTokenClass(EHTokIdentifier)) {
82 idToken = token;
83 advanceToken();
84 return true;
85 }
86
87 return false;
88}
89
John Kesseniche01a9bc2016-03-12 20:11:22 -070090// compilationUnit
91// : list of externalDeclaration
92//
93bool HlslGrammar::acceptCompilationUnit()
94{
John Kessenichd016be12016-03-13 11:24:20 -060095 TIntermNode* unitNode = nullptr;
96
John Kessenich9c86c6a2016-05-03 22:49:24 -060097 while (! peekTokenClass(EHTokNone)) {
John Kessenichd016be12016-03-13 11:24:20 -060098 // externalDeclaration
99 TIntermNode* declarationNode;
100 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700101 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600102
103 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600104 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700105 }
106
John Kessenichd016be12016-03-13 11:24:20 -0600107 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600108 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600109
John Kesseniche01a9bc2016-03-12 20:11:22 -0700110 return true;
111}
112
LoopDawg4886f692016-06-29 10:58:58 -0600113// sampler_state
114// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
115//
116// sampler_state_assignment
117// : sampler_state_identifier EQUAL value SEMICOLON
118//
119// sampler_state_identifier
120// : ADDRESSU
121// | ADDRESSV
122// | ADDRESSW
123// | BORDERCOLOR
124// | FILTER
125// | MAXANISOTROPY
126// | MAXLOD
127// | MINLOD
128// | MIPLODBIAS
129//
130bool HlslGrammar::acceptSamplerState()
131{
132 // TODO: this should be genericized to accept a list of valid tokens and
133 // return token/value pairs. Presently it is specific to texture values.
134
135 if (! acceptTokenClass(EHTokLeftBrace))
136 return true;
137
138 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
139
140 do {
141 // read state name
142 HlslToken state;
143 if (! acceptIdentifier(state))
144 break; // end of list
145
146 // FXC accepts any case
147 TString stateName = *state.string;
148 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
149
150 if (! acceptTokenClass(EHTokAssign)) {
151 expected("assign");
152 return false;
153 }
154
155 if (stateName == "minlod" || stateName == "maxlod") {
156 if (! peekTokenClass(EHTokIntConstant)) {
157 expected("integer");
158 return false;
159 }
160
161 TIntermTyped* lod = nullptr;
162 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
163 return false;
164 } else if (stateName == "maxanisotropy") {
165 if (! peekTokenClass(EHTokIntConstant)) {
166 expected("integer");
167 return false;
168 }
169
170 TIntermTyped* maxAnisotropy = nullptr;
171 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
172 return false;
173 } else if (stateName == "filter") {
174 HlslToken filterMode;
175 if (! acceptIdentifier(filterMode)) {
176 expected("filter mode");
177 return false;
178 }
179 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
180 HlslToken addrMode;
181 if (! acceptIdentifier(addrMode)) {
182 expected("texture address mode");
183 return false;
184 }
185 } else if (stateName == "miplodbias") {
186 TIntermTyped* lodBias = nullptr;
187 if (! acceptLiteral(lodBias)) {
188 expected("lod bias");
189 return false;
190 }
191 } else if (stateName == "bordercolor") {
192 return false;
193 } else {
194 expected("texture state");
195 return false;
196 }
197
198 // SEMICOLON
199 if (! acceptTokenClass(EHTokSemicolon)) {
200 expected("semicolon");
201 return false;
202 }
203 } while (true);
204
205 if (! acceptTokenClass(EHTokRightBrace))
206 return false;
207
208 return true;
209}
210
211// sampler_declaration_dx9
212// : SAMPLER identifier EQUAL sampler_type sampler_state
213//
214bool HlslGrammar::acceptSamplerDeclarationDX9(TType& type)
215{
216 if (! acceptTokenClass(EHTokSampler))
217 return false;
218
219 // TODO: remove this when DX9 style declarations are implemented.
220 unimplemented("Direct3D 9 sampler declaration");
221
222 // read sampler name
223 HlslToken name;
224 if (! acceptIdentifier(name)) {
225 expected("sampler name");
226 return false;
227 }
228
229 if (! acceptTokenClass(EHTokAssign)) {
230 expected("=");
231 return false;
232 }
233
234 return false;
235}
236
237
John Kesseniche01a9bc2016-03-12 20:11:22 -0700238// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600239// : sampler_declaration_dx9 post_decls SEMICOLON
240// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600241// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600242// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600243// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700244//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600245// declarator_list
246// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600247//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600248// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600249// : identifier array_specifier post_decls
250// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600251// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600252//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600253// Parsing has to go pretty far in to know whether it's a variable, prototype, or
254// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600255// as above. (The 'identifier' in the first item in init_declarator list is the
256// same as 'identifier' for function declarations.)
257//
258// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600259// or a function body.
260//
261bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700262{
John Kessenichd016be12016-03-13 11:24:20 -0600263 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600264 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600265
John Kessenich5e69ec62016-07-05 00:02:40 -0600266 // typedef
267 bool typedefDecl = acceptTokenClass(EHTokTypedef);
268
John Kessenich87142c72016-03-12 20:24:24 -0700269 TType type;
LoopDawg4886f692016-06-29 10:58:58 -0600270
271 // DX9 sampler declaration use a different syntax
272 if (acceptSamplerDeclarationDX9(type))
273 return true;
274
275 // fully_specified_type
John Kessenich87142c72016-03-12 20:24:24 -0700276 if (! acceptFullySpecifiedType(type))
277 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600278
279 if (type.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) {
280 if (type.getBasicType() == EbtSampler) {
281 // Sampler/textures are uniform by default (if no explicit qualifier is present) in
282 // HLSL. This line silently converts samplers *explicitly* declared static to uniform,
283 // which is incorrect but harmless.
284 type.getQualifier().storage = EvqUniform;
285 } else {
286 type.getQualifier().storage = EvqGlobal;
287 }
288 }
John Kessenich87142c72016-03-12 20:24:24 -0700289
290 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600291 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600292 while (acceptIdentifier(idToken)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600293 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600294 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600295 if (acceptFunctionParameters(*function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600296 // post_decls
297 acceptPostDecls(type);
John Kessenich078d7f22016-03-14 10:02:11 -0600298
John Kessenichd5ed0b62016-07-04 17:32:45 -0600299 // compound_statement (function body definition) or just a prototype?
300 if (peekTokenClass(EHTokLeftBrace)) {
301 if (list)
302 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600303 if (typedefDecl)
304 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich5f934b02016-03-13 17:58:25 -0600305 return acceptFunctionDefinition(*function, node);
John Kessenich5e69ec62016-07-05 00:02:40 -0600306 } else {
307 if (typedefDecl)
308 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600309 parseContext.handleFunctionDeclarator(idToken.loc, *function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600310 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600311 } else {
312 // a variable declaration
John Kessenich5f934b02016-03-13 17:58:25 -0600313
John Kessenichd5ed0b62016-07-04 17:32:45 -0600314 // array_specifier
315 TArraySizes* arraySizes = nullptr;
316 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600317
LoopDawg4886f692016-06-29 10:58:58 -0600318 // samplers accept immediate sampler state
319 if (type.getBasicType() == EbtSampler) {
320 if (! acceptSamplerState())
321 return false;
322 }
323
John Kessenichd5ed0b62016-07-04 17:32:45 -0600324 // post_decls
325 acceptPostDecls(type);
326
327 // EQUAL assignment_expression
328 TIntermTyped* expressionNode = nullptr;
329 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600330 if (typedefDecl)
331 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600332 if (! acceptAssignmentExpression(expressionNode)) {
333 expected("initializer");
334 return false;
335 }
336 }
337
John Kessenich5e69ec62016-07-05 00:02:40 -0600338 if (typedefDecl)
339 parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
340 else {
341 // Declare the variable and add any initializer code to the AST.
342 // The top-level node is always made into an aggregate, as that's
343 // historically how the AST has been.
344 node = intermediate.growAggregate(node,
345 parseContext.declareVariable(idToken.loc, *idToken.string, type,
346 arraySizes, expressionNode),
347 idToken.loc);
348 }
John Kessenich5f934b02016-03-13 17:58:25 -0600349 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600350
351 if (acceptTokenClass(EHTokComma)) {
352 list = true;
353 continue;
354 }
355 };
356
357 // The top-level node is a sequence.
358 if (node != nullptr)
359 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700360
John Kessenich078d7f22016-03-14 10:02:11 -0600361 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600362 if (! acceptTokenClass(EHTokSemicolon)) {
363 expected(";");
364 return false;
365 }
366
John Kesseniche01a9bc2016-03-12 20:11:22 -0700367 return true;
368}
369
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600370// control_declaration
371// : fully_specified_type identifier EQUAL expression
372//
373bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
374{
375 node = nullptr;
376
377 // fully_specified_type
378 TType type;
379 if (! acceptFullySpecifiedType(type))
380 return false;
381
382 // identifier
383 HlslToken idToken;
384 if (! acceptIdentifier(idToken)) {
385 expected("identifier");
386 return false;
387 }
388
389 // EQUAL
390 TIntermTyped* expressionNode = nullptr;
391 if (! acceptTokenClass(EHTokAssign)) {
392 expected("=");
393 return false;
394 }
395
396 // expression
397 if (! acceptExpression(expressionNode)) {
398 expected("initializer");
399 return false;
400 }
401
402 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
403
404 return true;
405}
406
John Kessenich87142c72016-03-12 20:24:24 -0700407// fully_specified_type
408// : type_specifier
409// | type_qualifier type_specifier
410//
411bool HlslGrammar::acceptFullySpecifiedType(TType& type)
412{
413 // type_qualifier
414 TQualifier qualifier;
415 qualifier.clear();
416 acceptQualifier(qualifier);
417
418 // type_specifier
419 if (! acceptType(type))
420 return false;
421 type.getQualifier() = qualifier;
422
423 return true;
424}
425
John Kessenich630dd7d2016-06-12 23:52:12 -0600426// type_qualifier
427// : qualifier qualifier ...
428//
429// Zero or more of these, so this can't return false.
430//
John Kessenich87142c72016-03-12 20:24:24 -0700431void HlslGrammar::acceptQualifier(TQualifier& qualifier)
432{
John Kessenich630dd7d2016-06-12 23:52:12 -0600433 do {
434 switch (peek()) {
435 case EHTokStatic:
436 // normal glslang default
437 break;
438 case EHTokExtern:
439 // TODO: no meaning in glslang?
440 break;
441 case EHTokShared:
442 // TODO: hint
443 break;
444 case EHTokGroupShared:
445 qualifier.storage = EvqShared;
446 break;
447 case EHTokUniform:
448 qualifier.storage = EvqUniform;
449 break;
450 case EHTokConst:
451 qualifier.storage = EvqConst;
452 break;
453 case EHTokVolatile:
454 qualifier.volatil = true;
455 break;
456 case EHTokLinear:
457 qualifier.storage = EvqVaryingIn;
458 qualifier.smooth = true;
459 break;
460 case EHTokCentroid:
461 qualifier.centroid = true;
462 break;
463 case EHTokNointerpolation:
464 qualifier.flat = true;
465 break;
466 case EHTokNoperspective:
467 qualifier.nopersp = true;
468 break;
469 case EHTokSample:
470 qualifier.sample = true;
471 break;
472 case EHTokRowMajor:
473 qualifier.layoutMatrix = ElmRowMajor;
474 break;
475 case EHTokColumnMajor:
476 qualifier.layoutMatrix = ElmColumnMajor;
477 break;
478 case EHTokPrecise:
479 qualifier.noContraction = true;
480 break;
481 default:
482 return;
483 }
484 advanceToken();
485 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700486}
487
LoopDawg6daaa4f2016-06-23 19:13:48 -0600488// template_type
489// : FLOAT
490// | DOUBLE
491// | INT
492// | DWORD
493// | UINT
494// | BOOL
495//
496bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
497{
498 switch (peek()) {
499 case EHTokFloat:
500 basicType = EbtFloat;
501 break;
502 case EHTokDouble:
503 basicType = EbtDouble;
504 break;
505 case EHTokInt:
506 case EHTokDword:
507 basicType = EbtInt;
508 break;
509 case EHTokUint:
510 basicType = EbtUint;
511 break;
512 case EHTokBool:
513 basicType = EbtBool;
514 break;
515 default:
516 return false;
517 }
518
519 advanceToken();
520
521 return true;
522}
523
524// vector_template_type
525// : VECTOR
526// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
527//
528bool HlslGrammar::acceptVectorTemplateType(TType& type)
529{
530 if (! acceptTokenClass(EHTokVector))
531 return false;
532
533 if (! acceptTokenClass(EHTokLeftAngle)) {
534 // in HLSL, 'vector' alone means float4.
535 new(&type) TType(EbtFloat, EvqTemporary, 4);
536 return true;
537 }
538
539 TBasicType basicType;
540 if (! acceptTemplateType(basicType)) {
541 expected("scalar type");
542 return false;
543 }
544
545 // COMMA
546 if (! acceptTokenClass(EHTokComma)) {
547 expected(",");
548 return false;
549 }
550
551 // integer
552 if (! peekTokenClass(EHTokIntConstant)) {
553 expected("literal integer");
554 return false;
555 }
556
557 TIntermTyped* vecSize;
558 if (! acceptLiteral(vecSize))
559 return false;
560
561 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
562
563 new(&type) TType(basicType, EvqTemporary, vecSizeI);
564
565 if (vecSizeI == 1)
566 type.makeVector();
567
568 if (!acceptTokenClass(EHTokRightAngle)) {
569 expected("right angle bracket");
570 return false;
571 }
572
573 return true;
574}
575
576// matrix_template_type
577// : MATRIX
578// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
579//
580bool HlslGrammar::acceptMatrixTemplateType(TType& type)
581{
582 if (! acceptTokenClass(EHTokMatrix))
583 return false;
584
585 if (! acceptTokenClass(EHTokLeftAngle)) {
586 // in HLSL, 'matrix' alone means float4x4.
587 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
588 return true;
589 }
590
591 TBasicType basicType;
592 if (! acceptTemplateType(basicType)) {
593 expected("scalar type");
594 return false;
595 }
596
597 // COMMA
598 if (! acceptTokenClass(EHTokComma)) {
599 expected(",");
600 return false;
601 }
602
603 // integer rows
604 if (! peekTokenClass(EHTokIntConstant)) {
605 expected("literal integer");
606 return false;
607 }
608
609 TIntermTyped* rows;
610 if (! acceptLiteral(rows))
611 return false;
612
613 // COMMA
614 if (! acceptTokenClass(EHTokComma)) {
615 expected(",");
616 return false;
617 }
618
619 // integer cols
620 if (! peekTokenClass(EHTokIntConstant)) {
621 expected("literal integer");
622 return false;
623 }
624
625 TIntermTyped* cols;
626 if (! acceptLiteral(cols))
627 return false;
628
629 new(&type) TType(basicType, EvqTemporary, 0,
630 cols->getAsConstantUnion()->getConstArray()[0].getIConst(),
631 rows->getAsConstantUnion()->getConstArray()[0].getIConst());
632
633 if (!acceptTokenClass(EHTokRightAngle)) {
634 expected("right angle bracket");
635 return false;
636 }
637
638 return true;
639}
640
641
LoopDawg4886f692016-06-29 10:58:58 -0600642// sampler_type
643// : SAMPLER
644// | SAMPLER1D
645// | SAMPLER2D
646// | SAMPLER3D
647// | SAMPLERCUBE
648// | SAMPLERSTATE
649// | SAMPLERCOMPARISONSTATE
650bool HlslGrammar::acceptSamplerType(TType& type)
651{
652 // read sampler type
653 const EHlslTokenClass samplerType = peek();
654
655 TSamplerDim dim = EsdNone;
656
657 switch (samplerType) {
658 case EHTokSampler: break;
659 case EHTokSampler1d: dim = Esd1D; break;
660 case EHTokSampler2d: dim = Esd2D; break;
661 case EHTokSampler3d: dim = Esd3D; break;
662 case EHTokSamplerCube: dim = EsdCube; break;
663 case EHTokSamplerState: break;
664 case EHTokSamplerComparisonState: break;
665 default:
666 return false; // not a sampler declaration
667 }
668
669 advanceToken(); // consume the sampler type keyword
670
671 TArraySizes* arraySizes = nullptr; // TODO: array
672 bool shadow = false; // TODO: shadow
673
674 TSampler sampler;
675 sampler.setPureSampler(shadow);
676
677 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
678
679 return true;
680}
681
682// texture_type
683// | BUFFER
684// | TEXTURE1D
685// | TEXTURE1DARRAY
686// | TEXTURE2D
687// | TEXTURE2DARRAY
688// | TEXTURE3D
689// | TEXTURECUBE
690// | TEXTURECUBEARRAY
691// | TEXTURE2DMS
692// | TEXTURE2DMSARRAY
693bool HlslGrammar::acceptTextureType(TType& type)
694{
695 const EHlslTokenClass textureType = peek();
696
697 TSamplerDim dim = EsdNone;
698 bool array = false;
699 bool ms = false;
700
701 switch (textureType) {
702 case EHTokBuffer: dim = EsdBuffer; break;
703 case EHTokTexture1d: dim = Esd1D; break;
704 case EHTokTexture1darray: dim = Esd1D; array = true; break;
705 case EHTokTexture2d: dim = Esd2D; break;
706 case EHTokTexture2darray: dim = Esd2D; array = true; break;
707 case EHTokTexture3d: dim = Esd3D; break;
708 case EHTokTextureCube: dim = EsdCube; break;
709 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
710 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
711 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
712 default:
713 return false; // not a texture declaration
714 }
715
716 advanceToken(); // consume the texture object keyword
717
718 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
719
720 TIntermTyped* msCount = nullptr;
721
722 // texture type: required for multisample types!
723 if (acceptTokenClass(EHTokLeftAngle)) {
724 if (! acceptType(txType)) {
725 expected("scalar or vector type");
726 return false;
727 }
728
729 const TBasicType basicRetType = txType.getBasicType() ;
730
731 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
732 unimplemented("basic type in texture");
733 return false;
734 }
735
736 if (!txType.isScalar() && !txType.isVector()) {
737 expected("scalar or vector type");
738 return false;
739 }
740
741 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
742 // TODO: handle vec2/3 types
743 expected("vector size not yet supported in texture type");
744 return false;
745 }
746
747 if (ms && acceptTokenClass(EHTokComma)) {
748 // read sample count for multisample types, if given
749 if (! peekTokenClass(EHTokIntConstant)) {
750 expected("multisample count");
751 return false;
752 }
753
754 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
755 return false;
756 }
757
758 if (! acceptTokenClass(EHTokRightAngle)) {
759 expected("right angle bracket");
760 return false;
761 }
762 } else if (ms) {
763 expected("texture type for multisample");
764 return false;
765 }
766
767 TArraySizes* arraySizes = nullptr;
768 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
769
770 TSampler sampler;
771 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
772
773 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
774
775 return true;
776}
777
778
John Kessenich87142c72016-03-12 20:24:24 -0700779// If token is for a type, update 'type' with the type information,
780// and return true and advance.
781// Otherwise, return false, and don't advance
782bool HlslGrammar::acceptType(TType& type)
783{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600784 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600785 case EHTokVector:
786 return acceptVectorTemplateType(type);
787 break;
788
789 case EHTokMatrix:
790 return acceptMatrixTemplateType(type);
791 break;
792
LoopDawg4886f692016-06-29 10:58:58 -0600793 case EHTokSampler: // fall through
794 case EHTokSampler1d: // ...
795 case EHTokSampler2d: // ...
796 case EHTokSampler3d: // ...
797 case EHTokSamplerCube: // ...
798 case EHTokSamplerState: // ...
799 case EHTokSamplerComparisonState: // ...
800 return acceptSamplerType(type);
801 break;
802
803 case EHTokBuffer: // fall through
804 case EHTokTexture1d: // ...
805 case EHTokTexture1darray: // ...
806 case EHTokTexture2d: // ...
807 case EHTokTexture2darray: // ...
808 case EHTokTexture3d: // ...
809 case EHTokTextureCube: // ...
810 case EHTokTextureCubearray: // ...
811 case EHTokTexture2DMS: // ...
812 case EHTokTexture2DMSarray: // ...
813 return acceptTextureType(type);
814 break;
815
John Kesseniche6e74942016-06-11 16:43:14 -0600816 case EHTokStruct:
817 return acceptStruct(type);
818 break;
819
820 case EHTokIdentifier:
821 // An identifier could be for a user-defined type.
822 // Note we cache the symbol table lookup, to save for a later rule
823 // when this is not a type.
824 token.symbol = parseContext.symbolTable.find(*token.string);
825 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
826 type.shallowCopy(token.symbol->getType());
827 advanceToken();
828 return true;
829 } else
830 return false;
831
John Kessenich71351de2016-06-08 12:50:56 -0600832 case EHTokVoid:
833 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700834 break;
John Kessenich71351de2016-06-08 12:50:56 -0600835
John Kessenich87142c72016-03-12 20:24:24 -0700836 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600837 new(&type) TType(EbtFloat);
838 break;
John Kessenich87142c72016-03-12 20:24:24 -0700839 case EHTokFloat1:
840 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600841 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700842 break;
John Kessenich87142c72016-03-12 20:24:24 -0700843 case EHTokFloat2:
844 new(&type) TType(EbtFloat, EvqTemporary, 2);
845 break;
846 case EHTokFloat3:
847 new(&type) TType(EbtFloat, EvqTemporary, 3);
848 break;
849 case EHTokFloat4:
850 new(&type) TType(EbtFloat, EvqTemporary, 4);
851 break;
852
John Kessenich71351de2016-06-08 12:50:56 -0600853 case EHTokDouble:
854 new(&type) TType(EbtDouble);
855 break;
856 case EHTokDouble1:
857 new(&type) TType(EbtDouble);
858 type.makeVector();
859 break;
860 case EHTokDouble2:
861 new(&type) TType(EbtDouble, EvqTemporary, 2);
862 break;
863 case EHTokDouble3:
864 new(&type) TType(EbtDouble, EvqTemporary, 3);
865 break;
866 case EHTokDouble4:
867 new(&type) TType(EbtDouble, EvqTemporary, 4);
868 break;
869
870 case EHTokInt:
871 case EHTokDword:
872 new(&type) TType(EbtInt);
873 break;
874 case EHTokInt1:
875 new(&type) TType(EbtInt);
876 type.makeVector();
877 break;
John Kessenich87142c72016-03-12 20:24:24 -0700878 case EHTokInt2:
879 new(&type) TType(EbtInt, EvqTemporary, 2);
880 break;
881 case EHTokInt3:
882 new(&type) TType(EbtInt, EvqTemporary, 3);
883 break;
884 case EHTokInt4:
885 new(&type) TType(EbtInt, EvqTemporary, 4);
886 break;
887
John Kessenich71351de2016-06-08 12:50:56 -0600888 case EHTokUint:
889 new(&type) TType(EbtUint);
890 break;
891 case EHTokUint1:
892 new(&type) TType(EbtUint);
893 type.makeVector();
894 break;
895 case EHTokUint2:
896 new(&type) TType(EbtUint, EvqTemporary, 2);
897 break;
898 case EHTokUint3:
899 new(&type) TType(EbtUint, EvqTemporary, 3);
900 break;
901 case EHTokUint4:
902 new(&type) TType(EbtUint, EvqTemporary, 4);
903 break;
904
LoopDawg6daaa4f2016-06-23 19:13:48 -0600905
John Kessenich71351de2016-06-08 12:50:56 -0600906 case EHTokBool:
907 new(&type) TType(EbtBool);
908 break;
909 case EHTokBool1:
910 new(&type) TType(EbtBool);
911 type.makeVector();
912 break;
John Kessenich87142c72016-03-12 20:24:24 -0700913 case EHTokBool2:
914 new(&type) TType(EbtBool, EvqTemporary, 2);
915 break;
916 case EHTokBool3:
917 new(&type) TType(EbtBool, EvqTemporary, 3);
918 break;
919 case EHTokBool4:
920 new(&type) TType(EbtBool, EvqTemporary, 4);
921 break;
922
John Kessenich0133c122016-05-20 12:17:26 -0600923 case EHTokInt1x1:
924 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
925 break;
926 case EHTokInt1x2:
927 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
928 break;
929 case EHTokInt1x3:
930 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
931 break;
932 case EHTokInt1x4:
933 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
934 break;
935 case EHTokInt2x1:
936 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
937 break;
938 case EHTokInt2x2:
939 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
940 break;
941 case EHTokInt2x3:
942 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
943 break;
944 case EHTokInt2x4:
945 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
946 break;
947 case EHTokInt3x1:
948 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
949 break;
950 case EHTokInt3x2:
951 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
952 break;
953 case EHTokInt3x3:
954 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
955 break;
956 case EHTokInt3x4:
957 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
958 break;
959 case EHTokInt4x1:
960 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
961 break;
962 case EHTokInt4x2:
963 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
964 break;
965 case EHTokInt4x3:
966 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
967 break;
968 case EHTokInt4x4:
969 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
970 break;
971
John Kessenich71351de2016-06-08 12:50:56 -0600972 case EHTokUint1x1:
973 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
974 break;
975 case EHTokUint1x2:
976 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
977 break;
978 case EHTokUint1x3:
979 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
980 break;
981 case EHTokUint1x4:
982 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
983 break;
984 case EHTokUint2x1:
985 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
986 break;
987 case EHTokUint2x2:
988 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
989 break;
990 case EHTokUint2x3:
991 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
992 break;
993 case EHTokUint2x4:
994 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
995 break;
996 case EHTokUint3x1:
997 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
998 break;
999 case EHTokUint3x2:
1000 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
1001 break;
1002 case EHTokUint3x3:
1003 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1004 break;
1005 case EHTokUint3x4:
1006 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
1007 break;
1008 case EHTokUint4x1:
1009 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
1010 break;
1011 case EHTokUint4x2:
1012 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
1013 break;
1014 case EHTokUint4x3:
1015 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
1016 break;
1017 case EHTokUint4x4:
1018 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1019 break;
1020
1021 case EHTokBool1x1:
1022 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1023 break;
1024 case EHTokBool1x2:
1025 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
1026 break;
1027 case EHTokBool1x3:
1028 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
1029 break;
1030 case EHTokBool1x4:
1031 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
1032 break;
1033 case EHTokBool2x1:
1034 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
1035 break;
1036 case EHTokBool2x2:
1037 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1038 break;
1039 case EHTokBool2x3:
1040 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
1041 break;
1042 case EHTokBool2x4:
1043 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
1044 break;
1045 case EHTokBool3x1:
1046 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
1047 break;
1048 case EHTokBool3x2:
1049 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
1050 break;
1051 case EHTokBool3x3:
1052 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1053 break;
1054 case EHTokBool3x4:
1055 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
1056 break;
1057 case EHTokBool4x1:
1058 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
1059 break;
1060 case EHTokBool4x2:
1061 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
1062 break;
1063 case EHTokBool4x3:
1064 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
1065 break;
1066 case EHTokBool4x4:
1067 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1068 break;
1069
John Kessenich0133c122016-05-20 12:17:26 -06001070 case EHTokFloat1x1:
1071 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1072 break;
1073 case EHTokFloat1x2:
1074 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
1075 break;
1076 case EHTokFloat1x3:
1077 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
1078 break;
1079 case EHTokFloat1x4:
1080 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
1081 break;
1082 case EHTokFloat2x1:
1083 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
1084 break;
John Kessenich87142c72016-03-12 20:24:24 -07001085 case EHTokFloat2x2:
1086 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1087 break;
1088 case EHTokFloat2x3:
1089 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
1090 break;
1091 case EHTokFloat2x4:
1092 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
1093 break;
John Kessenich0133c122016-05-20 12:17:26 -06001094 case EHTokFloat3x1:
1095 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
1096 break;
John Kessenich87142c72016-03-12 20:24:24 -07001097 case EHTokFloat3x2:
1098 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
1099 break;
1100 case EHTokFloat3x3:
1101 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1102 break;
1103 case EHTokFloat3x4:
1104 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
1105 break;
John Kessenich0133c122016-05-20 12:17:26 -06001106 case EHTokFloat4x1:
1107 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
1108 break;
John Kessenich87142c72016-03-12 20:24:24 -07001109 case EHTokFloat4x2:
1110 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
1111 break;
1112 case EHTokFloat4x3:
1113 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
1114 break;
1115 case EHTokFloat4x4:
1116 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1117 break;
1118
John Kessenich0133c122016-05-20 12:17:26 -06001119 case EHTokDouble1x1:
1120 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1121 break;
1122 case EHTokDouble1x2:
1123 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
1124 break;
1125 case EHTokDouble1x3:
1126 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
1127 break;
1128 case EHTokDouble1x4:
1129 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
1130 break;
1131 case EHTokDouble2x1:
1132 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
1133 break;
1134 case EHTokDouble2x2:
1135 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1136 break;
1137 case EHTokDouble2x3:
1138 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
1139 break;
1140 case EHTokDouble2x4:
1141 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
1142 break;
1143 case EHTokDouble3x1:
1144 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
1145 break;
1146 case EHTokDouble3x2:
1147 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
1148 break;
1149 case EHTokDouble3x3:
1150 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1151 break;
1152 case EHTokDouble3x4:
1153 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
1154 break;
1155 case EHTokDouble4x1:
1156 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
1157 break;
1158 case EHTokDouble4x2:
1159 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
1160 break;
1161 case EHTokDouble4x3:
1162 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
1163 break;
1164 case EHTokDouble4x4:
1165 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1166 break;
1167
John Kessenich87142c72016-03-12 20:24:24 -07001168 default:
1169 return false;
1170 }
1171
1172 advanceToken();
1173
1174 return true;
1175}
1176
John Kesseniche6e74942016-06-11 16:43:14 -06001177// struct
1178// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE
1179// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE
1180//
1181bool HlslGrammar::acceptStruct(TType& type)
1182{
1183 // STRUCT
1184 if (! acceptTokenClass(EHTokStruct))
1185 return false;
1186
1187 // IDENTIFIER
1188 TString structName = "";
1189 if (peekTokenClass(EHTokIdentifier)) {
1190 structName = *token.string;
1191 advanceToken();
1192 }
1193
1194 // LEFT_BRACE
1195 if (! acceptTokenClass(EHTokLeftBrace)) {
1196 expected("{");
1197 return false;
1198 }
1199
1200 // struct_declaration_list
1201 TTypeList* typeList;
1202 if (! acceptStructDeclarationList(typeList)) {
1203 expected("struct member declarations");
1204 return false;
1205 }
1206
1207 // RIGHT_BRACE
1208 if (! acceptTokenClass(EHTokRightBrace)) {
1209 expected("}");
1210 return false;
1211 }
1212
1213 // create the user-defined type
1214 new(&type) TType(typeList, structName);
1215
1216 // If it was named, which means it can be reused later, add
1217 // it to the symbol table.
1218 if (structName.size() > 0) {
1219 TVariable* userTypeDef = new TVariable(&structName, type, true);
1220 if (! parseContext.symbolTable.insert(*userTypeDef))
1221 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1222 }
1223
1224 return true;
1225}
1226
1227// struct_declaration_list
1228// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1229//
1230// struct_declaration
1231// : fully_specified_type struct_declarator COMMA struct_declarator ...
1232//
1233// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001234// : IDENTIFIER post_decls
1235// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001236//
1237bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1238{
1239 typeList = new TTypeList();
1240
1241 do {
1242 // success on seeing the RIGHT_BRACE coming up
1243 if (peekTokenClass(EHTokRightBrace))
1244 return true;
1245
1246 // struct_declaration
1247
1248 // fully_specified_type
1249 TType memberType;
1250 if (! acceptFullySpecifiedType(memberType)) {
1251 expected("member type");
1252 return false;
1253 }
1254
1255 // struct_declarator COMMA struct_declarator ...
1256 do {
1257 // peek IDENTIFIER
1258 if (! peekTokenClass(EHTokIdentifier)) {
1259 expected("member name");
1260 return false;
1261 }
1262
1263 // add it to the list of members
1264 TTypeLoc member = { new TType(EbtVoid), token.loc };
1265 member.type->shallowCopy(memberType);
1266 member.type->setFieldName(*token.string);
1267 typeList->push_back(member);
1268
1269 // accept IDENTIFIER
1270 advanceToken();
1271
1272 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001273 TArraySizes* arraySizes = nullptr;
1274 acceptArraySpecifier(arraySizes);
1275 if (arraySizes)
1276 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001277
John Kessenich630dd7d2016-06-12 23:52:12 -06001278 acceptPostDecls(*member.type);
1279
John Kesseniche6e74942016-06-11 16:43:14 -06001280 // success on seeing the SEMICOLON coming up
1281 if (peekTokenClass(EHTokSemicolon))
1282 break;
1283
1284 // COMMA
1285 if (! acceptTokenClass(EHTokComma)) {
1286 expected(",");
1287 return false;
1288 }
1289
1290 } while (true);
1291
1292 // SEMI_COLON
1293 if (! acceptTokenClass(EHTokSemicolon)) {
1294 expected(";");
1295 return false;
1296 }
1297
1298 } while (true);
1299}
1300
John Kessenich5f934b02016-03-13 17:58:25 -06001301// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001302// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001303// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001304//
1305bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1306{
John Kessenich078d7f22016-03-14 10:02:11 -06001307 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001308 if (! acceptTokenClass(EHTokLeftParen))
1309 return false;
1310
John Kessenich71351de2016-06-08 12:50:56 -06001311 // VOID RIGHT_PAREN
1312 if (! acceptTokenClass(EHTokVoid)) {
1313 do {
1314 // parameter_declaration
1315 if (! acceptParameterDeclaration(function))
1316 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001317
John Kessenich71351de2016-06-08 12:50:56 -06001318 // COMMA
1319 if (! acceptTokenClass(EHTokComma))
1320 break;
1321 } while (true);
1322 }
John Kessenich5f934b02016-03-13 17:58:25 -06001323
John Kessenich078d7f22016-03-14 10:02:11 -06001324 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001325 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001326 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001327 return false;
1328 }
1329
1330 return true;
1331}
1332
1333// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001334// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001335// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001336//
1337bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1338{
1339 // fully_specified_type
1340 TType* type = new TType;
1341 if (! acceptFullySpecifiedType(*type))
1342 return false;
1343
1344 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001345 HlslToken idToken;
1346 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001347
John Kessenich19b92ff2016-06-19 11:50:34 -06001348 // array_specifier
1349 TArraySizes* arraySizes = nullptr;
1350 acceptArraySpecifier(arraySizes);
1351 if (arraySizes)
1352 type->newArraySizes(*arraySizes);
1353
1354 // post_decls
John Kessenichc3387d32016-06-17 14:21:02 -06001355 acceptPostDecls(*type);
1356
John Kessenich5aa59e22016-06-17 15:50:47 -06001357 parseContext.paramFix(*type);
1358
John Kessenichaecd4972016-03-14 10:46:34 -06001359 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001360 function.addParameter(param);
1361
1362 return true;
1363}
1364
1365// Do the work to create the function definition in addition to
1366// parsing the body (compound_statement).
1367bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1368{
1369 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
1370
John Kessenich077e0522016-06-09 02:02:17 -06001371 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -06001372 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
1373
1374 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001375 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001376 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -06001377 node = intermediate.growAggregate(node, functionBody);
1378 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -06001379 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -06001380 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -06001381
1382 return true;
1383 }
1384
1385 return false;
1386}
1387
John Kessenich0d2b6de2016-06-05 11:23:11 -06001388// Accept an expression with parenthesis around it, where
1389// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001390// syntactically required ones like in "if ( expression )".
1391//
1392// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001393//
1394// Note this one is not set up to be speculative; as it gives
1395// errors if not found.
1396//
1397bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1398{
1399 // LEFT_PAREN
1400 if (! acceptTokenClass(EHTokLeftParen))
1401 expected("(");
1402
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001403 bool decl = false;
1404 TIntermNode* declNode = nullptr;
1405 decl = acceptControlDeclaration(declNode);
1406 if (decl) {
1407 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1408 expected("initialized declaration");
1409 return false;
1410 } else
1411 expression = declNode->getAsTyped();
1412 } else {
1413 // no declaration
1414 if (! acceptExpression(expression)) {
1415 expected("expression");
1416 return false;
1417 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001418 }
1419
1420 // RIGHT_PAREN
1421 if (! acceptTokenClass(EHTokRightParen))
1422 expected(")");
1423
1424 return true;
1425}
1426
John Kessenich34fb0362016-05-03 23:17:20 -06001427// The top-level full expression recognizer.
1428//
John Kessenich87142c72016-03-12 20:24:24 -07001429// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001430// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001431//
1432bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1433{
LoopDawgef764a22016-06-03 09:17:51 -06001434 node = nullptr;
1435
John Kessenich34fb0362016-05-03 23:17:20 -06001436 // assignment_expression
1437 if (! acceptAssignmentExpression(node))
1438 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001439
John Kessenich34fb0362016-05-03 23:17:20 -06001440 if (! peekTokenClass(EHTokComma))
1441 return true;
1442
1443 do {
1444 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001445 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001446 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001447
John Kessenich34fb0362016-05-03 23:17:20 -06001448 // ... assignment_expression
1449 TIntermTyped* rightNode = nullptr;
1450 if (! acceptAssignmentExpression(rightNode)) {
1451 expected("assignment expression");
1452 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001453 }
1454
John Kessenich34fb0362016-05-03 23:17:20 -06001455 node = intermediate.addComma(node, rightNode, loc);
1456
1457 if (! peekTokenClass(EHTokComma))
1458 return true;
1459 } while (true);
1460}
1461
John Kessenich07354242016-07-01 19:58:06 -06001462// initializer
1463// : LEFT_BRACE initializer_list RIGHT_BRACE
1464//
1465// initializer_list
1466// : assignment_expression COMMA assignment_expression COMMA ...
1467//
1468bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1469{
1470 // LEFT_BRACE
1471 if (! acceptTokenClass(EHTokLeftBrace))
1472 return false;
1473
1474 // initializer_list
1475 TSourceLoc loc = token.loc;
1476 node = nullptr;
1477 do {
1478 // assignment_expression
1479 TIntermTyped* expr;
1480 if (! acceptAssignmentExpression(expr)) {
1481 expected("assignment expression in initializer list");
1482 return false;
1483 }
1484 node = intermediate.growAggregate(node, expr, loc);
1485
1486 // COMMA
1487 if (acceptTokenClass(EHTokComma))
1488 continue;
1489
1490 // RIGHT_BRACE
1491 if (acceptTokenClass(EHTokRightBrace))
1492 return true;
1493
1494 expected(", or }");
1495 return false;
1496 } while (true);
1497}
1498
John Kessenich34fb0362016-05-03 23:17:20 -06001499// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001500// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001501//
1502// a op (b op (c op d))
1503//
1504// assigment_expression
1505// : binary_expression op binary_expression op binary_expression ...
John Kessenich07354242016-07-01 19:58:06 -06001506// | initializer
John Kessenich34fb0362016-05-03 23:17:20 -06001507//
1508bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1509{
John Kessenich07354242016-07-01 19:58:06 -06001510 // initializer
1511 if (peekTokenClass(EHTokLeftBrace)) {
1512 if (acceptInitializer(node))
1513 return true;
1514
1515 expected("initializer");
1516 return false;
1517 }
1518
1519 // binary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001520 if (! acceptBinaryExpression(node, PlLogicalOr))
1521 return false;
1522
John Kessenich07354242016-07-01 19:58:06 -06001523 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001524 TOperator assignOp = HlslOpMap::assignment(peek());
1525 if (assignOp == EOpNull)
1526 return true;
1527
John Kessenich07354242016-07-01 19:58:06 -06001528 // assignment op
John Kessenich34fb0362016-05-03 23:17:20 -06001529 TSourceLoc loc = token.loc;
1530 advanceToken();
1531
John Kessenich07354242016-07-01 19:58:06 -06001532 // binary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001533 // But, done by recursing this function, which automatically
1534 // gets the right-to-left associativity.
1535 TIntermTyped* rightNode = nullptr;
1536 if (! acceptAssignmentExpression(rightNode)) {
1537 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001538 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001539 }
1540
John Kessenich34fb0362016-05-03 23:17:20 -06001541 node = intermediate.addAssign(assignOp, node, rightNode, loc);
1542
1543 if (! peekTokenClass(EHTokComma))
1544 return true;
1545
1546 return true;
1547}
1548
1549// Accept a binary expression, for binary operations that
1550// associate left-to-right. This is, it is implicit, for example
1551//
1552// ((a op b) op c) op d
1553//
1554// binary_expression
1555// : expression op expression op expression ...
1556//
1557// where 'expression' is the next higher level in precedence.
1558//
1559bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1560{
1561 if (precedenceLevel > PlMul)
1562 return acceptUnaryExpression(node);
1563
1564 // assignment_expression
1565 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1566 return false;
1567
1568 TOperator op = HlslOpMap::binary(peek());
1569 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1570 if (tokenLevel < precedenceLevel)
1571 return true;
1572
1573 do {
1574 // ... op
1575 TSourceLoc loc = token.loc;
1576 advanceToken();
1577
1578 // ... expression
1579 TIntermTyped* rightNode = nullptr;
1580 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1581 expected("expression");
1582 return false;
1583 }
1584
1585 node = intermediate.addBinaryMath(op, node, rightNode, loc);
1586
1587 if (! peekTokenClass(EHTokComma))
1588 return true;
1589 } while (true);
1590}
1591
1592// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001593// : (type) unary_expression
1594// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001595// | - unary_expression
1596// | ! unary_expression
1597// | ~ unary_expression
1598// | ++ unary_expression
1599// | -- unary_expression
1600// | postfix_expression
1601//
1602bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1603{
John Kessenich1cc1a282016-06-03 16:55:49 -06001604 // (type) unary_expression
1605 // Have to look two steps ahead, because this could be, e.g., a
1606 // postfix_expression instead, since that also starts with at "(".
1607 if (acceptTokenClass(EHTokLeftParen)) {
1608 TType castType;
1609 if (acceptType(castType)) {
1610 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001611 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -06001612 return false;
1613 }
1614
1615 // We've matched "(type)" now, get the expression to cast
1616 TSourceLoc loc = token.loc;
1617 if (! acceptUnaryExpression(node))
1618 return false;
1619
1620 // Hook it up like a constructor
1621 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1622 if (constructorFunction == nullptr) {
1623 expected("type that can be constructed");
1624 return false;
1625 }
1626 TIntermTyped* arguments = nullptr;
1627 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1628 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1629
1630 return true;
1631 } else {
1632 // This isn't a type cast, but it still started "(", so if it is a
1633 // unary expression, it can only be a postfix_expression, so try that.
1634 // Back it up first.
1635 recedeToken();
1636 return acceptPostfixExpression(node);
1637 }
1638 }
1639
1640 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001641 TOperator unaryOp = HlslOpMap::preUnary(peek());
1642
John Kessenich1cc1a282016-06-03 16:55:49 -06001643 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001644 if (unaryOp == EOpNull)
1645 return acceptPostfixExpression(node);
1646
1647 // op unary_expression
1648 TSourceLoc loc = token.loc;
1649 advanceToken();
1650 if (! acceptUnaryExpression(node))
1651 return false;
1652
1653 // + is a no-op
1654 if (unaryOp == EOpAdd)
1655 return true;
1656
1657 node = intermediate.addUnaryMath(unaryOp, node, loc);
1658
1659 return node != nullptr;
1660}
1661
1662// postfix_expression
1663// : LEFT_PAREN expression RIGHT_PAREN
1664// | literal
1665// | constructor
1666// | identifier
1667// | function_call
1668// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1669// | postfix_expression DOT IDENTIFIER
1670// | postfix_expression INC_OP
1671// | postfix_expression DEC_OP
1672//
1673bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1674{
1675 // Not implemented as self-recursive:
1676 // The logical "right recursion" is done with an loop at the end
1677
1678 // idToken will pick up either a variable or a function name in a function call
1679 HlslToken idToken;
1680
John Kessenich21472ae2016-06-04 11:46:33 -06001681 // Find something before the postfix operations, as they can't operate
1682 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001683 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001684 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001685 if (! acceptExpression(node)) {
1686 expected("expression");
1687 return false;
1688 }
1689 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001690 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001691 return false;
1692 }
John Kessenich34fb0362016-05-03 23:17:20 -06001693 } else if (acceptLiteral(node)) {
1694 // literal (nothing else to do yet), go on to the
1695 } else if (acceptConstructor(node)) {
1696 // constructor (nothing else to do yet)
1697 } else if (acceptIdentifier(idToken)) {
1698 // identifier or function_call name
1699 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001700 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001701 } else if (acceptFunctionCall(idToken, node)) {
1702 // function_call (nothing else to do yet)
1703 } else {
1704 expected("function call arguments");
1705 return false;
1706 }
John Kessenich21472ae2016-06-04 11:46:33 -06001707 } else {
1708 // nothing found, can't post operate
1709 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001710 }
1711
John Kessenich21472ae2016-06-04 11:46:33 -06001712 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001713 do {
1714 TSourceLoc loc = token.loc;
1715 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001716
John Kessenich34fb0362016-05-03 23:17:20 -06001717 // Consume only a valid post-unary operator, otherwise we are done.
1718 switch (postOp) {
1719 case EOpIndexDirectStruct:
1720 case EOpIndexIndirect:
1721 case EOpPostIncrement:
1722 case EOpPostDecrement:
1723 advanceToken();
1724 break;
1725 default:
1726 return true;
1727 }
John Kessenich87142c72016-03-12 20:24:24 -07001728
John Kessenich34fb0362016-05-03 23:17:20 -06001729 // We have a valid post-unary operator, process it.
1730 switch (postOp) {
1731 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001732 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001733 // DOT IDENTIFIER
1734 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001735 HlslToken field;
1736 if (! acceptIdentifier(field)) {
1737 expected("swizzle or member");
1738 return false;
1739 }
LoopDawg4886f692016-06-29 10:58:58 -06001740
1741 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001742 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001743
1744 // In the event of a method node, we look for an open paren and accept the function call.
1745 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1746 if (! acceptFunctionCall(field, node, base)) {
1747 expected("function parameters");
1748 return false;
1749 }
1750 }
1751
John Kessenich34fb0362016-05-03 23:17:20 -06001752 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001753 }
John Kessenich34fb0362016-05-03 23:17:20 -06001754 case EOpIndexIndirect:
1755 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001756 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001757 TIntermTyped* indexNode = nullptr;
1758 if (! acceptExpression(indexNode) ||
1759 ! peekTokenClass(EHTokRightBracket)) {
1760 expected("expression followed by ']'");
1761 return false;
1762 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001763 advanceToken();
1764 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1765 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001766 }
1767 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001768 // INC_OP
1769 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001770 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001771 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001772 node = intermediate.addUnaryMath(postOp, node, loc);
1773 break;
1774 default:
1775 assert(0);
1776 break;
1777 }
1778 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001779}
1780
John Kessenichd016be12016-03-13 11:24:20 -06001781// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001782// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001783//
1784bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1785{
1786 // type
1787 TType type;
1788 if (acceptType(type)) {
1789 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1790 if (constructorFunction == nullptr)
1791 return false;
1792
1793 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001794 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001795 if (! acceptArguments(constructorFunction, arguments)) {
1796 expected("constructor arguments");
1797 return false;
1798 }
1799
1800 // hook it up
1801 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1802
1803 return true;
1804 }
1805
1806 return false;
1807}
1808
John Kessenich34fb0362016-05-03 23:17:20 -06001809// The function_call identifier was already recognized, and passed in as idToken.
1810//
1811// function_call
1812// : [idToken] arguments
1813//
LoopDawg4886f692016-06-29 10:58:58 -06001814bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06001815{
John Kessenich4678ca92016-05-13 09:33:42 -06001816 // arguments
1817 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1818 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06001819
1820 // methods have an implicit first argument of the calling object.
1821 if (base != nullptr)
1822 parseContext.handleFunctionArgument(function, arguments, base);
1823
John Kessenich4678ca92016-05-13 09:33:42 -06001824 if (! acceptArguments(function, arguments))
1825 return false;
1826
1827 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1828
1829 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001830}
1831
John Kessenich87142c72016-03-12 20:24:24 -07001832// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001833// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001834//
John Kessenichd016be12016-03-13 11:24:20 -06001835// The arguments are pushed onto the 'function' argument list and
1836// onto the 'arguments' aggregate.
1837//
John Kessenich4678ca92016-05-13 09:33:42 -06001838bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001839{
John Kessenich078d7f22016-03-14 10:02:11 -06001840 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001841 if (! acceptTokenClass(EHTokLeftParen))
1842 return false;
1843
1844 do {
John Kessenichd016be12016-03-13 11:24:20 -06001845 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001846 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001847 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001848 break;
John Kessenichd016be12016-03-13 11:24:20 -06001849
1850 // hook it up
1851 parseContext.handleFunctionArgument(function, arguments, arg);
1852
John Kessenich078d7f22016-03-14 10:02:11 -06001853 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001854 if (! acceptTokenClass(EHTokComma))
1855 break;
1856 } while (true);
1857
John Kessenich078d7f22016-03-14 10:02:11 -06001858 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001859 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001860 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001861 return false;
1862 }
1863
1864 return true;
1865}
1866
1867bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1868{
1869 switch (token.tokenClass) {
1870 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001871 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001872 break;
1873 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001874 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001875 break;
1876 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001877 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001878 break;
1879 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001880 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001881 break;
1882
1883 default:
1884 return false;
1885 }
1886
1887 advanceToken();
1888
1889 return true;
1890}
1891
John Kessenich5f934b02016-03-13 17:58:25 -06001892// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001893// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001894//
John Kessenich21472ae2016-06-04 11:46:33 -06001895bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001896{
John Kessenich21472ae2016-06-04 11:46:33 -06001897 TIntermAggregate* compoundStatement = nullptr;
1898
John Kessenich34fb0362016-05-03 23:17:20 -06001899 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001900 if (! acceptTokenClass(EHTokLeftBrace))
1901 return false;
1902
1903 // statement statement ...
1904 TIntermNode* statement = nullptr;
1905 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06001906 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
1907 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
1908 branch->getFlowOp() == EOpDefault)) {
1909 // hook up individual subsequences within a switch statement
1910 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
1911 compoundStatement = nullptr;
1912 } else {
1913 // hook it up to the growing compound statement
1914 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
1915 }
John Kessenich5f934b02016-03-13 17:58:25 -06001916 }
John Kessenich34fb0362016-05-03 23:17:20 -06001917 if (compoundStatement)
1918 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001919
John Kessenich21472ae2016-06-04 11:46:33 -06001920 retStatement = compoundStatement;
1921
John Kessenich34fb0362016-05-03 23:17:20 -06001922 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001923 return acceptTokenClass(EHTokRightBrace);
1924}
1925
John Kessenich0d2b6de2016-06-05 11:23:11 -06001926bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1927{
1928 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001929 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001930 parseContext.popScope();
1931
1932 return result;
1933}
1934
John Kessenich077e0522016-06-09 02:02:17 -06001935bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001936{
John Kessenich077e0522016-06-09 02:02:17 -06001937 parseContext.pushScope();
1938 bool result = acceptCompoundStatement(statement);
1939 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001940
1941 return result;
1942}
1943
John Kessenich5f934b02016-03-13 17:58:25 -06001944// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001945// : attributes attributed_statement
1946//
1947// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001948// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001949// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001950// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001951// | declaration_statement
1952// | selection_statement
1953// | switch_statement
1954// | case_label
1955// | iteration_statement
1956// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001957//
1958bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1959{
John Kessenich21472ae2016-06-04 11:46:33 -06001960 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001961
John Kessenich21472ae2016-06-04 11:46:33 -06001962 // attributes
1963 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001964
John Kessenich21472ae2016-06-04 11:46:33 -06001965 // attributed_statement
1966 switch (peek()) {
1967 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001968 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001969
John Kessenich21472ae2016-06-04 11:46:33 -06001970 case EHTokIf:
1971 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001972
John Kessenich21472ae2016-06-04 11:46:33 -06001973 case EHTokSwitch:
1974 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001975
John Kessenich21472ae2016-06-04 11:46:33 -06001976 case EHTokFor:
1977 case EHTokDo:
1978 case EHTokWhile:
1979 return acceptIterationStatement(statement);
1980
1981 case EHTokContinue:
1982 case EHTokBreak:
1983 case EHTokDiscard:
1984 case EHTokReturn:
1985 return acceptJumpStatement(statement);
1986
1987 case EHTokCase:
1988 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06001989 case EHTokDefault:
1990 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06001991
1992 case EHTokSemicolon:
1993 return acceptTokenClass(EHTokSemicolon);
1994
1995 case EHTokRightBrace:
1996 // Performance: not strictly necessary, but stops a bunch of hunting early,
1997 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001998 return false;
1999
John Kessenich21472ae2016-06-04 11:46:33 -06002000 default:
2001 {
2002 // declaration
2003 if (acceptDeclaration(statement))
2004 return true;
2005
2006 // expression
2007 TIntermTyped* node;
2008 if (acceptExpression(node))
2009 statement = node;
2010 else
2011 return false;
2012
2013 // SEMICOLON (following an expression)
2014 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002015 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002016 return false;
2017 }
2018 }
2019 }
2020
John Kessenich5f934b02016-03-13 17:58:25 -06002021 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002022}
2023
John Kessenich21472ae2016-06-04 11:46:33 -06002024// attributes
2025// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2026//
2027// attribute:
2028// : UNROLL
2029// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2030// | FASTOPT
2031// | ALLOW_UAV_CONDITION
2032// | BRANCH
2033// | FLATTEN
2034// | FORCECASE
2035// | CALL
2036//
2037void HlslGrammar::acceptAttributes()
2038{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002039 // For now, accept the [ XXX(X) ] syntax, but drop.
2040 // TODO: subset to correct set? Pass on?
2041 do {
2042 // LEFT_BRACKET?
2043 if (! acceptTokenClass(EHTokLeftBracket))
2044 return;
2045
2046 // attribute
2047 if (peekTokenClass(EHTokIdentifier)) {
2048 // 'token.string' is the attribute
2049 advanceToken();
2050 } else if (! peekTokenClass(EHTokRightBracket)) {
2051 expected("identifier");
2052 advanceToken();
2053 }
2054
2055 // (x)
2056 if (acceptTokenClass(EHTokLeftParen)) {
2057 TIntermTyped* node;
2058 if (! acceptLiteral(node))
2059 expected("literal");
2060 // 'node' has the literal in it
2061 if (! acceptTokenClass(EHTokRightParen))
2062 expected(")");
2063 }
2064
2065 // RIGHT_BRACKET
2066 if (acceptTokenClass(EHTokRightBracket))
2067 continue;
2068
2069 expected("]");
2070 return;
2071
2072 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002073}
2074
John Kessenich0d2b6de2016-06-05 11:23:11 -06002075// selection_statement
2076// : IF LEFT_PAREN expression RIGHT_PAREN statement
2077// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2078//
John Kessenich21472ae2016-06-04 11:46:33 -06002079bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2080{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002081 TSourceLoc loc = token.loc;
2082
2083 // IF
2084 if (! acceptTokenClass(EHTokIf))
2085 return false;
2086
2087 // so that something declared in the condition is scoped to the lifetimes
2088 // of the then-else statements
2089 parseContext.pushScope();
2090
2091 // LEFT_PAREN expression RIGHT_PAREN
2092 TIntermTyped* condition;
2093 if (! acceptParenExpression(condition))
2094 return false;
2095
2096 // create the child statements
2097 TIntermNodePair thenElse = { nullptr, nullptr };
2098
2099 // then statement
2100 if (! acceptScopedStatement(thenElse.node1)) {
2101 expected("then statement");
2102 return false;
2103 }
2104
2105 // ELSE
2106 if (acceptTokenClass(EHTokElse)) {
2107 // else statement
2108 if (! acceptScopedStatement(thenElse.node2)) {
2109 expected("else statement");
2110 return false;
2111 }
2112 }
2113
2114 // Put the pieces together
2115 statement = intermediate.addSelection(condition, thenElse, loc);
2116 parseContext.popScope();
2117
2118 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002119}
2120
John Kessenichd02dc5d2016-07-01 00:04:11 -06002121// switch_statement
2122// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2123//
John Kessenich21472ae2016-06-04 11:46:33 -06002124bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2125{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002126 // SWITCH
2127 TSourceLoc loc = token.loc;
2128 if (! acceptTokenClass(EHTokSwitch))
2129 return false;
2130
2131 // LEFT_PAREN expression RIGHT_PAREN
2132 parseContext.pushScope();
2133 TIntermTyped* switchExpression;
2134 if (! acceptParenExpression(switchExpression)) {
2135 parseContext.popScope();
2136 return false;
2137 }
2138
2139 // compound_statement
2140 parseContext.pushSwitchSequence(new TIntermSequence);
2141 bool statementOkay = acceptCompoundStatement(statement);
2142 if (statementOkay)
2143 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2144
2145 parseContext.popSwitchSequence();
2146 parseContext.popScope();
2147
2148 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002149}
2150
John Kessenich119f8f62016-06-05 15:44:07 -06002151// iteration_statement
2152// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2153// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2154// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2155//
2156// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002157bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2158{
John Kessenich119f8f62016-06-05 15:44:07 -06002159 TSourceLoc loc = token.loc;
2160 TIntermTyped* condition = nullptr;
2161
2162 EHlslTokenClass loop = peek();
2163 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2164
2165 // WHILE or DO or FOR
2166 advanceToken();
2167
2168 switch (loop) {
2169 case EHTokWhile:
2170 // so that something declared in the condition is scoped to the lifetime
2171 // of the while sub-statement
2172 parseContext.pushScope();
2173 parseContext.nestLooping();
2174
2175 // LEFT_PAREN condition RIGHT_PAREN
2176 if (! acceptParenExpression(condition))
2177 return false;
2178
2179 // statement
2180 if (! acceptScopedStatement(statement)) {
2181 expected("while sub-statement");
2182 return false;
2183 }
2184
2185 parseContext.unnestLooping();
2186 parseContext.popScope();
2187
2188 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2189
2190 return true;
2191
2192 case EHTokDo:
2193 parseContext.nestLooping();
2194
2195 if (! acceptTokenClass(EHTokLeftBrace))
2196 expected("{");
2197
2198 // statement
2199 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2200 expected("do sub-statement");
2201 return false;
2202 }
2203
2204 if (! acceptTokenClass(EHTokRightBrace))
2205 expected("}");
2206
2207 // WHILE
2208 if (! acceptTokenClass(EHTokWhile)) {
2209 expected("while");
2210 return false;
2211 }
2212
2213 // LEFT_PAREN condition RIGHT_PAREN
2214 TIntermTyped* condition;
2215 if (! acceptParenExpression(condition))
2216 return false;
2217
2218 if (! acceptTokenClass(EHTokSemicolon))
2219 expected(";");
2220
2221 parseContext.unnestLooping();
2222
2223 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2224
2225 return true;
2226
2227 case EHTokFor:
2228 {
2229 // LEFT_PAREN
2230 if (! acceptTokenClass(EHTokLeftParen))
2231 expected("(");
2232
2233 // so that something declared in the condition is scoped to the lifetime
2234 // of the for sub-statement
2235 parseContext.pushScope();
2236
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002237 // initializer
2238 TIntermNode* initNode = nullptr;
2239 if (! acceptControlDeclaration(initNode)) {
2240 TIntermTyped* initExpr = nullptr;
2241 acceptExpression(initExpr);
2242 initNode = initExpr;
2243 }
2244 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002245 if (! acceptTokenClass(EHTokSemicolon))
2246 expected(";");
2247
2248 parseContext.nestLooping();
2249
2250 // condition SEMI_COLON
2251 acceptExpression(condition);
2252 if (! acceptTokenClass(EHTokSemicolon))
2253 expected(";");
2254
2255 // iterator SEMI_COLON
2256 TIntermTyped* iterator = nullptr;
2257 acceptExpression(iterator);
2258 if (! acceptTokenClass(EHTokRightParen))
2259 expected(")");
2260
2261 // statement
2262 if (! acceptScopedStatement(statement)) {
2263 expected("for sub-statement");
2264 return false;
2265 }
2266
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002267 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002268
2269 parseContext.popScope();
2270 parseContext.unnestLooping();
2271
2272 return true;
2273 }
2274
2275 default:
2276 return false;
2277 }
John Kessenich21472ae2016-06-04 11:46:33 -06002278}
2279
2280// jump_statement
2281// : CONTINUE SEMICOLON
2282// | BREAK SEMICOLON
2283// | DISCARD SEMICOLON
2284// | RETURN SEMICOLON
2285// | RETURN expression SEMICOLON
2286//
2287bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2288{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002289 EHlslTokenClass jump = peek();
2290 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002291 case EHTokContinue:
2292 case EHTokBreak:
2293 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002294 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002295 advanceToken();
2296 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002297 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002298 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002299 return false;
2300 }
John Kessenich21472ae2016-06-04 11:46:33 -06002301
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002302 switch (jump) {
2303 case EHTokContinue:
2304 statement = intermediate.addBranch(EOpContinue, token.loc);
2305 break;
2306 case EHTokBreak:
2307 statement = intermediate.addBranch(EOpBreak, token.loc);
2308 break;
2309 case EHTokDiscard:
2310 statement = intermediate.addBranch(EOpKill, token.loc);
2311 break;
2312
2313 case EHTokReturn:
2314 {
2315 // expression
2316 TIntermTyped* node;
2317 if (acceptExpression(node)) {
2318 // hook it up
2319 statement = intermediate.addBranch(EOpReturn, node, token.loc);
2320 } else
2321 statement = intermediate.addBranch(EOpReturn, token.loc);
2322 break;
2323 }
2324
2325 default:
2326 assert(0);
2327 return false;
2328 }
2329
2330 // SEMICOLON
2331 if (! acceptTokenClass(EHTokSemicolon))
2332 expected(";");
2333
2334 return true;
2335}
John Kessenich21472ae2016-06-04 11:46:33 -06002336
John Kessenichd02dc5d2016-07-01 00:04:11 -06002337// case_label
2338// : CASE expression COLON
2339//
John Kessenich21472ae2016-06-04 11:46:33 -06002340bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2341{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002342 TSourceLoc loc = token.loc;
2343 if (! acceptTokenClass(EHTokCase))
2344 return false;
2345
2346 TIntermTyped* expression;
2347 if (! acceptExpression(expression)) {
2348 expected("case expression");
2349 return false;
2350 }
2351
2352 if (! acceptTokenClass(EHTokColon)) {
2353 expected(":");
2354 return false;
2355 }
2356
2357 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2358
2359 return true;
2360}
2361
2362// default_label
2363// : DEFAULT COLON
2364//
2365bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2366{
2367 TSourceLoc loc = token.loc;
2368 if (! acceptTokenClass(EHTokDefault))
2369 return false;
2370
2371 if (! acceptTokenClass(EHTokColon)) {
2372 expected(":");
2373 return false;
2374 }
2375
2376 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2377
2378 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002379}
2380
John Kessenich19b92ff2016-06-19 11:50:34 -06002381// array_specifier
2382// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
2383//
2384void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2385{
2386 arraySizes = nullptr;
2387
2388 if (! acceptTokenClass(EHTokLeftBracket))
2389 return;
2390
2391 TSourceLoc loc = token.loc;
2392 TIntermTyped* sizeExpr;
2393 if (! acceptAssignmentExpression(sizeExpr)) {
2394 expected("array-sizing expression");
2395 return;
2396 }
2397
2398 if (! acceptTokenClass(EHTokRightBracket)) {
2399 expected("]");
2400 return;
2401 }
2402
2403 TArraySize arraySize;
2404 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2405 arraySizes = new TArraySizes;
2406 arraySizes->addInnerSize(arraySize);
2407}
2408
John Kessenich630dd7d2016-06-12 23:52:12 -06002409// post_decls
2410// : COLON semantic // optional
2411// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
2412// COLON REGISTER // optional
2413// annotations // optional
2414//
2415void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06002416{
John Kessenich630dd7d2016-06-12 23:52:12 -06002417 do {
2418 // COLON
2419 if (acceptTokenClass(EHTokColon)) {
2420 HlslToken idToken;
2421 if (acceptTokenClass(EHTokPackOffset)) {
2422 if (! acceptTokenClass(EHTokLeftParen)) {
2423 expected("(");
2424 return;
2425 }
2426 acceptTokenClass(EHTokIdentifier);
2427 acceptTokenClass(EHTokDot);
2428 acceptTokenClass(EHTokIdentifier);
2429 if (! acceptTokenClass(EHTokRightParen)) {
2430 expected(")");
2431 break;
2432 }
2433 // TODO: process the packoffset information
2434 } else if (! acceptIdentifier(idToken)) {
2435 expected("semantic or packoffset or register");
2436 return;
2437 } else if (*idToken.string == "register") {
2438 if (! acceptTokenClass(EHTokLeftParen)) {
2439 expected("(");
2440 return;
2441 }
2442 acceptTokenClass(EHTokIdentifier);
2443 acceptTokenClass(EHTokComma);
2444 acceptTokenClass(EHTokIdentifier);
2445 acceptTokenClass(EHTokLeftBracket);
2446 if (peekTokenClass(EHTokIntConstant))
2447 advanceToken();
2448 acceptTokenClass(EHTokRightBracket);
2449 if (! acceptTokenClass(EHTokRightParen)) {
2450 expected(")");
2451 break;
2452 }
2453 // TODO: process the register information
2454 } else {
2455 // semantic, in idToken.string
2456 parseContext.handleSemantic(type, *idToken.string);
2457 }
2458 } else if (acceptTokenClass(EHTokLeftAngle)) {
2459 // TODO: process annotations, just accepting them for now
2460 do {
2461 if (peekTokenClass(EHTokNone))
2462 return;
2463 if (acceptTokenClass(EHTokRightAngle))
2464 break;
2465 advanceToken();
2466 } while (true);
2467 } else
2468 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002469
John Kessenich630dd7d2016-06-12 23:52:12 -06002470 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002471}
2472
John Kesseniche01a9bc2016-03-12 20:11:22 -07002473} // end namespace glslang