blob: 48e2672ab183566b8470681670056c944864d4bd [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//
John Kesseniche4821e42016-07-16 10:19:43 -0600214bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600215{
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);
John Kessenich3d157c52016-07-25 16:05:33 -0600340 else if (type.getBasicType() == EbtBlock)
341 parseContext.declareBlock(idToken.loc, type, idToken.string);
John Kessenich5e69ec62016-07-05 00:02:40 -0600342 else {
343 // Declare the variable and add any initializer code to the AST.
344 // The top-level node is always made into an aggregate, as that's
345 // historically how the AST has been.
346 node = intermediate.growAggregate(node,
347 parseContext.declareVariable(idToken.loc, *idToken.string, type,
348 arraySizes, expressionNode),
349 idToken.loc);
350 }
John Kessenich5f934b02016-03-13 17:58:25 -0600351 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600352
353 if (acceptTokenClass(EHTokComma)) {
354 list = true;
355 continue;
356 }
357 };
358
359 // The top-level node is a sequence.
360 if (node != nullptr)
361 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700362
John Kessenich078d7f22016-03-14 10:02:11 -0600363 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600364 if (! acceptTokenClass(EHTokSemicolon)) {
365 expected(";");
366 return false;
367 }
368
John Kesseniche01a9bc2016-03-12 20:11:22 -0700369 return true;
370}
371
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600372// control_declaration
373// : fully_specified_type identifier EQUAL expression
374//
375bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
376{
377 node = nullptr;
378
379 // fully_specified_type
380 TType type;
381 if (! acceptFullySpecifiedType(type))
382 return false;
383
384 // identifier
385 HlslToken idToken;
386 if (! acceptIdentifier(idToken)) {
387 expected("identifier");
388 return false;
389 }
390
391 // EQUAL
392 TIntermTyped* expressionNode = nullptr;
393 if (! acceptTokenClass(EHTokAssign)) {
394 expected("=");
395 return false;
396 }
397
398 // expression
399 if (! acceptExpression(expressionNode)) {
400 expected("initializer");
401 return false;
402 }
403
404 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
405
406 return true;
407}
408
John Kessenich87142c72016-03-12 20:24:24 -0700409// fully_specified_type
410// : type_specifier
411// | type_qualifier type_specifier
412//
413bool HlslGrammar::acceptFullySpecifiedType(TType& type)
414{
415 // type_qualifier
416 TQualifier qualifier;
417 qualifier.clear();
418 acceptQualifier(qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600419 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700420
421 // type_specifier
422 if (! acceptType(type))
423 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600424 if (type.getBasicType() == EbtBlock) {
425 // the type was a block, which set some parts of the qualifier
426 parseContext.mergeQualifiers(loc, type.getQualifier(), qualifier, true);
427 // further, it can create an anonymous instance of the block
428 if (peekTokenClass(EHTokSemicolon))
429 parseContext.declareBlock(loc, type);
430 } else
431 type.getQualifier() = qualifier;
John Kessenich87142c72016-03-12 20:24:24 -0700432
433 return true;
434}
435
John Kessenich630dd7d2016-06-12 23:52:12 -0600436// type_qualifier
437// : qualifier qualifier ...
438//
439// Zero or more of these, so this can't return false.
440//
John Kessenich87142c72016-03-12 20:24:24 -0700441void HlslGrammar::acceptQualifier(TQualifier& qualifier)
442{
John Kessenich630dd7d2016-06-12 23:52:12 -0600443 do {
444 switch (peek()) {
445 case EHTokStatic:
446 // normal glslang default
447 break;
448 case EHTokExtern:
449 // TODO: no meaning in glslang?
450 break;
451 case EHTokShared:
452 // TODO: hint
453 break;
454 case EHTokGroupShared:
455 qualifier.storage = EvqShared;
456 break;
457 case EHTokUniform:
458 qualifier.storage = EvqUniform;
459 break;
460 case EHTokConst:
461 qualifier.storage = EvqConst;
462 break;
463 case EHTokVolatile:
464 qualifier.volatil = true;
465 break;
466 case EHTokLinear:
467 qualifier.storage = EvqVaryingIn;
468 qualifier.smooth = true;
469 break;
470 case EHTokCentroid:
471 qualifier.centroid = true;
472 break;
473 case EHTokNointerpolation:
474 qualifier.flat = true;
475 break;
476 case EHTokNoperspective:
477 qualifier.nopersp = true;
478 break;
479 case EHTokSample:
480 qualifier.sample = true;
481 break;
482 case EHTokRowMajor:
483 qualifier.layoutMatrix = ElmRowMajor;
484 break;
485 case EHTokColumnMajor:
486 qualifier.layoutMatrix = ElmColumnMajor;
487 break;
488 case EHTokPrecise:
489 qualifier.noContraction = true;
490 break;
LoopDawg9249c702016-07-12 20:44:32 -0600491 case EHTokIn:
492 qualifier.storage = EvqIn;
493 break;
494 case EHTokOut:
495 qualifier.storage = EvqOut;
496 break;
497 case EHTokInOut:
498 qualifier.storage = EvqInOut;
499 break;
John Kessenich630dd7d2016-06-12 23:52:12 -0600500 default:
501 return;
502 }
503 advanceToken();
504 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700505}
506
LoopDawg6daaa4f2016-06-23 19:13:48 -0600507// template_type
508// : FLOAT
509// | DOUBLE
510// | INT
511// | DWORD
512// | UINT
513// | BOOL
514//
515bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
516{
517 switch (peek()) {
518 case EHTokFloat:
519 basicType = EbtFloat;
520 break;
521 case EHTokDouble:
522 basicType = EbtDouble;
523 break;
524 case EHTokInt:
525 case EHTokDword:
526 basicType = EbtInt;
527 break;
528 case EHTokUint:
529 basicType = EbtUint;
530 break;
531 case EHTokBool:
532 basicType = EbtBool;
533 break;
534 default:
535 return false;
536 }
537
538 advanceToken();
539
540 return true;
541}
542
543// vector_template_type
544// : VECTOR
545// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
546//
547bool HlslGrammar::acceptVectorTemplateType(TType& type)
548{
549 if (! acceptTokenClass(EHTokVector))
550 return false;
551
552 if (! acceptTokenClass(EHTokLeftAngle)) {
553 // in HLSL, 'vector' alone means float4.
554 new(&type) TType(EbtFloat, EvqTemporary, 4);
555 return true;
556 }
557
558 TBasicType basicType;
559 if (! acceptTemplateType(basicType)) {
560 expected("scalar type");
561 return false;
562 }
563
564 // COMMA
565 if (! acceptTokenClass(EHTokComma)) {
566 expected(",");
567 return false;
568 }
569
570 // integer
571 if (! peekTokenClass(EHTokIntConstant)) {
572 expected("literal integer");
573 return false;
574 }
575
576 TIntermTyped* vecSize;
577 if (! acceptLiteral(vecSize))
578 return false;
579
580 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
581
582 new(&type) TType(basicType, EvqTemporary, vecSizeI);
583
584 if (vecSizeI == 1)
585 type.makeVector();
586
587 if (!acceptTokenClass(EHTokRightAngle)) {
588 expected("right angle bracket");
589 return false;
590 }
591
592 return true;
593}
594
595// matrix_template_type
596// : MATRIX
597// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
598//
599bool HlslGrammar::acceptMatrixTemplateType(TType& type)
600{
601 if (! acceptTokenClass(EHTokMatrix))
602 return false;
603
604 if (! acceptTokenClass(EHTokLeftAngle)) {
605 // in HLSL, 'matrix' alone means float4x4.
606 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
607 return true;
608 }
609
610 TBasicType basicType;
611 if (! acceptTemplateType(basicType)) {
612 expected("scalar type");
613 return false;
614 }
615
616 // COMMA
617 if (! acceptTokenClass(EHTokComma)) {
618 expected(",");
619 return false;
620 }
621
622 // integer rows
623 if (! peekTokenClass(EHTokIntConstant)) {
624 expected("literal integer");
625 return false;
626 }
627
628 TIntermTyped* rows;
629 if (! acceptLiteral(rows))
630 return false;
631
632 // COMMA
633 if (! acceptTokenClass(EHTokComma)) {
634 expected(",");
635 return false;
636 }
637
638 // integer cols
639 if (! peekTokenClass(EHTokIntConstant)) {
640 expected("literal integer");
641 return false;
642 }
643
644 TIntermTyped* cols;
645 if (! acceptLiteral(cols))
646 return false;
647
648 new(&type) TType(basicType, EvqTemporary, 0,
649 cols->getAsConstantUnion()->getConstArray()[0].getIConst(),
650 rows->getAsConstantUnion()->getConstArray()[0].getIConst());
651
652 if (!acceptTokenClass(EHTokRightAngle)) {
653 expected("right angle bracket");
654 return false;
655 }
656
657 return true;
658}
659
660
LoopDawg4886f692016-06-29 10:58:58 -0600661// sampler_type
662// : SAMPLER
663// | SAMPLER1D
664// | SAMPLER2D
665// | SAMPLER3D
666// | SAMPLERCUBE
667// | SAMPLERSTATE
668// | SAMPLERCOMPARISONSTATE
669bool HlslGrammar::acceptSamplerType(TType& type)
670{
671 // read sampler type
672 const EHlslTokenClass samplerType = peek();
673
LoopDawga78b0292016-07-19 14:28:05 -0600674 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600675 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600676
LoopDawga78b0292016-07-19 14:28:05 -0600677 bool isShadow = false;
678
LoopDawg4886f692016-06-29 10:58:58 -0600679 switch (samplerType) {
680 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600681 case EHTokSampler1d: /*dim = Esd1D*/; break;
682 case EHTokSampler2d: /*dim = Esd2D*/; break;
683 case EHTokSampler3d: /*dim = Esd3D*/; break;
684 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600685 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600686 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600687 default:
688 return false; // not a sampler declaration
689 }
690
691 advanceToken(); // consume the sampler type keyword
692
693 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600694
695 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600696 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600697
698 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
699
700 return true;
701}
702
703// texture_type
704// | BUFFER
705// | TEXTURE1D
706// | TEXTURE1DARRAY
707// | TEXTURE2D
708// | TEXTURE2DARRAY
709// | TEXTURE3D
710// | TEXTURECUBE
711// | TEXTURECUBEARRAY
712// | TEXTURE2DMS
713// | TEXTURE2DMSARRAY
714bool HlslGrammar::acceptTextureType(TType& type)
715{
716 const EHlslTokenClass textureType = peek();
717
718 TSamplerDim dim = EsdNone;
719 bool array = false;
720 bool ms = false;
721
722 switch (textureType) {
723 case EHTokBuffer: dim = EsdBuffer; break;
724 case EHTokTexture1d: dim = Esd1D; break;
725 case EHTokTexture1darray: dim = Esd1D; array = true; break;
726 case EHTokTexture2d: dim = Esd2D; break;
727 case EHTokTexture2darray: dim = Esd2D; array = true; break;
728 case EHTokTexture3d: dim = Esd3D; break;
729 case EHTokTextureCube: dim = EsdCube; break;
730 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
731 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
732 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
733 default:
734 return false; // not a texture declaration
735 }
736
737 advanceToken(); // consume the texture object keyword
738
739 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
740
741 TIntermTyped* msCount = nullptr;
742
743 // texture type: required for multisample types!
744 if (acceptTokenClass(EHTokLeftAngle)) {
745 if (! acceptType(txType)) {
746 expected("scalar or vector type");
747 return false;
748 }
749
750 const TBasicType basicRetType = txType.getBasicType() ;
751
752 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
753 unimplemented("basic type in texture");
754 return false;
755 }
756
757 if (!txType.isScalar() && !txType.isVector()) {
758 expected("scalar or vector type");
759 return false;
760 }
761
762 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
763 // TODO: handle vec2/3 types
764 expected("vector size not yet supported in texture type");
765 return false;
766 }
767
768 if (ms && acceptTokenClass(EHTokComma)) {
769 // read sample count for multisample types, if given
770 if (! peekTokenClass(EHTokIntConstant)) {
771 expected("multisample count");
772 return false;
773 }
774
775 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
776 return false;
777 }
778
779 if (! acceptTokenClass(EHTokRightAngle)) {
780 expected("right angle bracket");
781 return false;
782 }
783 } else if (ms) {
784 expected("texture type for multisample");
785 return false;
786 }
787
788 TArraySizes* arraySizes = nullptr;
789 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
790
791 TSampler sampler;
792 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
793
794 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
795
796 return true;
797}
798
799
John Kessenich87142c72016-03-12 20:24:24 -0700800// If token is for a type, update 'type' with the type information,
801// and return true and advance.
802// Otherwise, return false, and don't advance
803bool HlslGrammar::acceptType(TType& type)
804{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600805 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600806 case EHTokVector:
807 return acceptVectorTemplateType(type);
808 break;
809
810 case EHTokMatrix:
811 return acceptMatrixTemplateType(type);
812 break;
813
LoopDawg4886f692016-06-29 10:58:58 -0600814 case EHTokSampler: // fall through
815 case EHTokSampler1d: // ...
816 case EHTokSampler2d: // ...
817 case EHTokSampler3d: // ...
818 case EHTokSamplerCube: // ...
819 case EHTokSamplerState: // ...
820 case EHTokSamplerComparisonState: // ...
821 return acceptSamplerType(type);
822 break;
823
824 case EHTokBuffer: // fall through
825 case EHTokTexture1d: // ...
826 case EHTokTexture1darray: // ...
827 case EHTokTexture2d: // ...
828 case EHTokTexture2darray: // ...
829 case EHTokTexture3d: // ...
830 case EHTokTextureCube: // ...
831 case EHTokTextureCubearray: // ...
832 case EHTokTexture2DMS: // ...
833 case EHTokTexture2DMSarray: // ...
834 return acceptTextureType(type);
835 break;
836
John Kesseniche6e74942016-06-11 16:43:14 -0600837 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600838 case EHTokCBuffer:
839 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600840 return acceptStruct(type);
841 break;
842
843 case EHTokIdentifier:
844 // An identifier could be for a user-defined type.
845 // Note we cache the symbol table lookup, to save for a later rule
846 // when this is not a type.
847 token.symbol = parseContext.symbolTable.find(*token.string);
848 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
849 type.shallowCopy(token.symbol->getType());
850 advanceToken();
851 return true;
852 } else
853 return false;
854
John Kessenich71351de2016-06-08 12:50:56 -0600855 case EHTokVoid:
856 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700857 break;
John Kessenich71351de2016-06-08 12:50:56 -0600858
John Kessenich87142c72016-03-12 20:24:24 -0700859 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600860 new(&type) TType(EbtFloat);
861 break;
John Kessenich87142c72016-03-12 20:24:24 -0700862 case EHTokFloat1:
863 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600864 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700865 break;
John Kessenich87142c72016-03-12 20:24:24 -0700866 case EHTokFloat2:
867 new(&type) TType(EbtFloat, EvqTemporary, 2);
868 break;
869 case EHTokFloat3:
870 new(&type) TType(EbtFloat, EvqTemporary, 3);
871 break;
872 case EHTokFloat4:
873 new(&type) TType(EbtFloat, EvqTemporary, 4);
874 break;
875
John Kessenich71351de2016-06-08 12:50:56 -0600876 case EHTokDouble:
877 new(&type) TType(EbtDouble);
878 break;
879 case EHTokDouble1:
880 new(&type) TType(EbtDouble);
881 type.makeVector();
882 break;
883 case EHTokDouble2:
884 new(&type) TType(EbtDouble, EvqTemporary, 2);
885 break;
886 case EHTokDouble3:
887 new(&type) TType(EbtDouble, EvqTemporary, 3);
888 break;
889 case EHTokDouble4:
890 new(&type) TType(EbtDouble, EvqTemporary, 4);
891 break;
892
893 case EHTokInt:
894 case EHTokDword:
895 new(&type) TType(EbtInt);
896 break;
897 case EHTokInt1:
898 new(&type) TType(EbtInt);
899 type.makeVector();
900 break;
John Kessenich87142c72016-03-12 20:24:24 -0700901 case EHTokInt2:
902 new(&type) TType(EbtInt, EvqTemporary, 2);
903 break;
904 case EHTokInt3:
905 new(&type) TType(EbtInt, EvqTemporary, 3);
906 break;
907 case EHTokInt4:
908 new(&type) TType(EbtInt, EvqTemporary, 4);
909 break;
910
John Kessenich71351de2016-06-08 12:50:56 -0600911 case EHTokUint:
912 new(&type) TType(EbtUint);
913 break;
914 case EHTokUint1:
915 new(&type) TType(EbtUint);
916 type.makeVector();
917 break;
918 case EHTokUint2:
919 new(&type) TType(EbtUint, EvqTemporary, 2);
920 break;
921 case EHTokUint3:
922 new(&type) TType(EbtUint, EvqTemporary, 3);
923 break;
924 case EHTokUint4:
925 new(&type) TType(EbtUint, EvqTemporary, 4);
926 break;
927
LoopDawg6daaa4f2016-06-23 19:13:48 -0600928
John Kessenich71351de2016-06-08 12:50:56 -0600929 case EHTokBool:
930 new(&type) TType(EbtBool);
931 break;
932 case EHTokBool1:
933 new(&type) TType(EbtBool);
934 type.makeVector();
935 break;
John Kessenich87142c72016-03-12 20:24:24 -0700936 case EHTokBool2:
937 new(&type) TType(EbtBool, EvqTemporary, 2);
938 break;
939 case EHTokBool3:
940 new(&type) TType(EbtBool, EvqTemporary, 3);
941 break;
942 case EHTokBool4:
943 new(&type) TType(EbtBool, EvqTemporary, 4);
944 break;
945
John Kessenich0133c122016-05-20 12:17:26 -0600946 case EHTokInt1x1:
947 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
948 break;
949 case EHTokInt1x2:
950 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
951 break;
952 case EHTokInt1x3:
953 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
954 break;
955 case EHTokInt1x4:
956 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
957 break;
958 case EHTokInt2x1:
959 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
960 break;
961 case EHTokInt2x2:
962 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
963 break;
964 case EHTokInt2x3:
965 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
966 break;
967 case EHTokInt2x4:
968 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
969 break;
970 case EHTokInt3x1:
971 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
972 break;
973 case EHTokInt3x2:
974 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
975 break;
976 case EHTokInt3x3:
977 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
978 break;
979 case EHTokInt3x4:
980 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
981 break;
982 case EHTokInt4x1:
983 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
984 break;
985 case EHTokInt4x2:
986 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
987 break;
988 case EHTokInt4x3:
989 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
990 break;
991 case EHTokInt4x4:
992 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
993 break;
994
John Kessenich71351de2016-06-08 12:50:56 -0600995 case EHTokUint1x1:
996 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
997 break;
998 case EHTokUint1x2:
999 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
1000 break;
1001 case EHTokUint1x3:
1002 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
1003 break;
1004 case EHTokUint1x4:
1005 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
1006 break;
1007 case EHTokUint2x1:
1008 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
1009 break;
1010 case EHTokUint2x2:
1011 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1012 break;
1013 case EHTokUint2x3:
1014 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
1015 break;
1016 case EHTokUint2x4:
1017 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
1018 break;
1019 case EHTokUint3x1:
1020 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
1021 break;
1022 case EHTokUint3x2:
1023 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
1024 break;
1025 case EHTokUint3x3:
1026 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1027 break;
1028 case EHTokUint3x4:
1029 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
1030 break;
1031 case EHTokUint4x1:
1032 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
1033 break;
1034 case EHTokUint4x2:
1035 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
1036 break;
1037 case EHTokUint4x3:
1038 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
1039 break;
1040 case EHTokUint4x4:
1041 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1042 break;
1043
1044 case EHTokBool1x1:
1045 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1046 break;
1047 case EHTokBool1x2:
1048 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
1049 break;
1050 case EHTokBool1x3:
1051 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
1052 break;
1053 case EHTokBool1x4:
1054 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
1055 break;
1056 case EHTokBool2x1:
1057 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
1058 break;
1059 case EHTokBool2x2:
1060 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1061 break;
1062 case EHTokBool2x3:
1063 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
1064 break;
1065 case EHTokBool2x4:
1066 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
1067 break;
1068 case EHTokBool3x1:
1069 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
1070 break;
1071 case EHTokBool3x2:
1072 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
1073 break;
1074 case EHTokBool3x3:
1075 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1076 break;
1077 case EHTokBool3x4:
1078 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
1079 break;
1080 case EHTokBool4x1:
1081 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
1082 break;
1083 case EHTokBool4x2:
1084 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
1085 break;
1086 case EHTokBool4x3:
1087 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
1088 break;
1089 case EHTokBool4x4:
1090 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1091 break;
1092
John Kessenich0133c122016-05-20 12:17:26 -06001093 case EHTokFloat1x1:
1094 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1095 break;
1096 case EHTokFloat1x2:
1097 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
1098 break;
1099 case EHTokFloat1x3:
1100 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
1101 break;
1102 case EHTokFloat1x4:
1103 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
1104 break;
1105 case EHTokFloat2x1:
1106 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
1107 break;
John Kessenich87142c72016-03-12 20:24:24 -07001108 case EHTokFloat2x2:
1109 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1110 break;
1111 case EHTokFloat2x3:
1112 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
1113 break;
1114 case EHTokFloat2x4:
1115 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
1116 break;
John Kessenich0133c122016-05-20 12:17:26 -06001117 case EHTokFloat3x1:
1118 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
1119 break;
John Kessenich87142c72016-03-12 20:24:24 -07001120 case EHTokFloat3x2:
1121 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
1122 break;
1123 case EHTokFloat3x3:
1124 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1125 break;
1126 case EHTokFloat3x4:
1127 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
1128 break;
John Kessenich0133c122016-05-20 12:17:26 -06001129 case EHTokFloat4x1:
1130 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
1131 break;
John Kessenich87142c72016-03-12 20:24:24 -07001132 case EHTokFloat4x2:
1133 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
1134 break;
1135 case EHTokFloat4x3:
1136 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
1137 break;
1138 case EHTokFloat4x4:
1139 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1140 break;
1141
John Kessenich0133c122016-05-20 12:17:26 -06001142 case EHTokDouble1x1:
1143 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1144 break;
1145 case EHTokDouble1x2:
1146 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
1147 break;
1148 case EHTokDouble1x3:
1149 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
1150 break;
1151 case EHTokDouble1x4:
1152 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
1153 break;
1154 case EHTokDouble2x1:
1155 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
1156 break;
1157 case EHTokDouble2x2:
1158 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1159 break;
1160 case EHTokDouble2x3:
1161 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
1162 break;
1163 case EHTokDouble2x4:
1164 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
1165 break;
1166 case EHTokDouble3x1:
1167 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
1168 break;
1169 case EHTokDouble3x2:
1170 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
1171 break;
1172 case EHTokDouble3x3:
1173 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1174 break;
1175 case EHTokDouble3x4:
1176 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
1177 break;
1178 case EHTokDouble4x1:
1179 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
1180 break;
1181 case EHTokDouble4x2:
1182 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
1183 break;
1184 case EHTokDouble4x3:
1185 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
1186 break;
1187 case EHTokDouble4x4:
1188 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1189 break;
1190
John Kessenich87142c72016-03-12 20:24:24 -07001191 default:
1192 return false;
1193 }
1194
1195 advanceToken();
1196
1197 return true;
1198}
1199
John Kesseniche6e74942016-06-11 16:43:14 -06001200// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001201// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1202// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1203//
1204// struct_type
1205// : STRUCT
1206// | CBUFFER
1207// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001208//
1209bool HlslGrammar::acceptStruct(TType& type)
1210{
John Kessenich3d157c52016-07-25 16:05:33 -06001211 // This qualifier.storage will tell us whether it's an AST block or
1212 // just a struct.
1213 TQualifier qualifier;
1214 qualifier.clear();
1215
1216 // CBUFFER
1217 if (acceptTokenClass(EHTokCBuffer))
1218 qualifier.storage = EvqUniform;
1219 // TBUFFER
1220 else if (acceptTokenClass(EHTokTBuffer))
1221 qualifier.storage = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001222 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001223 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001224 return false;
1225
1226 // IDENTIFIER
1227 TString structName = "";
1228 if (peekTokenClass(EHTokIdentifier)) {
1229 structName = *token.string;
1230 advanceToken();
1231 }
1232
John Kessenich3d157c52016-07-25 16:05:33 -06001233 // post_decls
1234 acceptPostDecls(type);
1235
John Kesseniche6e74942016-06-11 16:43:14 -06001236 // LEFT_BRACE
1237 if (! acceptTokenClass(EHTokLeftBrace)) {
1238 expected("{");
1239 return false;
1240 }
1241
1242 // struct_declaration_list
1243 TTypeList* typeList;
1244 if (! acceptStructDeclarationList(typeList)) {
1245 expected("struct member declarations");
1246 return false;
1247 }
1248
1249 // RIGHT_BRACE
1250 if (! acceptTokenClass(EHTokRightBrace)) {
1251 expected("}");
1252 return false;
1253 }
1254
1255 // create the user-defined type
John Kessenich3d157c52016-07-25 16:05:33 -06001256 if (qualifier.storage == EvqTemporary)
1257 new(&type) TType(typeList, structName);
1258 else
1259 new(&type) TType(typeList, structName, qualifier); // sets EbtBlock
John Kesseniche6e74942016-06-11 16:43:14 -06001260
John Kessenich3d157c52016-07-25 16:05:33 -06001261 // If it was named, which means the type can be reused later, add
1262 // it to the symbol table. (Unless it's a block, in which
1263 // case the name is not a type.)
1264 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001265 TVariable* userTypeDef = new TVariable(&structName, type, true);
1266 if (! parseContext.symbolTable.insert(*userTypeDef))
1267 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1268 }
1269
1270 return true;
1271}
1272
1273// struct_declaration_list
1274// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1275//
1276// struct_declaration
1277// : fully_specified_type struct_declarator COMMA struct_declarator ...
1278//
1279// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001280// : IDENTIFIER post_decls
1281// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001282//
1283bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1284{
1285 typeList = new TTypeList();
1286
1287 do {
1288 // success on seeing the RIGHT_BRACE coming up
1289 if (peekTokenClass(EHTokRightBrace))
1290 return true;
1291
1292 // struct_declaration
1293
1294 // fully_specified_type
1295 TType memberType;
1296 if (! acceptFullySpecifiedType(memberType)) {
1297 expected("member type");
1298 return false;
1299 }
1300
1301 // struct_declarator COMMA struct_declarator ...
1302 do {
1303 // peek IDENTIFIER
1304 if (! peekTokenClass(EHTokIdentifier)) {
1305 expected("member name");
1306 return false;
1307 }
1308
1309 // add it to the list of members
1310 TTypeLoc member = { new TType(EbtVoid), token.loc };
1311 member.type->shallowCopy(memberType);
1312 member.type->setFieldName(*token.string);
1313 typeList->push_back(member);
1314
1315 // accept IDENTIFIER
1316 advanceToken();
1317
1318 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001319 TArraySizes* arraySizes = nullptr;
1320 acceptArraySpecifier(arraySizes);
1321 if (arraySizes)
1322 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001323
John Kessenich630dd7d2016-06-12 23:52:12 -06001324 acceptPostDecls(*member.type);
1325
John Kesseniche6e74942016-06-11 16:43:14 -06001326 // success on seeing the SEMICOLON coming up
1327 if (peekTokenClass(EHTokSemicolon))
1328 break;
1329
1330 // COMMA
1331 if (! acceptTokenClass(EHTokComma)) {
1332 expected(",");
1333 return false;
1334 }
1335
1336 } while (true);
1337
1338 // SEMI_COLON
1339 if (! acceptTokenClass(EHTokSemicolon)) {
1340 expected(";");
1341 return false;
1342 }
1343
1344 } while (true);
1345}
1346
John Kessenich5f934b02016-03-13 17:58:25 -06001347// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001348// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001349// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001350//
1351bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1352{
John Kessenich078d7f22016-03-14 10:02:11 -06001353 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001354 if (! acceptTokenClass(EHTokLeftParen))
1355 return false;
1356
John Kessenich71351de2016-06-08 12:50:56 -06001357 // VOID RIGHT_PAREN
1358 if (! acceptTokenClass(EHTokVoid)) {
1359 do {
1360 // parameter_declaration
1361 if (! acceptParameterDeclaration(function))
1362 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001363
John Kessenich71351de2016-06-08 12:50:56 -06001364 // COMMA
1365 if (! acceptTokenClass(EHTokComma))
1366 break;
1367 } while (true);
1368 }
John Kessenich5f934b02016-03-13 17:58:25 -06001369
John Kessenich078d7f22016-03-14 10:02:11 -06001370 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001371 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001372 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001373 return false;
1374 }
1375
1376 return true;
1377}
1378
1379// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001380// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001381// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001382//
1383bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1384{
1385 // fully_specified_type
1386 TType* type = new TType;
1387 if (! acceptFullySpecifiedType(*type))
1388 return false;
1389
1390 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001391 HlslToken idToken;
1392 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001393
John Kessenich19b92ff2016-06-19 11:50:34 -06001394 // array_specifier
1395 TArraySizes* arraySizes = nullptr;
1396 acceptArraySpecifier(arraySizes);
1397 if (arraySizes)
1398 type->newArraySizes(*arraySizes);
1399
1400 // post_decls
John Kessenichc3387d32016-06-17 14:21:02 -06001401 acceptPostDecls(*type);
1402
John Kessenich5aa59e22016-06-17 15:50:47 -06001403 parseContext.paramFix(*type);
1404
John Kessenichaecd4972016-03-14 10:46:34 -06001405 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001406 function.addParameter(param);
1407
1408 return true;
1409}
1410
1411// Do the work to create the function definition in addition to
1412// parsing the body (compound_statement).
1413bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1414{
1415 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
1416
John Kessenich077e0522016-06-09 02:02:17 -06001417 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -06001418 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
1419
1420 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001421 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001422 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -06001423 node = intermediate.growAggregate(node, functionBody);
1424 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -06001425 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -06001426 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -06001427
1428 return true;
1429 }
1430
1431 return false;
1432}
1433
John Kessenich0d2b6de2016-06-05 11:23:11 -06001434// Accept an expression with parenthesis around it, where
1435// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001436// syntactically required ones like in "if ( expression )".
1437//
1438// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001439//
1440// Note this one is not set up to be speculative; as it gives
1441// errors if not found.
1442//
1443bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1444{
1445 // LEFT_PAREN
1446 if (! acceptTokenClass(EHTokLeftParen))
1447 expected("(");
1448
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001449 bool decl = false;
1450 TIntermNode* declNode = nullptr;
1451 decl = acceptControlDeclaration(declNode);
1452 if (decl) {
1453 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1454 expected("initialized declaration");
1455 return false;
1456 } else
1457 expression = declNode->getAsTyped();
1458 } else {
1459 // no declaration
1460 if (! acceptExpression(expression)) {
1461 expected("expression");
1462 return false;
1463 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001464 }
1465
1466 // RIGHT_PAREN
1467 if (! acceptTokenClass(EHTokRightParen))
1468 expected(")");
1469
1470 return true;
1471}
1472
John Kessenich34fb0362016-05-03 23:17:20 -06001473// The top-level full expression recognizer.
1474//
John Kessenich87142c72016-03-12 20:24:24 -07001475// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001476// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001477//
1478bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1479{
LoopDawgef764a22016-06-03 09:17:51 -06001480 node = nullptr;
1481
John Kessenich34fb0362016-05-03 23:17:20 -06001482 // assignment_expression
1483 if (! acceptAssignmentExpression(node))
1484 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001485
John Kessenich34fb0362016-05-03 23:17:20 -06001486 if (! peekTokenClass(EHTokComma))
1487 return true;
1488
1489 do {
1490 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001491 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001492 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001493
John Kessenich34fb0362016-05-03 23:17:20 -06001494 // ... assignment_expression
1495 TIntermTyped* rightNode = nullptr;
1496 if (! acceptAssignmentExpression(rightNode)) {
1497 expected("assignment expression");
1498 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001499 }
1500
John Kessenich34fb0362016-05-03 23:17:20 -06001501 node = intermediate.addComma(node, rightNode, loc);
1502
1503 if (! peekTokenClass(EHTokComma))
1504 return true;
1505 } while (true);
1506}
1507
John Kessenich07354242016-07-01 19:58:06 -06001508// initializer
1509// : LEFT_BRACE initializer_list RIGHT_BRACE
1510//
1511// initializer_list
1512// : assignment_expression COMMA assignment_expression COMMA ...
1513//
1514bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1515{
1516 // LEFT_BRACE
1517 if (! acceptTokenClass(EHTokLeftBrace))
1518 return false;
1519
1520 // initializer_list
1521 TSourceLoc loc = token.loc;
1522 node = nullptr;
1523 do {
1524 // assignment_expression
1525 TIntermTyped* expr;
1526 if (! acceptAssignmentExpression(expr)) {
1527 expected("assignment expression in initializer list");
1528 return false;
1529 }
1530 node = intermediate.growAggregate(node, expr, loc);
1531
1532 // COMMA
1533 if (acceptTokenClass(EHTokComma))
1534 continue;
1535
1536 // RIGHT_BRACE
1537 if (acceptTokenClass(EHTokRightBrace))
1538 return true;
1539
1540 expected(", or }");
1541 return false;
1542 } while (true);
1543}
1544
John Kessenich34fb0362016-05-03 23:17:20 -06001545// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001546// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001547//
1548// a op (b op (c op d))
1549//
1550// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001551// : initializer
1552// | conditional_expression
1553// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001554//
1555bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1556{
John Kessenich07354242016-07-01 19:58:06 -06001557 // initializer
1558 if (peekTokenClass(EHTokLeftBrace)) {
1559 if (acceptInitializer(node))
1560 return true;
1561
1562 expected("initializer");
1563 return false;
1564 }
1565
John Kessenich00957f82016-07-27 10:39:57 -06001566 // conditional_expression
1567 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001568 return false;
1569
John Kessenich07354242016-07-01 19:58:06 -06001570 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001571 TOperator assignOp = HlslOpMap::assignment(peek());
1572 if (assignOp == EOpNull)
1573 return true;
1574
John Kessenich00957f82016-07-27 10:39:57 -06001575 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001576 TSourceLoc loc = token.loc;
1577 advanceToken();
1578
John Kessenich00957f82016-07-27 10:39:57 -06001579 // conditional_expression assign_op conditional_expression ...
1580 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001581 // gets the right-to-left associativity.
1582 TIntermTyped* rightNode = nullptr;
1583 if (! acceptAssignmentExpression(rightNode)) {
1584 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001585 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001586 }
1587
John Kessenich34fb0362016-05-03 23:17:20 -06001588 node = intermediate.addAssign(assignOp, node, rightNode, loc);
John Kessenichb783d712016-07-27 10:24:31 -06001589 // TODO: Turn this on after tests are fixed for it:
1590 //if (node == nullptr)
1591 // parseContext.error(loc, "could not create assignment", "", "");
John Kessenich34fb0362016-05-03 23:17:20 -06001592
1593 if (! peekTokenClass(EHTokComma))
1594 return true;
1595
1596 return true;
1597}
1598
John Kessenich00957f82016-07-27 10:39:57 -06001599// Accept a conditional expression, which associates right-to-left,
1600// accomplished by the "true" expression calling down to lower
1601// precedence levels than this level.
1602//
1603// conditional_expression
1604// : binary_expression
1605// | binary_expression QUESTION expression COLON assignment_expression
1606//
1607bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1608{
1609 // binary_expression
1610 if (! acceptBinaryExpression(node, PlLogicalOr))
1611 return false;
1612
1613 if (! acceptTokenClass(EHTokQuestion))
1614 return true;
1615
1616 TIntermTyped* trueNode = nullptr;
1617 if (! acceptExpression(trueNode)) {
1618 expected("expression after ?");
1619 return false;
1620 }
1621 TSourceLoc loc = token.loc;
1622
1623 if (! acceptTokenClass(EHTokColon)) {
1624 expected(":");
1625 return false;
1626 }
1627
1628 TIntermTyped* falseNode = nullptr;
1629 if (! acceptAssignmentExpression(falseNode)) {
1630 expected("expression after :");
1631 return false;
1632 }
1633
1634 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1635
1636 return true;
1637}
1638
John Kessenich34fb0362016-05-03 23:17:20 -06001639// Accept a binary expression, for binary operations that
1640// associate left-to-right. This is, it is implicit, for example
1641//
1642// ((a op b) op c) op d
1643//
1644// binary_expression
1645// : expression op expression op expression ...
1646//
1647// where 'expression' is the next higher level in precedence.
1648//
1649bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1650{
1651 if (precedenceLevel > PlMul)
1652 return acceptUnaryExpression(node);
1653
1654 // assignment_expression
1655 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1656 return false;
1657
1658 TOperator op = HlslOpMap::binary(peek());
1659 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1660 if (tokenLevel < precedenceLevel)
1661 return true;
1662
1663 do {
1664 // ... op
1665 TSourceLoc loc = token.loc;
1666 advanceToken();
1667
1668 // ... expression
1669 TIntermTyped* rightNode = nullptr;
1670 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1671 expected("expression");
1672 return false;
1673 }
1674
1675 node = intermediate.addBinaryMath(op, node, rightNode, loc);
1676
1677 if (! peekTokenClass(EHTokComma))
1678 return true;
1679 } while (true);
1680}
1681
1682// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001683// : (type) unary_expression
1684// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001685// | - unary_expression
1686// | ! unary_expression
1687// | ~ unary_expression
1688// | ++ unary_expression
1689// | -- unary_expression
1690// | postfix_expression
1691//
1692bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1693{
John Kessenich1cc1a282016-06-03 16:55:49 -06001694 // (type) unary_expression
1695 // Have to look two steps ahead, because this could be, e.g., a
1696 // postfix_expression instead, since that also starts with at "(".
1697 if (acceptTokenClass(EHTokLeftParen)) {
1698 TType castType;
1699 if (acceptType(castType)) {
1700 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001701 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -06001702 return false;
1703 }
1704
1705 // We've matched "(type)" now, get the expression to cast
1706 TSourceLoc loc = token.loc;
1707 if (! acceptUnaryExpression(node))
1708 return false;
1709
1710 // Hook it up like a constructor
1711 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1712 if (constructorFunction == nullptr) {
1713 expected("type that can be constructed");
1714 return false;
1715 }
1716 TIntermTyped* arguments = nullptr;
1717 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1718 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1719
1720 return true;
1721 } else {
1722 // This isn't a type cast, but it still started "(", so if it is a
1723 // unary expression, it can only be a postfix_expression, so try that.
1724 // Back it up first.
1725 recedeToken();
1726 return acceptPostfixExpression(node);
1727 }
1728 }
1729
1730 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001731 TOperator unaryOp = HlslOpMap::preUnary(peek());
1732
John Kessenich1cc1a282016-06-03 16:55:49 -06001733 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001734 if (unaryOp == EOpNull)
1735 return acceptPostfixExpression(node);
1736
1737 // op unary_expression
1738 TSourceLoc loc = token.loc;
1739 advanceToken();
1740 if (! acceptUnaryExpression(node))
1741 return false;
1742
1743 // + is a no-op
1744 if (unaryOp == EOpAdd)
1745 return true;
1746
1747 node = intermediate.addUnaryMath(unaryOp, node, loc);
1748
1749 return node != nullptr;
1750}
1751
1752// postfix_expression
1753// : LEFT_PAREN expression RIGHT_PAREN
1754// | literal
1755// | constructor
1756// | identifier
1757// | function_call
1758// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1759// | postfix_expression DOT IDENTIFIER
1760// | postfix_expression INC_OP
1761// | postfix_expression DEC_OP
1762//
1763bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1764{
1765 // Not implemented as self-recursive:
1766 // The logical "right recursion" is done with an loop at the end
1767
1768 // idToken will pick up either a variable or a function name in a function call
1769 HlslToken idToken;
1770
John Kessenich21472ae2016-06-04 11:46:33 -06001771 // Find something before the postfix operations, as they can't operate
1772 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001773 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001774 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001775 if (! acceptExpression(node)) {
1776 expected("expression");
1777 return false;
1778 }
1779 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001780 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001781 return false;
1782 }
John Kessenich34fb0362016-05-03 23:17:20 -06001783 } else if (acceptLiteral(node)) {
1784 // literal (nothing else to do yet), go on to the
1785 } else if (acceptConstructor(node)) {
1786 // constructor (nothing else to do yet)
1787 } else if (acceptIdentifier(idToken)) {
1788 // identifier or function_call name
1789 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001790 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001791 } else if (acceptFunctionCall(idToken, node)) {
1792 // function_call (nothing else to do yet)
1793 } else {
1794 expected("function call arguments");
1795 return false;
1796 }
John Kessenich21472ae2016-06-04 11:46:33 -06001797 } else {
1798 // nothing found, can't post operate
1799 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001800 }
1801
John Kessenich21472ae2016-06-04 11:46:33 -06001802 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001803 do {
1804 TSourceLoc loc = token.loc;
1805 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001806
John Kessenich34fb0362016-05-03 23:17:20 -06001807 // Consume only a valid post-unary operator, otherwise we are done.
1808 switch (postOp) {
1809 case EOpIndexDirectStruct:
1810 case EOpIndexIndirect:
1811 case EOpPostIncrement:
1812 case EOpPostDecrement:
1813 advanceToken();
1814 break;
1815 default:
1816 return true;
1817 }
John Kessenich87142c72016-03-12 20:24:24 -07001818
John Kessenich34fb0362016-05-03 23:17:20 -06001819 // We have a valid post-unary operator, process it.
1820 switch (postOp) {
1821 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001822 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001823 // DOT IDENTIFIER
1824 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001825 HlslToken field;
1826 if (! acceptIdentifier(field)) {
1827 expected("swizzle or member");
1828 return false;
1829 }
LoopDawg4886f692016-06-29 10:58:58 -06001830
1831 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001832 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001833
1834 // In the event of a method node, we look for an open paren and accept the function call.
1835 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1836 if (! acceptFunctionCall(field, node, base)) {
1837 expected("function parameters");
1838 return false;
1839 }
1840 }
1841
John Kessenich34fb0362016-05-03 23:17:20 -06001842 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001843 }
John Kessenich34fb0362016-05-03 23:17:20 -06001844 case EOpIndexIndirect:
1845 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001846 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001847 TIntermTyped* indexNode = nullptr;
1848 if (! acceptExpression(indexNode) ||
1849 ! peekTokenClass(EHTokRightBracket)) {
1850 expected("expression followed by ']'");
1851 return false;
1852 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001853 advanceToken();
1854 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1855 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001856 }
1857 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001858 // INC_OP
1859 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001860 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001861 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001862 node = intermediate.addUnaryMath(postOp, node, loc);
1863 break;
1864 default:
1865 assert(0);
1866 break;
1867 }
1868 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001869}
1870
John Kessenichd016be12016-03-13 11:24:20 -06001871// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001872// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001873//
1874bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1875{
1876 // type
1877 TType type;
1878 if (acceptType(type)) {
1879 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1880 if (constructorFunction == nullptr)
1881 return false;
1882
1883 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001884 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001885 if (! acceptArguments(constructorFunction, arguments)) {
1886 expected("constructor arguments");
1887 return false;
1888 }
1889
1890 // hook it up
1891 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1892
1893 return true;
1894 }
1895
1896 return false;
1897}
1898
John Kessenich34fb0362016-05-03 23:17:20 -06001899// The function_call identifier was already recognized, and passed in as idToken.
1900//
1901// function_call
1902// : [idToken] arguments
1903//
LoopDawg4886f692016-06-29 10:58:58 -06001904bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06001905{
John Kessenich4678ca92016-05-13 09:33:42 -06001906 // arguments
1907 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1908 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06001909
1910 // methods have an implicit first argument of the calling object.
1911 if (base != nullptr)
1912 parseContext.handleFunctionArgument(function, arguments, base);
1913
John Kessenich4678ca92016-05-13 09:33:42 -06001914 if (! acceptArguments(function, arguments))
1915 return false;
1916
1917 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1918
1919 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001920}
1921
John Kessenich87142c72016-03-12 20:24:24 -07001922// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001923// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001924//
John Kessenichd016be12016-03-13 11:24:20 -06001925// The arguments are pushed onto the 'function' argument list and
1926// onto the 'arguments' aggregate.
1927//
John Kessenich4678ca92016-05-13 09:33:42 -06001928bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001929{
John Kessenich078d7f22016-03-14 10:02:11 -06001930 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001931 if (! acceptTokenClass(EHTokLeftParen))
1932 return false;
1933
1934 do {
John Kessenichd016be12016-03-13 11:24:20 -06001935 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001936 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001937 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001938 break;
John Kessenichd016be12016-03-13 11:24:20 -06001939
1940 // hook it up
1941 parseContext.handleFunctionArgument(function, arguments, arg);
1942
John Kessenich078d7f22016-03-14 10:02:11 -06001943 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001944 if (! acceptTokenClass(EHTokComma))
1945 break;
1946 } while (true);
1947
John Kessenich078d7f22016-03-14 10:02:11 -06001948 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001949 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001950 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001951 return false;
1952 }
1953
1954 return true;
1955}
1956
1957bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1958{
1959 switch (token.tokenClass) {
1960 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001961 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001962 break;
steve-lunarg2de32912016-07-28 14:49:48 -06001963 case EHTokUintConstant:
1964 node = intermediate.addConstantUnion(token.u, token.loc, true);
1965 break;
John Kessenich87142c72016-03-12 20:24:24 -07001966 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001967 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001968 break;
1969 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001970 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001971 break;
1972 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001973 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001974 break;
1975
1976 default:
1977 return false;
1978 }
1979
1980 advanceToken();
1981
1982 return true;
1983}
1984
John Kessenich5f934b02016-03-13 17:58:25 -06001985// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001986// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001987//
John Kessenich21472ae2016-06-04 11:46:33 -06001988bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001989{
John Kessenich21472ae2016-06-04 11:46:33 -06001990 TIntermAggregate* compoundStatement = nullptr;
1991
John Kessenich34fb0362016-05-03 23:17:20 -06001992 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001993 if (! acceptTokenClass(EHTokLeftBrace))
1994 return false;
1995
1996 // statement statement ...
1997 TIntermNode* statement = nullptr;
1998 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06001999 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2000 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2001 branch->getFlowOp() == EOpDefault)) {
2002 // hook up individual subsequences within a switch statement
2003 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2004 compoundStatement = nullptr;
2005 } else {
2006 // hook it up to the growing compound statement
2007 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2008 }
John Kessenich5f934b02016-03-13 17:58:25 -06002009 }
John Kessenich34fb0362016-05-03 23:17:20 -06002010 if (compoundStatement)
2011 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002012
John Kessenich21472ae2016-06-04 11:46:33 -06002013 retStatement = compoundStatement;
2014
John Kessenich34fb0362016-05-03 23:17:20 -06002015 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002016 return acceptTokenClass(EHTokRightBrace);
2017}
2018
John Kessenich0d2b6de2016-06-05 11:23:11 -06002019bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2020{
2021 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002022 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002023 parseContext.popScope();
2024
2025 return result;
2026}
2027
John Kessenich077e0522016-06-09 02:02:17 -06002028bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002029{
John Kessenich077e0522016-06-09 02:02:17 -06002030 parseContext.pushScope();
2031 bool result = acceptCompoundStatement(statement);
2032 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002033
2034 return result;
2035}
2036
John Kessenich5f934b02016-03-13 17:58:25 -06002037// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002038// : attributes attributed_statement
2039//
2040// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002041// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002042// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002043// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002044// | declaration_statement
2045// | selection_statement
2046// | switch_statement
2047// | case_label
2048// | iteration_statement
2049// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002050//
2051bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2052{
John Kessenich21472ae2016-06-04 11:46:33 -06002053 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002054
John Kessenich21472ae2016-06-04 11:46:33 -06002055 // attributes
2056 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002057
John Kessenich21472ae2016-06-04 11:46:33 -06002058 // attributed_statement
2059 switch (peek()) {
2060 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002061 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002062
John Kessenich21472ae2016-06-04 11:46:33 -06002063 case EHTokIf:
2064 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002065
John Kessenich21472ae2016-06-04 11:46:33 -06002066 case EHTokSwitch:
2067 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002068
John Kessenich21472ae2016-06-04 11:46:33 -06002069 case EHTokFor:
2070 case EHTokDo:
2071 case EHTokWhile:
2072 return acceptIterationStatement(statement);
2073
2074 case EHTokContinue:
2075 case EHTokBreak:
2076 case EHTokDiscard:
2077 case EHTokReturn:
2078 return acceptJumpStatement(statement);
2079
2080 case EHTokCase:
2081 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002082 case EHTokDefault:
2083 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002084
2085 case EHTokSemicolon:
2086 return acceptTokenClass(EHTokSemicolon);
2087
2088 case EHTokRightBrace:
2089 // Performance: not strictly necessary, but stops a bunch of hunting early,
2090 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002091 return false;
2092
John Kessenich21472ae2016-06-04 11:46:33 -06002093 default:
2094 {
2095 // declaration
2096 if (acceptDeclaration(statement))
2097 return true;
2098
2099 // expression
2100 TIntermTyped* node;
2101 if (acceptExpression(node))
2102 statement = node;
2103 else
2104 return false;
2105
2106 // SEMICOLON (following an expression)
2107 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002108 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002109 return false;
2110 }
2111 }
2112 }
2113
John Kessenich5f934b02016-03-13 17:58:25 -06002114 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002115}
2116
John Kessenich21472ae2016-06-04 11:46:33 -06002117// attributes
2118// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2119//
2120// attribute:
2121// : UNROLL
2122// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2123// | FASTOPT
2124// | ALLOW_UAV_CONDITION
2125// | BRANCH
2126// | FLATTEN
2127// | FORCECASE
2128// | CALL
2129//
2130void HlslGrammar::acceptAttributes()
2131{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002132 // For now, accept the [ XXX(X) ] syntax, but drop.
2133 // TODO: subset to correct set? Pass on?
2134 do {
2135 // LEFT_BRACKET?
2136 if (! acceptTokenClass(EHTokLeftBracket))
2137 return;
2138
2139 // attribute
2140 if (peekTokenClass(EHTokIdentifier)) {
2141 // 'token.string' is the attribute
2142 advanceToken();
2143 } else if (! peekTokenClass(EHTokRightBracket)) {
2144 expected("identifier");
2145 advanceToken();
2146 }
2147
2148 // (x)
2149 if (acceptTokenClass(EHTokLeftParen)) {
2150 TIntermTyped* node;
2151 if (! acceptLiteral(node))
2152 expected("literal");
2153 // 'node' has the literal in it
2154 if (! acceptTokenClass(EHTokRightParen))
2155 expected(")");
2156 }
2157
2158 // RIGHT_BRACKET
2159 if (acceptTokenClass(EHTokRightBracket))
2160 continue;
2161
2162 expected("]");
2163 return;
2164
2165 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002166}
2167
John Kessenich0d2b6de2016-06-05 11:23:11 -06002168// selection_statement
2169// : IF LEFT_PAREN expression RIGHT_PAREN statement
2170// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2171//
John Kessenich21472ae2016-06-04 11:46:33 -06002172bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2173{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002174 TSourceLoc loc = token.loc;
2175
2176 // IF
2177 if (! acceptTokenClass(EHTokIf))
2178 return false;
2179
2180 // so that something declared in the condition is scoped to the lifetimes
2181 // of the then-else statements
2182 parseContext.pushScope();
2183
2184 // LEFT_PAREN expression RIGHT_PAREN
2185 TIntermTyped* condition;
2186 if (! acceptParenExpression(condition))
2187 return false;
2188
2189 // create the child statements
2190 TIntermNodePair thenElse = { nullptr, nullptr };
2191
2192 // then statement
2193 if (! acceptScopedStatement(thenElse.node1)) {
2194 expected("then statement");
2195 return false;
2196 }
2197
2198 // ELSE
2199 if (acceptTokenClass(EHTokElse)) {
2200 // else statement
2201 if (! acceptScopedStatement(thenElse.node2)) {
2202 expected("else statement");
2203 return false;
2204 }
2205 }
2206
2207 // Put the pieces together
2208 statement = intermediate.addSelection(condition, thenElse, loc);
2209 parseContext.popScope();
2210
2211 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002212}
2213
John Kessenichd02dc5d2016-07-01 00:04:11 -06002214// switch_statement
2215// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2216//
John Kessenich21472ae2016-06-04 11:46:33 -06002217bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2218{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002219 // SWITCH
2220 TSourceLoc loc = token.loc;
2221 if (! acceptTokenClass(EHTokSwitch))
2222 return false;
2223
2224 // LEFT_PAREN expression RIGHT_PAREN
2225 parseContext.pushScope();
2226 TIntermTyped* switchExpression;
2227 if (! acceptParenExpression(switchExpression)) {
2228 parseContext.popScope();
2229 return false;
2230 }
2231
2232 // compound_statement
2233 parseContext.pushSwitchSequence(new TIntermSequence);
2234 bool statementOkay = acceptCompoundStatement(statement);
2235 if (statementOkay)
2236 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2237
2238 parseContext.popSwitchSequence();
2239 parseContext.popScope();
2240
2241 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002242}
2243
John Kessenich119f8f62016-06-05 15:44:07 -06002244// iteration_statement
2245// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2246// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2247// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2248//
2249// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002250bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2251{
John Kessenich119f8f62016-06-05 15:44:07 -06002252 TSourceLoc loc = token.loc;
2253 TIntermTyped* condition = nullptr;
2254
2255 EHlslTokenClass loop = peek();
2256 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2257
2258 // WHILE or DO or FOR
2259 advanceToken();
2260
2261 switch (loop) {
2262 case EHTokWhile:
2263 // so that something declared in the condition is scoped to the lifetime
2264 // of the while sub-statement
2265 parseContext.pushScope();
2266 parseContext.nestLooping();
2267
2268 // LEFT_PAREN condition RIGHT_PAREN
2269 if (! acceptParenExpression(condition))
2270 return false;
2271
2272 // statement
2273 if (! acceptScopedStatement(statement)) {
2274 expected("while sub-statement");
2275 return false;
2276 }
2277
2278 parseContext.unnestLooping();
2279 parseContext.popScope();
2280
2281 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2282
2283 return true;
2284
2285 case EHTokDo:
2286 parseContext.nestLooping();
2287
2288 if (! acceptTokenClass(EHTokLeftBrace))
2289 expected("{");
2290
2291 // statement
2292 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2293 expected("do sub-statement");
2294 return false;
2295 }
2296
2297 if (! acceptTokenClass(EHTokRightBrace))
2298 expected("}");
2299
2300 // WHILE
2301 if (! acceptTokenClass(EHTokWhile)) {
2302 expected("while");
2303 return false;
2304 }
2305
2306 // LEFT_PAREN condition RIGHT_PAREN
2307 TIntermTyped* condition;
2308 if (! acceptParenExpression(condition))
2309 return false;
2310
2311 if (! acceptTokenClass(EHTokSemicolon))
2312 expected(";");
2313
2314 parseContext.unnestLooping();
2315
2316 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2317
2318 return true;
2319
2320 case EHTokFor:
2321 {
2322 // LEFT_PAREN
2323 if (! acceptTokenClass(EHTokLeftParen))
2324 expected("(");
2325
2326 // so that something declared in the condition is scoped to the lifetime
2327 // of the for sub-statement
2328 parseContext.pushScope();
2329
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002330 // initializer
2331 TIntermNode* initNode = nullptr;
2332 if (! acceptControlDeclaration(initNode)) {
2333 TIntermTyped* initExpr = nullptr;
2334 acceptExpression(initExpr);
2335 initNode = initExpr;
2336 }
2337 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002338 if (! acceptTokenClass(EHTokSemicolon))
2339 expected(";");
2340
2341 parseContext.nestLooping();
2342
2343 // condition SEMI_COLON
2344 acceptExpression(condition);
2345 if (! acceptTokenClass(EHTokSemicolon))
2346 expected(";");
2347
2348 // iterator SEMI_COLON
2349 TIntermTyped* iterator = nullptr;
2350 acceptExpression(iterator);
2351 if (! acceptTokenClass(EHTokRightParen))
2352 expected(")");
2353
2354 // statement
2355 if (! acceptScopedStatement(statement)) {
2356 expected("for sub-statement");
2357 return false;
2358 }
2359
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002360 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002361
2362 parseContext.popScope();
2363 parseContext.unnestLooping();
2364
2365 return true;
2366 }
2367
2368 default:
2369 return false;
2370 }
John Kessenich21472ae2016-06-04 11:46:33 -06002371}
2372
2373// jump_statement
2374// : CONTINUE SEMICOLON
2375// | BREAK SEMICOLON
2376// | DISCARD SEMICOLON
2377// | RETURN SEMICOLON
2378// | RETURN expression SEMICOLON
2379//
2380bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2381{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002382 EHlslTokenClass jump = peek();
2383 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002384 case EHTokContinue:
2385 case EHTokBreak:
2386 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002387 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002388 advanceToken();
2389 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002390 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002391 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002392 return false;
2393 }
John Kessenich21472ae2016-06-04 11:46:33 -06002394
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002395 switch (jump) {
2396 case EHTokContinue:
2397 statement = intermediate.addBranch(EOpContinue, token.loc);
2398 break;
2399 case EHTokBreak:
2400 statement = intermediate.addBranch(EOpBreak, token.loc);
2401 break;
2402 case EHTokDiscard:
2403 statement = intermediate.addBranch(EOpKill, token.loc);
2404 break;
2405
2406 case EHTokReturn:
2407 {
2408 // expression
2409 TIntermTyped* node;
2410 if (acceptExpression(node)) {
2411 // hook it up
2412 statement = intermediate.addBranch(EOpReturn, node, token.loc);
2413 } else
2414 statement = intermediate.addBranch(EOpReturn, token.loc);
2415 break;
2416 }
2417
2418 default:
2419 assert(0);
2420 return false;
2421 }
2422
2423 // SEMICOLON
2424 if (! acceptTokenClass(EHTokSemicolon))
2425 expected(";");
2426
2427 return true;
2428}
John Kessenich21472ae2016-06-04 11:46:33 -06002429
John Kessenichd02dc5d2016-07-01 00:04:11 -06002430// case_label
2431// : CASE expression COLON
2432//
John Kessenich21472ae2016-06-04 11:46:33 -06002433bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2434{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002435 TSourceLoc loc = token.loc;
2436 if (! acceptTokenClass(EHTokCase))
2437 return false;
2438
2439 TIntermTyped* expression;
2440 if (! acceptExpression(expression)) {
2441 expected("case expression");
2442 return false;
2443 }
2444
2445 if (! acceptTokenClass(EHTokColon)) {
2446 expected(":");
2447 return false;
2448 }
2449
2450 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2451
2452 return true;
2453}
2454
2455// default_label
2456// : DEFAULT COLON
2457//
2458bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2459{
2460 TSourceLoc loc = token.loc;
2461 if (! acceptTokenClass(EHTokDefault))
2462 return false;
2463
2464 if (! acceptTokenClass(EHTokColon)) {
2465 expected(":");
2466 return false;
2467 }
2468
2469 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2470
2471 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002472}
2473
John Kessenich19b92ff2016-06-19 11:50:34 -06002474// array_specifier
2475// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
2476//
2477void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2478{
2479 arraySizes = nullptr;
2480
2481 if (! acceptTokenClass(EHTokLeftBracket))
2482 return;
2483
2484 TSourceLoc loc = token.loc;
2485 TIntermTyped* sizeExpr;
2486 if (! acceptAssignmentExpression(sizeExpr)) {
2487 expected("array-sizing expression");
2488 return;
2489 }
2490
2491 if (! acceptTokenClass(EHTokRightBracket)) {
2492 expected("]");
2493 return;
2494 }
2495
2496 TArraySize arraySize;
2497 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2498 arraySizes = new TArraySizes;
2499 arraySizes->addInnerSize(arraySize);
2500}
2501
John Kessenich630dd7d2016-06-12 23:52:12 -06002502// post_decls
2503// : COLON semantic // optional
2504// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
2505// COLON REGISTER // optional
2506// annotations // optional
2507//
2508void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06002509{
John Kessenich630dd7d2016-06-12 23:52:12 -06002510 do {
2511 // COLON
2512 if (acceptTokenClass(EHTokColon)) {
2513 HlslToken idToken;
2514 if (acceptTokenClass(EHTokPackOffset)) {
2515 if (! acceptTokenClass(EHTokLeftParen)) {
2516 expected("(");
2517 return;
2518 }
2519 acceptTokenClass(EHTokIdentifier);
2520 acceptTokenClass(EHTokDot);
2521 acceptTokenClass(EHTokIdentifier);
2522 if (! acceptTokenClass(EHTokRightParen)) {
2523 expected(")");
2524 break;
2525 }
2526 // TODO: process the packoffset information
John Kessenich3d157c52016-07-25 16:05:33 -06002527 // c1.y means component y of location slot 1
John Kessenich630dd7d2016-06-12 23:52:12 -06002528 } else if (! acceptIdentifier(idToken)) {
2529 expected("semantic or packoffset or register");
2530 return;
2531 } else if (*idToken.string == "register") {
2532 if (! acceptTokenClass(EHTokLeftParen)) {
2533 expected("(");
2534 return;
2535 }
2536 acceptTokenClass(EHTokIdentifier);
2537 acceptTokenClass(EHTokComma);
2538 acceptTokenClass(EHTokIdentifier);
2539 acceptTokenClass(EHTokLeftBracket);
2540 if (peekTokenClass(EHTokIntConstant))
2541 advanceToken();
2542 acceptTokenClass(EHTokRightBracket);
2543 if (! acceptTokenClass(EHTokRightParen)) {
2544 expected(")");
2545 break;
2546 }
2547 // TODO: process the register information
John Kessenich3d157c52016-07-25 16:05:33 -06002548 // b2 means buffer 2
John Kessenich630dd7d2016-06-12 23:52:12 -06002549 } else {
2550 // semantic, in idToken.string
2551 parseContext.handleSemantic(type, *idToken.string);
2552 }
2553 } else if (acceptTokenClass(EHTokLeftAngle)) {
2554 // TODO: process annotations, just accepting them for now
2555 do {
2556 if (peekTokenClass(EHTokNone))
2557 return;
2558 if (acceptTokenClass(EHTokRightAngle))
2559 break;
2560 advanceToken();
2561 } while (true);
2562 } else
2563 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002564
John Kessenich630dd7d2016-06-12 23:52:12 -06002565 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002566}
2567
John Kesseniche01a9bc2016-03-12 20:11:22 -07002568} // end namespace glslang