blob: 974c8959ee6ba019975f4351a2250efe5e1d06c6 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
John Kessenich927608b2017-01-06 12:34:14 -07002// Copyright (C) 2016 Google, Inc.
3// Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
John Kessenich927608b2017-01-06 12:34:14 -07005// All rights reserved.
John Kesseniche01a9bc2016-03-12 20:11:22 -07006//
John Kessenich927608b2017-01-06 12:34:14 -07007// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
John Kesseniche01a9bc2016-03-12 20:11:22 -070010//
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//
John Kessenich927608b2017-01-06 12:34:14 -070023// 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.
John Kesseniche01a9bc2016-03-12 20:11:22 -070035//
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"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenichaecd4972016-03-14 10:46:34 -060078// Only process the next token if it is an identifier.
79// Return true if it was an identifier.
80bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
81{
82 if (peekTokenClass(EHTokIdentifier)) {
83 idToken = token;
84 advanceToken();
85 return true;
86 }
87
steve-lunarg5ca85ad2016-12-26 18:45:52 -070088 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
89 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
90 // valid identifier, nor is "linear". This code special cases the known instances of this, so
91 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -070092
steve-lunarg5ca85ad2016-12-26 18:45:52 -070093 TString* idString = nullptr;
94 switch (peek()) {
95 case EHTokSample: idString = NewPoolTString("sample"); break;
96 case EHTokHalf: idString = NewPoolTString("half"); break;
97 case EHTokBool: idString = NewPoolTString("bool"); break;
98 case EHTokFloat: idString = NewPoolTString("float"); break;
99 case EHTokDouble: idString = NewPoolTString("double"); break;
100 case EHTokInt: idString = NewPoolTString("int"); break;
101 case EHTokUint: idString = NewPoolTString("uint"); break;
102 case EHTokMin16float: idString = NewPoolTString("min16float"); break;
103 case EHTokMin10float: idString = NewPoolTString("min10float"); break;
104 case EHTokMin16int: idString = NewPoolTString("min16int"); break;
105 case EHTokMin12int: idString = NewPoolTString("min12int"); break;
106 default:
107 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700108 }
109
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700110 token.string = idString;
111 token.tokenClass = EHTokIdentifier;
112 token.symbol = nullptr;
113 idToken = token;
114
115 advanceToken();
116
117 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600118}
119
John Kesseniche01a9bc2016-03-12 20:11:22 -0700120// compilationUnit
121// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600122// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700123//
124bool HlslGrammar::acceptCompilationUnit()
125{
John Kessenichd016be12016-03-13 11:24:20 -0600126 TIntermNode* unitNode = nullptr;
127
John Kessenich9c86c6a2016-05-03 22:49:24 -0600128 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600129 // HLSL allows semicolons between global declarations, e.g, between functions.
130 if (acceptTokenClass(EHTokSemicolon))
131 continue;
132
John Kessenichd016be12016-03-13 11:24:20 -0600133 // externalDeclaration
John Kessenich02467d82017-01-19 15:41:47 -0700134 TIntermNode* declarationNode1;
135 TIntermNode* declarationNode2 = nullptr; // sometimes the grammar for a single declaration creates two
136 if (! acceptDeclaration(declarationNode1, declarationNode2))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700137 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600138
139 // hook it up
John Kessenich02467d82017-01-19 15:41:47 -0700140 unitNode = intermediate.growAggregate(unitNode, declarationNode1);
141 if (declarationNode2 != nullptr)
142 unitNode = intermediate.growAggregate(unitNode, declarationNode2);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700143 }
144
John Kessenichd016be12016-03-13 11:24:20 -0600145 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600146 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600147
John Kesseniche01a9bc2016-03-12 20:11:22 -0700148 return true;
149}
150
LoopDawg4886f692016-06-29 10:58:58 -0600151// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700152// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600153//
154// sampler_state_assignment
155// : sampler_state_identifier EQUAL value SEMICOLON
156//
157// sampler_state_identifier
158// : ADDRESSU
159// | ADDRESSV
160// | ADDRESSW
161// | BORDERCOLOR
162// | FILTER
163// | MAXANISOTROPY
164// | MAXLOD
165// | MINLOD
166// | MIPLODBIAS
167//
168bool HlslGrammar::acceptSamplerState()
169{
170 // TODO: this should be genericized to accept a list of valid tokens and
171 // return token/value pairs. Presently it is specific to texture values.
172
173 if (! acceptTokenClass(EHTokLeftBrace))
174 return true;
175
176 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700177
LoopDawg4886f692016-06-29 10:58:58 -0600178 do {
179 // read state name
180 HlslToken state;
181 if (! acceptIdentifier(state))
182 break; // end of list
183
184 // FXC accepts any case
185 TString stateName = *state.string;
186 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
187
188 if (! acceptTokenClass(EHTokAssign)) {
189 expected("assign");
190 return false;
191 }
192
193 if (stateName == "minlod" || stateName == "maxlod") {
194 if (! peekTokenClass(EHTokIntConstant)) {
195 expected("integer");
196 return false;
197 }
198
199 TIntermTyped* lod = nullptr;
200 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
201 return false;
202 } else if (stateName == "maxanisotropy") {
203 if (! peekTokenClass(EHTokIntConstant)) {
204 expected("integer");
205 return false;
206 }
207
208 TIntermTyped* maxAnisotropy = nullptr;
209 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
210 return false;
211 } else if (stateName == "filter") {
212 HlslToken filterMode;
213 if (! acceptIdentifier(filterMode)) {
214 expected("filter mode");
215 return false;
216 }
217 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
218 HlslToken addrMode;
219 if (! acceptIdentifier(addrMode)) {
220 expected("texture address mode");
221 return false;
222 }
223 } else if (stateName == "miplodbias") {
224 TIntermTyped* lodBias = nullptr;
225 if (! acceptLiteral(lodBias)) {
226 expected("lod bias");
227 return false;
228 }
229 } else if (stateName == "bordercolor") {
230 return false;
231 } else {
232 expected("texture state");
233 return false;
234 }
235
236 // SEMICOLON
237 if (! acceptTokenClass(EHTokSemicolon)) {
238 expected("semicolon");
239 return false;
240 }
241 } while (true);
242
243 if (! acceptTokenClass(EHTokRightBrace))
244 return false;
245
246 return true;
247}
248
249// sampler_declaration_dx9
250// : SAMPLER identifier EQUAL sampler_type sampler_state
251//
John Kesseniche4821e42016-07-16 10:19:43 -0600252bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600253{
254 if (! acceptTokenClass(EHTokSampler))
255 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700256
LoopDawg4886f692016-06-29 10:58:58 -0600257 // TODO: remove this when DX9 style declarations are implemented.
258 unimplemented("Direct3D 9 sampler declaration");
259
260 // read sampler name
261 HlslToken name;
262 if (! acceptIdentifier(name)) {
263 expected("sampler name");
264 return false;
265 }
266
267 if (! acceptTokenClass(EHTokAssign)) {
268 expected("=");
269 return false;
270 }
271
272 return false;
273}
274
John Kesseniche01a9bc2016-03-12 20:11:22 -0700275// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600276// : sampler_declaration_dx9 post_decls SEMICOLON
277// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600278// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600279// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600280// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700281//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600282// declarator_list
283// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600284//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600285// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600286// : identifier array_specifier post_decls
287// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600288// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600289//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600290// Parsing has to go pretty far in to know whether it's a variable, prototype, or
291// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600292// as above. (The 'identifier' in the first item in init_declarator list is the
293// same as 'identifier' for function declarations.)
294//
295// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600296// or a function body.
297//
John Kessenich02467d82017-01-19 15:41:47 -0700298// 'node2' could get populated with a second decoration tree if a single source declaration
299// leads to two subtrees that need to be peers higher up.
300//
John Kessenichd016be12016-03-13 11:24:20 -0600301bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700302{
John Kessenich02467d82017-01-19 15:41:47 -0700303 TIntermNode* node2;
304 return acceptDeclaration(node, node2);
305}
306bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
307{
John Kessenichd016be12016-03-13 11:24:20 -0600308 node = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -0700309 node2 = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600310 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600311
steve-lunarg1868b142016-10-20 13:07:10 -0600312 // attributes
313 TAttributeMap attributes;
314 acceptAttributes(attributes);
315
John Kessenich5e69ec62016-07-05 00:02:40 -0600316 // typedef
317 bool typedefDecl = acceptTokenClass(EHTokTypedef);
318
John Kesseniche82061d2016-09-27 14:38:57 -0600319 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600320
321 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600322 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
323 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
324 // HLSL shaders, this will have to be a master level switch
325 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700326 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400327
John Kesseniche82061d2016-09-27 14:38:57 -0600328 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400329 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600330
331 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600332 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700333 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600334
John Kessenich87142c72016-03-12 20:24:24 -0700335 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600336 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600337 while (acceptIdentifier(idToken)) {
steve-lunargf1e0c872016-10-31 15:13:43 -0600338 TString* fnName = idToken.string;
339
340 // Potentially rename shader entry point function. No-op most of the time.
341 parseContext.renameShaderFunction(fnName);
342
John Kessenich5f934b02016-03-13 17:58:25 -0600343 // function_parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600344 TFunction& function = *new TFunction(fnName, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600345 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600346 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600347 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600348
John Kessenichd5ed0b62016-07-04 17:32:45 -0600349 // compound_statement (function body definition) or just a prototype?
350 if (peekTokenClass(EHTokLeftBrace)) {
351 if (list)
352 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600353 if (typedefDecl)
354 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich02467d82017-01-19 15:41:47 -0700355 return acceptFunctionDefinition(function, node, node2, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600356 } else {
357 if (typedefDecl)
358 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600359 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600360 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600361 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600362 // A variable declaration. Fix the storage qualifier if it's a global.
363 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
364 declaredType.getQualifier().storage = EvqUniform;
365
John Kessenichecba76f2017-01-06 00:34:48 -0700366 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600367 // the number of types can expand when arrayness is different.
368 TType variableType;
369 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600370
John Kesseniche82061d2016-09-27 14:38:57 -0600371 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600372 TArraySizes* arraySizes = nullptr;
373 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600374
John Kesseniche82061d2016-09-27 14:38:57 -0600375 // Fix arrayness in the variableType
376 if (declaredType.isImplicitlySizedArray()) {
377 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
378 // of different sizes, for this case sharing the shallow copy of arrayness
379 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
380 variableType.newArraySizes(declaredType.getArraySizes());
381 }
382 if (arraySizes || variableType.isArray()) {
383 // In the most general case, arrayness is potentially coming both from the
384 // declared type and from the variable: "int[] a[];" or just one or the other.
385 // Merge it all to the variableType, so all arrayness is part of the variableType.
386 parseContext.arrayDimMerge(variableType, arraySizes);
387 }
388
LoopDawg4886f692016-06-29 10:58:58 -0600389 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600390 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600391 if (! acceptSamplerState())
392 return false;
393 }
394
John Kessenichd5ed0b62016-07-04 17:32:45 -0600395 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600396 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600397
398 // EQUAL assignment_expression
399 TIntermTyped* expressionNode = nullptr;
400 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600401 if (typedefDecl)
402 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600403 if (! acceptAssignmentExpression(expressionNode)) {
404 expected("initializer");
405 return false;
406 }
407 }
408
steve-lunarg5da1f032017-02-12 17:50:28 -0700409 TString* blockName = idToken.string;
410
411 // For structbuffers, we couldn't create the block type while accepting the
412 // template type, because we need the identifier name. Now that we have that,
413 // we can create the buffer type.
414 // TODO: how to determine this without looking for implicit array sizes?
415 if (variableType.getBasicType() == EbtBlock) {
416 const int memberCount = variableType.getStruct()->size();
417 assert(memberCount > 0);
418
419 TType* contentType = (*variableType.getStruct())[memberCount-1].type;
420
421 // Set the field name and qualifier from the declaration, now that we know it.
422 if (contentType->isRuntimeSizedArray()) {
423 contentType->getQualifier() = variableType.getQualifier();
424 blockName = nullptr; // this will be an anonymous block...
425 contentType->setFieldName(*idToken.string); // field name is declaration name
426 variableType.setTypeName(*idToken.string);
427 }
428 }
429
John Kessenich6dbc0a72016-09-27 19:13:05 -0600430 // Hand off the actual declaration
431
432 // TODO: things scoped within an annotation need their own name space;
433 // TODO: strings are not yet handled.
434 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
435 if (typedefDecl)
436 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
437 else if (variableType.getBasicType() == EbtBlock)
steve-lunarg5da1f032017-02-12 17:50:28 -0700438 parseContext.declareBlock(idToken.loc, variableType, blockName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600439 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700440 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600441 // this isn't really an individual variable, but a member of the $Global buffer
442 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
443 } else {
444 // Declare the variable and add any initializer code to the AST.
445 // The top-level node is always made into an aggregate, as that's
446 // historically how the AST has been.
447 node = intermediate.growAggregate(node,
448 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
449 expressionNode),
450 idToken.loc);
451 }
452 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600453 }
John Kessenich5f934b02016-03-13 17:58:25 -0600454 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600455
456 if (acceptTokenClass(EHTokComma)) {
457 list = true;
458 continue;
459 }
460 };
461
462 // The top-level node is a sequence.
463 if (node != nullptr)
464 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700465
John Kessenich078d7f22016-03-14 10:02:11 -0600466 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600467 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700468 // This may have been a false detection of what appeared to be a declaration, but
469 // was actually an assignment such as "float = 4", where "float" is an identifier.
470 // We put the token back to let further parsing happen for cases where that may
471 // happen. This errors on the side of caution, and mostly triggers the error.
472
473 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
474 recedeToken();
475 else
476 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600477 return false;
478 }
John Kessenichecba76f2017-01-06 00:34:48 -0700479
John Kesseniche01a9bc2016-03-12 20:11:22 -0700480 return true;
481}
482
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600483// control_declaration
484// : fully_specified_type identifier EQUAL expression
485//
486bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
487{
488 node = nullptr;
489
490 // fully_specified_type
491 TType type;
492 if (! acceptFullySpecifiedType(type))
493 return false;
494
495 // identifier
496 HlslToken idToken;
497 if (! acceptIdentifier(idToken)) {
498 expected("identifier");
499 return false;
500 }
501
502 // EQUAL
503 TIntermTyped* expressionNode = nullptr;
504 if (! acceptTokenClass(EHTokAssign)) {
505 expected("=");
506 return false;
507 }
508
509 // expression
510 if (! acceptExpression(expressionNode)) {
511 expected("initializer");
512 return false;
513 }
514
John Kesseniche82061d2016-09-27 14:38:57 -0600515 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600516
517 return true;
518}
519
John Kessenich87142c72016-03-12 20:24:24 -0700520// fully_specified_type
521// : type_specifier
522// | type_qualifier type_specifier
523//
524bool HlslGrammar::acceptFullySpecifiedType(TType& type)
525{
526 // type_qualifier
527 TQualifier qualifier;
528 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600529 if (! acceptQualifier(qualifier))
530 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600531 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700532
533 // type_specifier
steve-lunarga64ed3e2016-12-18 17:51:14 -0700534 if (! acceptType(type)) {
535 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700536 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700537 // qualifier. Back it out, if we did.
538 if (qualifier.sample)
539 recedeToken();
540
John Kessenich87142c72016-03-12 20:24:24 -0700541 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700542 }
John Kessenich3d157c52016-07-25 16:05:33 -0600543 if (type.getBasicType() == EbtBlock) {
544 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600545 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600546 // further, it can create an anonymous instance of the block
547 if (peekTokenClass(EHTokSemicolon))
548 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600549 } else {
550 // Some qualifiers are set when parsing the type. Merge those with
551 // whatever comes from acceptQualifier.
552 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700553
steve-lunargbb0183f2016-10-04 16:58:14 -0600554 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600555 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700556
steve-lunarg5da1f032017-02-12 17:50:28 -0700557 if (type.getQualifier().storage == EvqVaryingOut ||
558 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700559 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700560 qualifier.readonly = type.getQualifier().readonly;
561 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700562
563 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600564 }
John Kessenich87142c72016-03-12 20:24:24 -0700565
566 return true;
567}
568
John Kessenich630dd7d2016-06-12 23:52:12 -0600569// type_qualifier
570// : qualifier qualifier ...
571//
572// Zero or more of these, so this can't return false.
573//
John Kessenichb9e39122016-08-17 10:22:08 -0600574bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700575{
John Kessenich630dd7d2016-06-12 23:52:12 -0600576 do {
577 switch (peek()) {
578 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600579 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600580 break;
581 case EHTokExtern:
582 // TODO: no meaning in glslang?
583 break;
584 case EHTokShared:
585 // TODO: hint
586 break;
587 case EHTokGroupShared:
588 qualifier.storage = EvqShared;
589 break;
590 case EHTokUniform:
591 qualifier.storage = EvqUniform;
592 break;
593 case EHTokConst:
594 qualifier.storage = EvqConst;
595 break;
596 case EHTokVolatile:
597 qualifier.volatil = true;
598 break;
599 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600600 qualifier.smooth = true;
601 break;
602 case EHTokCentroid:
603 qualifier.centroid = true;
604 break;
605 case EHTokNointerpolation:
606 qualifier.flat = true;
607 break;
608 case EHTokNoperspective:
609 qualifier.nopersp = true;
610 break;
611 case EHTokSample:
612 qualifier.sample = true;
613 break;
614 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600615 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600616 break;
617 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600618 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600619 break;
620 case EHTokPrecise:
621 qualifier.noContraction = true;
622 break;
LoopDawg9249c702016-07-12 20:44:32 -0600623 case EHTokIn:
624 qualifier.storage = EvqIn;
625 break;
626 case EHTokOut:
627 qualifier.storage = EvqOut;
628 break;
629 case EHTokInOut:
630 qualifier.storage = EvqInOut;
631 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600632 case EHTokLayout:
633 if (! acceptLayoutQualifierList(qualifier))
634 return false;
635 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700636 case EHTokGloballyCoherent:
637 qualifier.coherent = true;
638 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700639
640 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
641 // for output variables.
642 case EHTokPoint:
643 qualifier.storage = EvqIn;
644 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
645 return false;
646 break;
647 case EHTokLine:
648 qualifier.storage = EvqIn;
649 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
650 return false;
651 break;
652 case EHTokTriangle:
653 qualifier.storage = EvqIn;
654 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
655 return false;
656 break;
657 case EHTokLineAdj:
658 qualifier.storage = EvqIn;
659 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
660 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700661 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700662 case EHTokTriangleAdj:
663 qualifier.storage = EvqIn;
664 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
665 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700666 break;
667
John Kessenich630dd7d2016-06-12 23:52:12 -0600668 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600669 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600670 }
671 advanceToken();
672 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700673}
674
John Kessenichb9e39122016-08-17 10:22:08 -0600675// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600676// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600677//
678// layout_qualifier
679// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600680// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600681//
682// Zero or more of these, so this can't return false.
683//
684bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
685{
686 if (! acceptTokenClass(EHTokLayout))
687 return false;
688
689 // LEFT_PAREN
690 if (! acceptTokenClass(EHTokLeftParen))
691 return false;
692
693 do {
694 // identifier
695 HlslToken idToken;
696 if (! acceptIdentifier(idToken))
697 break;
698
699 // EQUAL expression
700 if (acceptTokenClass(EHTokAssign)) {
701 TIntermTyped* expr;
702 if (! acceptConditionalExpression(expr)) {
703 expected("expression");
704 return false;
705 }
706 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
707 } else
708 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
709
710 // COMMA
711 if (! acceptTokenClass(EHTokComma))
712 break;
713 } while (true);
714
715 // RIGHT_PAREN
716 if (! acceptTokenClass(EHTokRightParen)) {
717 expected(")");
718 return false;
719 }
720
721 return true;
722}
723
LoopDawg6daaa4f2016-06-23 19:13:48 -0600724// template_type
725// : FLOAT
726// | DOUBLE
727// | INT
728// | DWORD
729// | UINT
730// | BOOL
731//
steve-lunargf49cdf42016-11-17 15:04:20 -0700732bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600733{
734 switch (peek()) {
735 case EHTokFloat:
736 basicType = EbtFloat;
737 break;
738 case EHTokDouble:
739 basicType = EbtDouble;
740 break;
741 case EHTokInt:
742 case EHTokDword:
743 basicType = EbtInt;
744 break;
745 case EHTokUint:
746 basicType = EbtUint;
747 break;
748 case EHTokBool:
749 basicType = EbtBool;
750 break;
751 default:
752 return false;
753 }
754
755 advanceToken();
756
757 return true;
758}
759
760// vector_template_type
761// : VECTOR
762// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
763//
764bool HlslGrammar::acceptVectorTemplateType(TType& type)
765{
766 if (! acceptTokenClass(EHTokVector))
767 return false;
768
769 if (! acceptTokenClass(EHTokLeftAngle)) {
770 // in HLSL, 'vector' alone means float4.
771 new(&type) TType(EbtFloat, EvqTemporary, 4);
772 return true;
773 }
774
775 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700776 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600777 expected("scalar type");
778 return false;
779 }
780
781 // COMMA
782 if (! acceptTokenClass(EHTokComma)) {
783 expected(",");
784 return false;
785 }
786
787 // integer
788 if (! peekTokenClass(EHTokIntConstant)) {
789 expected("literal integer");
790 return false;
791 }
792
793 TIntermTyped* vecSize;
794 if (! acceptLiteral(vecSize))
795 return false;
796
797 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
798
799 new(&type) TType(basicType, EvqTemporary, vecSizeI);
800
801 if (vecSizeI == 1)
802 type.makeVector();
803
804 if (!acceptTokenClass(EHTokRightAngle)) {
805 expected("right angle bracket");
806 return false;
807 }
808
809 return true;
810}
811
812// matrix_template_type
813// : MATRIX
814// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
815//
816bool HlslGrammar::acceptMatrixTemplateType(TType& type)
817{
818 if (! acceptTokenClass(EHTokMatrix))
819 return false;
820
821 if (! acceptTokenClass(EHTokLeftAngle)) {
822 // in HLSL, 'matrix' alone means float4x4.
823 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
824 return true;
825 }
826
827 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700828 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600829 expected("scalar type");
830 return false;
831 }
832
833 // COMMA
834 if (! acceptTokenClass(EHTokComma)) {
835 expected(",");
836 return false;
837 }
838
839 // integer rows
840 if (! peekTokenClass(EHTokIntConstant)) {
841 expected("literal integer");
842 return false;
843 }
844
845 TIntermTyped* rows;
846 if (! acceptLiteral(rows))
847 return false;
848
849 // COMMA
850 if (! acceptTokenClass(EHTokComma)) {
851 expected(",");
852 return false;
853 }
John Kessenichecba76f2017-01-06 00:34:48 -0700854
LoopDawg6daaa4f2016-06-23 19:13:48 -0600855 // integer cols
856 if (! peekTokenClass(EHTokIntConstant)) {
857 expected("literal integer");
858 return false;
859 }
860
861 TIntermTyped* cols;
862 if (! acceptLiteral(cols))
863 return false;
864
865 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600866 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
867 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600868
869 if (!acceptTokenClass(EHTokRightAngle)) {
870 expected("right angle bracket");
871 return false;
872 }
873
874 return true;
875}
876
steve-lunargf49cdf42016-11-17 15:04:20 -0700877// layout_geometry
878// : LINESTREAM
879// | POINTSTREAM
880// | TRIANGLESTREAM
881//
882bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
883{
884 // read geometry type
885 const EHlslTokenClass geometryType = peek();
886
887 switch (geometryType) {
888 case EHTokPointStream: geometry = ElgPoints; break;
889 case EHTokLineStream: geometry = ElgLineStrip; break;
890 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
891 default:
892 return false; // not a layout geometry
893 }
894
895 advanceToken(); // consume the layout keyword
896 return true;
897}
898
steve-lunarg858c9282017-01-07 08:54:10 -0700899// tessellation_decl_type
900// : INPUTPATCH
901// | OUTPUTPATCH
902//
903bool HlslGrammar::acceptTessellationDeclType()
904{
905 // read geometry type
906 const EHlslTokenClass tessType = peek();
907
908 switch (tessType) {
909 case EHTokInputPatch: break;
910 case EHTokOutputPatch: break;
911 default:
912 return false; // not a tessellation decl
913 }
914
915 advanceToken(); // consume the keyword
916 return true;
917}
918
919// tessellation_patch_template_type
920// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
921//
922bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
923{
924 if (! acceptTessellationDeclType())
925 return false;
926
927 if (! acceptTokenClass(EHTokLeftAngle))
928 return false;
929
930 if (! acceptType(type)) {
931 expected("tessellation patch type");
932 return false;
933 }
934
935 if (! acceptTokenClass(EHTokComma))
936 return false;
937
938 // integer size
939 if (! peekTokenClass(EHTokIntConstant)) {
940 expected("literal integer");
941 return false;
942 }
943
944 TIntermTyped* size;
945 if (! acceptLiteral(size))
946 return false;
947
948 TArraySizes* arraySizes = new TArraySizes;
949 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
950 type.newArraySizes(*arraySizes);
951
952 if (! acceptTokenClass(EHTokRightAngle)) {
953 expected("right angle bracket");
954 return false;
955 }
956
957 return true;
958}
959
steve-lunargf49cdf42016-11-17 15:04:20 -0700960// stream_out_template_type
961// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
962//
963bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
964{
965 geometry = ElgNone;
966
967 if (! acceptOutputPrimitiveGeometry(geometry))
968 return false;
969
970 if (! acceptTokenClass(EHTokLeftAngle))
971 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700972
steve-lunargf49cdf42016-11-17 15:04:20 -0700973 if (! acceptType(type)) {
974 expected("stream output type");
975 return false;
976 }
977
978 type.getQualifier().storage = EvqVaryingOut;
979
980 if (! acceptTokenClass(EHTokRightAngle)) {
981 expected("right angle bracket");
982 return false;
983 }
984
985 return true;
986}
John Kessenichecba76f2017-01-06 00:34:48 -0700987
John Kessenicha1e2d492016-09-20 13:22:58 -0600988// annotations
989// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600990//
John Kessenicha1e2d492016-09-20 13:22:58 -0600991bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600992{
John Kessenicha1e2d492016-09-20 13:22:58 -0600993 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600994 return false;
995
John Kessenicha1e2d492016-09-20 13:22:58 -0600996 // note that we are nesting a name space
997 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600998
999 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1000 do {
1001 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1002 while (acceptTokenClass(EHTokSemicolon))
1003 ;
1004
1005 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001006 break;
John Kessenich86f71382016-09-19 20:23:18 -06001007
1008 // declaration
1009 TIntermNode* node;
1010 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001011 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001012 return false;
1013 }
1014 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001015
1016 parseContext.unnestAnnotations();
1017 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001018}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001019
LoopDawg4886f692016-06-29 10:58:58 -06001020// sampler_type
1021// : SAMPLER
1022// | SAMPLER1D
1023// | SAMPLER2D
1024// | SAMPLER3D
1025// | SAMPLERCUBE
1026// | SAMPLERSTATE
1027// | SAMPLERCOMPARISONSTATE
1028bool HlslGrammar::acceptSamplerType(TType& type)
1029{
1030 // read sampler type
1031 const EHlslTokenClass samplerType = peek();
1032
LoopDawga78b0292016-07-19 14:28:05 -06001033 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001034 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001035
LoopDawga78b0292016-07-19 14:28:05 -06001036 bool isShadow = false;
1037
LoopDawg4886f692016-06-29 10:58:58 -06001038 switch (samplerType) {
1039 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001040 case EHTokSampler1d: /*dim = Esd1D*/; break;
1041 case EHTokSampler2d: /*dim = Esd2D*/; break;
1042 case EHTokSampler3d: /*dim = Esd3D*/; break;
1043 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001044 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001045 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001046 default:
1047 return false; // not a sampler declaration
1048 }
1049
1050 advanceToken(); // consume the sampler type keyword
1051
1052 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001053
1054 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001055 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001056
1057 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1058
1059 return true;
1060}
1061
1062// texture_type
1063// | BUFFER
1064// | TEXTURE1D
1065// | TEXTURE1DARRAY
1066// | TEXTURE2D
1067// | TEXTURE2DARRAY
1068// | TEXTURE3D
1069// | TEXTURECUBE
1070// | TEXTURECUBEARRAY
1071// | TEXTURE2DMS
1072// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001073// | RWBUFFER
1074// | RWTEXTURE1D
1075// | RWTEXTURE1DARRAY
1076// | RWTEXTURE2D
1077// | RWTEXTURE2DARRAY
1078// | RWTEXTURE3D
1079
LoopDawg4886f692016-06-29 10:58:58 -06001080bool HlslGrammar::acceptTextureType(TType& type)
1081{
1082 const EHlslTokenClass textureType = peek();
1083
1084 TSamplerDim dim = EsdNone;
1085 bool array = false;
1086 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001087 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -06001088
1089 switch (textureType) {
1090 case EHTokBuffer: dim = EsdBuffer; break;
1091 case EHTokTexture1d: dim = Esd1D; break;
1092 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1093 case EHTokTexture2d: dim = Esd2D; break;
1094 case EHTokTexture2darray: dim = Esd2D; array = true; break;
John Kessenichecba76f2017-01-06 00:34:48 -07001095 case EHTokTexture3d: dim = Esd3D; break;
LoopDawg4886f692016-06-29 10:58:58 -06001096 case EHTokTextureCube: dim = EsdCube; break;
1097 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1098 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1099 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -06001100 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1101 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1102 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1103 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1104 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1105 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001106 default:
1107 return false; // not a texture declaration
1108 }
1109
1110 advanceToken(); // consume the texture object keyword
1111
1112 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001113
LoopDawg4886f692016-06-29 10:58:58 -06001114 TIntermTyped* msCount = nullptr;
1115
steve-lunargbb0183f2016-10-04 16:58:14 -06001116 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001117 if (acceptTokenClass(EHTokLeftAngle)) {
1118 if (! acceptType(txType)) {
1119 expected("scalar or vector type");
1120 return false;
1121 }
1122
1123 const TBasicType basicRetType = txType.getBasicType() ;
1124
1125 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1126 unimplemented("basic type in texture");
1127 return false;
1128 }
1129
steve-lunargd53f7172016-07-27 15:46:48 -06001130 // Buffers can handle small mats if they fit in 4 components
1131 if (dim == EsdBuffer && txType.isMatrix()) {
1132 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1133 expected("components < 4 in matrix buffer type");
1134 return false;
1135 }
1136
1137 // TODO: except we don't handle it yet...
1138 unimplemented("matrix type in buffer");
1139 return false;
1140 }
1141
LoopDawg4886f692016-06-29 10:58:58 -06001142 if (!txType.isScalar() && !txType.isVector()) {
1143 expected("scalar or vector type");
1144 return false;
1145 }
1146
LoopDawg4886f692016-06-29 10:58:58 -06001147 if (ms && acceptTokenClass(EHTokComma)) {
1148 // read sample count for multisample types, if given
1149 if (! peekTokenClass(EHTokIntConstant)) {
1150 expected("multisample count");
1151 return false;
1152 }
1153
1154 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1155 return false;
1156 }
1157
1158 if (! acceptTokenClass(EHTokRightAngle)) {
1159 expected("right angle bracket");
1160 return false;
1161 }
1162 } else if (ms) {
1163 expected("texture type for multisample");
1164 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001165 } else if (image) {
1166 expected("type for RWTexture/RWBuffer");
1167 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001168 }
1169
1170 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001171 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001172
1173 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001174 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001175
steve-lunarg4f2da272016-10-10 15:24:57 -06001176 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1177 if (image || dim == EsdBuffer)
1178 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001179
1180 // Non-image Buffers are combined
1181 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001182 sampler.set(txType.getBasicType(), dim, array);
1183 } else {
1184 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001185 if (image) {
1186 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1187 } else {
1188 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1189 }
steve-lunargd53f7172016-07-27 15:46:48 -06001190 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001191
1192 // Remember the declared vector size.
1193 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001194
LoopDawg4886f692016-06-29 10:58:58 -06001195 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001196 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001197
1198 return true;
1199}
1200
John Kessenich87142c72016-03-12 20:24:24 -07001201// If token is for a type, update 'type' with the type information,
1202// and return true and advance.
1203// Otherwise, return false, and don't advance
1204bool HlslGrammar::acceptType(TType& type)
1205{
steve-lunarg3226b082016-10-26 19:18:55 -06001206 // Basic types for min* types, broken out here in case of future
1207 // changes, e.g, to use native halfs.
1208 static const TBasicType min16float_bt = EbtFloat;
1209 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001210 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001211 static const TBasicType min16int_bt = EbtInt;
1212 static const TBasicType min12int_bt = EbtInt;
1213 static const TBasicType min16uint_bt = EbtUint;
1214
John Kessenich9c86c6a2016-05-03 22:49:24 -06001215 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001216 case EHTokVector:
1217 return acceptVectorTemplateType(type);
1218 break;
1219
1220 case EHTokMatrix:
1221 return acceptMatrixTemplateType(type);
1222 break;
1223
steve-lunargf49cdf42016-11-17 15:04:20 -07001224 case EHTokPointStream: // fall through
1225 case EHTokLineStream: // ...
1226 case EHTokTriangleStream: // ...
1227 {
1228 TLayoutGeometry geometry;
1229 if (! acceptStreamOutTemplateType(type, geometry))
1230 return false;
1231
1232 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1233 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001234
steve-lunargf49cdf42016-11-17 15:04:20 -07001235 return true;
1236 }
1237
steve-lunarg858c9282017-01-07 08:54:10 -07001238 case EHTokInputPatch: // fall through
1239 case EHTokOutputPatch: // ...
1240 {
1241 if (! acceptTessellationPatchTemplateType(type))
1242 return false;
1243
1244 return true;
1245 }
1246
LoopDawg4886f692016-06-29 10:58:58 -06001247 case EHTokSampler: // fall through
1248 case EHTokSampler1d: // ...
1249 case EHTokSampler2d: // ...
1250 case EHTokSampler3d: // ...
1251 case EHTokSamplerCube: // ...
1252 case EHTokSamplerState: // ...
1253 case EHTokSamplerComparisonState: // ...
1254 return acceptSamplerType(type);
1255 break;
1256
1257 case EHTokBuffer: // fall through
1258 case EHTokTexture1d: // ...
1259 case EHTokTexture1darray: // ...
1260 case EHTokTexture2d: // ...
1261 case EHTokTexture2darray: // ...
1262 case EHTokTexture3d: // ...
1263 case EHTokTextureCube: // ...
1264 case EHTokTextureCubearray: // ...
1265 case EHTokTexture2DMS: // ...
1266 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001267 case EHTokRWTexture1d: // ...
1268 case EHTokRWTexture1darray: // ...
1269 case EHTokRWTexture2d: // ...
1270 case EHTokRWTexture2darray: // ...
1271 case EHTokRWTexture3d: // ...
1272 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001273 return acceptTextureType(type);
1274 break;
1275
steve-lunarg5da1f032017-02-12 17:50:28 -07001276 case EHTokAppendStructuredBuffer:
1277 case EHTokByteAddressBuffer:
1278 case EHTokConsumeStructuredBuffer:
1279 case EHTokRWByteAddressBuffer:
1280 case EHTokRWStructuredBuffer:
1281 case EHTokStructuredBuffer:
1282 return acceptStructBufferType(type);
1283 break;
1284
John Kesseniche6e74942016-06-11 16:43:14 -06001285 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001286 case EHTokCBuffer:
1287 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001288 return acceptStruct(type);
John Kesseniche6e74942016-06-11 16:43:14 -06001289
1290 case EHTokIdentifier:
1291 // An identifier could be for a user-defined type.
1292 // Note we cache the symbol table lookup, to save for a later rule
1293 // when this is not a type.
1294 token.symbol = parseContext.symbolTable.find(*token.string);
1295 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1296 type.shallowCopy(token.symbol->getType());
1297 advanceToken();
1298 return true;
1299 } else
1300 return false;
1301
John Kessenich71351de2016-06-08 12:50:56 -06001302 case EHTokVoid:
1303 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001304 break;
John Kessenich71351de2016-06-08 12:50:56 -06001305
John Kessenicha1e2d492016-09-20 13:22:58 -06001306 case EHTokString:
1307 new(&type) TType(EbtString);
1308 break;
1309
John Kessenich87142c72016-03-12 20:24:24 -07001310 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001311 new(&type) TType(EbtFloat);
1312 break;
John Kessenich87142c72016-03-12 20:24:24 -07001313 case EHTokFloat1:
1314 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001315 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001316 break;
John Kessenich87142c72016-03-12 20:24:24 -07001317 case EHTokFloat2:
1318 new(&type) TType(EbtFloat, EvqTemporary, 2);
1319 break;
1320 case EHTokFloat3:
1321 new(&type) TType(EbtFloat, EvqTemporary, 3);
1322 break;
1323 case EHTokFloat4:
1324 new(&type) TType(EbtFloat, EvqTemporary, 4);
1325 break;
1326
John Kessenich71351de2016-06-08 12:50:56 -06001327 case EHTokDouble:
1328 new(&type) TType(EbtDouble);
1329 break;
1330 case EHTokDouble1:
1331 new(&type) TType(EbtDouble);
1332 type.makeVector();
1333 break;
1334 case EHTokDouble2:
1335 new(&type) TType(EbtDouble, EvqTemporary, 2);
1336 break;
1337 case EHTokDouble3:
1338 new(&type) TType(EbtDouble, EvqTemporary, 3);
1339 break;
1340 case EHTokDouble4:
1341 new(&type) TType(EbtDouble, EvqTemporary, 4);
1342 break;
1343
1344 case EHTokInt:
1345 case EHTokDword:
1346 new(&type) TType(EbtInt);
1347 break;
1348 case EHTokInt1:
1349 new(&type) TType(EbtInt);
1350 type.makeVector();
1351 break;
John Kessenich87142c72016-03-12 20:24:24 -07001352 case EHTokInt2:
1353 new(&type) TType(EbtInt, EvqTemporary, 2);
1354 break;
1355 case EHTokInt3:
1356 new(&type) TType(EbtInt, EvqTemporary, 3);
1357 break;
1358 case EHTokInt4:
1359 new(&type) TType(EbtInt, EvqTemporary, 4);
1360 break;
1361
John Kessenich71351de2016-06-08 12:50:56 -06001362 case EHTokUint:
1363 new(&type) TType(EbtUint);
1364 break;
1365 case EHTokUint1:
1366 new(&type) TType(EbtUint);
1367 type.makeVector();
1368 break;
1369 case EHTokUint2:
1370 new(&type) TType(EbtUint, EvqTemporary, 2);
1371 break;
1372 case EHTokUint3:
1373 new(&type) TType(EbtUint, EvqTemporary, 3);
1374 break;
1375 case EHTokUint4:
1376 new(&type) TType(EbtUint, EvqTemporary, 4);
1377 break;
1378
1379 case EHTokBool:
1380 new(&type) TType(EbtBool);
1381 break;
1382 case EHTokBool1:
1383 new(&type) TType(EbtBool);
1384 type.makeVector();
1385 break;
John Kessenich87142c72016-03-12 20:24:24 -07001386 case EHTokBool2:
1387 new(&type) TType(EbtBool, EvqTemporary, 2);
1388 break;
1389 case EHTokBool3:
1390 new(&type) TType(EbtBool, EvqTemporary, 3);
1391 break;
1392 case EHTokBool4:
1393 new(&type) TType(EbtBool, EvqTemporary, 4);
1394 break;
1395
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001396 case EHTokHalf:
1397 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1398 break;
1399 case EHTokHalf1:
1400 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1401 type.makeVector();
1402 break;
1403 case EHTokHalf2:
1404 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1405 break;
1406 case EHTokHalf3:
1407 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1408 break;
1409 case EHTokHalf4:
1410 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1411 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001412
steve-lunarg3226b082016-10-26 19:18:55 -06001413 case EHTokMin16float:
1414 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1415 break;
1416 case EHTokMin16float1:
1417 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1418 type.makeVector();
1419 break;
1420 case EHTokMin16float2:
1421 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1422 break;
1423 case EHTokMin16float3:
1424 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1425 break;
1426 case EHTokMin16float4:
1427 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1428 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001429
steve-lunarg3226b082016-10-26 19:18:55 -06001430 case EHTokMin10float:
1431 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1432 break;
1433 case EHTokMin10float1:
1434 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1435 type.makeVector();
1436 break;
1437 case EHTokMin10float2:
1438 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1439 break;
1440 case EHTokMin10float3:
1441 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1442 break;
1443 case EHTokMin10float4:
1444 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1445 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001446
steve-lunarg3226b082016-10-26 19:18:55 -06001447 case EHTokMin16int:
1448 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1449 break;
1450 case EHTokMin16int1:
1451 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1452 type.makeVector();
1453 break;
1454 case EHTokMin16int2:
1455 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1456 break;
1457 case EHTokMin16int3:
1458 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1459 break;
1460 case EHTokMin16int4:
1461 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1462 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001463
steve-lunarg3226b082016-10-26 19:18:55 -06001464 case EHTokMin12int:
1465 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1466 break;
1467 case EHTokMin12int1:
1468 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1469 type.makeVector();
1470 break;
1471 case EHTokMin12int2:
1472 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1473 break;
1474 case EHTokMin12int3:
1475 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1476 break;
1477 case EHTokMin12int4:
1478 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1479 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001480
steve-lunarg3226b082016-10-26 19:18:55 -06001481 case EHTokMin16uint:
1482 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1483 break;
1484 case EHTokMin16uint1:
1485 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1486 type.makeVector();
1487 break;
1488 case EHTokMin16uint2:
1489 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1490 break;
1491 case EHTokMin16uint3:
1492 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1493 break;
1494 case EHTokMin16uint4:
1495 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1496 break;
1497
John Kessenich0133c122016-05-20 12:17:26 -06001498 case EHTokInt1x1:
1499 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1500 break;
1501 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001502 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001503 break;
1504 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001505 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001506 break;
1507 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001508 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001509 break;
1510 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001511 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001512 break;
1513 case EHTokInt2x2:
1514 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1515 break;
1516 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001517 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001518 break;
1519 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001520 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001521 break;
1522 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001523 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001524 break;
1525 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001526 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001527 break;
1528 case EHTokInt3x3:
1529 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1530 break;
1531 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001532 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001533 break;
1534 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001535 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001536 break;
1537 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001538 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001539 break;
1540 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001541 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001542 break;
1543 case EHTokInt4x4:
1544 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1545 break;
1546
John Kessenich71351de2016-06-08 12:50:56 -06001547 case EHTokUint1x1:
1548 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1549 break;
1550 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001551 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001552 break;
1553 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001554 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001555 break;
1556 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001557 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001558 break;
1559 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001560 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001561 break;
1562 case EHTokUint2x2:
1563 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1564 break;
1565 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001566 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001567 break;
1568 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001569 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001570 break;
1571 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001572 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001573 break;
1574 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001575 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001576 break;
1577 case EHTokUint3x3:
1578 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1579 break;
1580 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001581 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001582 break;
1583 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001584 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001585 break;
1586 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001587 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001588 break;
1589 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001590 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001591 break;
1592 case EHTokUint4x4:
1593 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1594 break;
1595
1596 case EHTokBool1x1:
1597 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1598 break;
1599 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001600 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001601 break;
1602 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001603 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001604 break;
1605 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001606 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001607 break;
1608 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001609 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001610 break;
1611 case EHTokBool2x2:
1612 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1613 break;
1614 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001615 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001616 break;
1617 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001618 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001619 break;
1620 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001621 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001622 break;
1623 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001624 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001625 break;
1626 case EHTokBool3x3:
1627 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1628 break;
1629 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001630 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001631 break;
1632 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001633 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001634 break;
1635 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001636 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001637 break;
1638 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001639 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001640 break;
1641 case EHTokBool4x4:
1642 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1643 break;
1644
John Kessenich0133c122016-05-20 12:17:26 -06001645 case EHTokFloat1x1:
1646 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1647 break;
1648 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001649 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001650 break;
1651 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001652 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001653 break;
1654 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001655 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001656 break;
1657 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001658 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001659 break;
John Kessenich87142c72016-03-12 20:24:24 -07001660 case EHTokFloat2x2:
1661 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1662 break;
1663 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001664 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001665 break;
1666 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001667 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001668 break;
John Kessenich0133c122016-05-20 12:17:26 -06001669 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001670 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001671 break;
John Kessenich87142c72016-03-12 20:24:24 -07001672 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001673 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001674 break;
1675 case EHTokFloat3x3:
1676 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1677 break;
1678 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001679 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001680 break;
John Kessenich0133c122016-05-20 12:17:26 -06001681 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001682 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001683 break;
John Kessenich87142c72016-03-12 20:24:24 -07001684 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001685 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001686 break;
1687 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001688 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001689 break;
1690 case EHTokFloat4x4:
1691 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1692 break;
1693
John Kessenich0133c122016-05-20 12:17:26 -06001694 case EHTokDouble1x1:
1695 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1696 break;
1697 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001698 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001699 break;
1700 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001701 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001702 break;
1703 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001704 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001705 break;
1706 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001707 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001708 break;
1709 case EHTokDouble2x2:
1710 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1711 break;
1712 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001713 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001714 break;
1715 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001716 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001717 break;
1718 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001719 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001720 break;
1721 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001722 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001723 break;
1724 case EHTokDouble3x3:
1725 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1726 break;
1727 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001728 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001729 break;
1730 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001731 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001732 break;
1733 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001734 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001735 break;
1736 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001737 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001738 break;
1739 case EHTokDouble4x4:
1740 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1741 break;
1742
John Kessenich87142c72016-03-12 20:24:24 -07001743 default:
1744 return false;
1745 }
1746
1747 advanceToken();
1748
1749 return true;
1750}
1751
John Kesseniche6e74942016-06-11 16:43:14 -06001752// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001753// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1754// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1755//
1756// struct_type
1757// : STRUCT
1758// | CBUFFER
1759// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001760//
1761bool HlslGrammar::acceptStruct(TType& type)
1762{
John Kessenichb804de62016-09-05 12:19:18 -06001763 // This storage qualifier will tell us whether it's an AST
1764 // block type or just a generic structure type.
1765 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001766
1767 // CBUFFER
1768 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001769 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001770 // TBUFFER
1771 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001772 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001773 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001774 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001775 return false;
1776
1777 // IDENTIFIER
1778 TString structName = "";
1779 if (peekTokenClass(EHTokIdentifier)) {
1780 structName = *token.string;
1781 advanceToken();
1782 }
1783
John Kessenich3d157c52016-07-25 16:05:33 -06001784 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001785 TQualifier postDeclQualifier;
1786 postDeclQualifier.clear();
1787 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001788
John Kesseniche6e74942016-06-11 16:43:14 -06001789 // LEFT_BRACE
1790 if (! acceptTokenClass(EHTokLeftBrace)) {
1791 expected("{");
1792 return false;
1793 }
1794
1795 // struct_declaration_list
1796 TTypeList* typeList;
1797 if (! acceptStructDeclarationList(typeList)) {
1798 expected("struct member declarations");
1799 return false;
1800 }
1801
1802 // RIGHT_BRACE
1803 if (! acceptTokenClass(EHTokRightBrace)) {
1804 expected("}");
1805 return false;
1806 }
1807
1808 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001809 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001810 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001811 else {
John Kessenich7735b942016-09-05 12:40:06 -06001812 postDeclQualifier.storage = storageQualifier;
1813 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001814 }
John Kesseniche6e74942016-06-11 16:43:14 -06001815
John Kessenich727b3742017-02-03 17:57:55 -07001816 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001817
1818 return true;
1819}
1820
steve-lunarg5da1f032017-02-12 17:50:28 -07001821// struct_buffer
1822// : APPENDSTRUCTUREDBUFFER
1823// | BYTEADDRESSBUFFER
1824// | CONSUMESTRUCTUREDBUFFER
1825// | RWBYTEADDRESSBUFFER
1826// | RWSTRUCTUREDBUFFER
1827// | STRUCTUREDBUFFER
1828bool HlslGrammar::acceptStructBufferType(TType& type)
1829{
1830 const EHlslTokenClass structBuffType = peek();
1831
1832 // TODO: globallycoherent
1833 bool hasTemplateType = true;
1834 bool readonly = false;
1835
1836 TStorageQualifier storage = EvqBuffer;
1837
1838 switch (structBuffType) {
1839 case EHTokAppendStructuredBuffer:
1840 unimplemented("AppendStructuredBuffer");
1841 return false;
1842 case EHTokByteAddressBuffer:
1843 hasTemplateType = false;
1844 readonly = true;
1845 break;
1846 case EHTokConsumeStructuredBuffer:
1847 unimplemented("ConsumeStructuredBuffer");
1848 return false;
1849 case EHTokRWByteAddressBuffer:
1850 hasTemplateType = false;
1851 break;
1852 case EHTokRWStructuredBuffer:
1853 break;
1854 case EHTokStructuredBuffer:
1855 readonly = true;
1856 break;
1857 default:
1858 return false; // not a structure buffer type
1859 }
1860
1861 advanceToken(); // consume the structure keyword
1862
1863 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
1864 TType* templateType = new TType;
1865
1866 if (hasTemplateType) {
1867 if (! acceptTokenClass(EHTokLeftAngle)) {
1868 expected("left angle bracket");
1869 return false;
1870 }
1871
1872 if (! acceptType(*templateType)) {
1873 expected("type");
1874 return false;
1875 }
1876 if (! acceptTokenClass(EHTokRightAngle)) {
1877 expected("right angle bracket");
1878 return false;
1879 }
1880 } else {
1881 // byte address buffers have no explicit type.
1882 TType uintType(EbtUint, storage);
1883 templateType->shallowCopy(uintType);
1884 }
1885
1886 // Create an unsized array out of that type.
1887 // TODO: does this work if it's already an array type?
1888 TArraySizes unsizedArray;
1889 unsizedArray.addInnerSize(UnsizedArraySize);
1890 templateType->newArraySizes(unsizedArray);
1891 templateType->getQualifier().storage = storage;
1892 templateType->getQualifier().readonly = readonly;
1893
1894 // Create block type. TODO: hidden internal uint member when needed
1895 TTypeList* blockStruct = new TTypeList;
1896 TTypeLoc member = { templateType, token.loc };
1897 blockStruct->push_back(member);
1898
1899 TType blockType(blockStruct, "", templateType->getQualifier());
1900
1901 // It's not until we see the name during declaration that we can set the
1902 // field name. That happens in HlslGrammar::acceptDeclaration.
1903 type.shallowCopy(blockType);
1904
1905 return true;
1906}
1907
John Kesseniche6e74942016-06-11 16:43:14 -06001908// struct_declaration_list
1909// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1910//
1911// struct_declaration
1912// : fully_specified_type struct_declarator COMMA struct_declarator ...
1913//
1914// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001915// : IDENTIFIER post_decls
1916// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001917//
1918bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1919{
1920 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001921 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001922
1923 do {
1924 // success on seeing the RIGHT_BRACE coming up
1925 if (peekTokenClass(EHTokRightBrace))
1926 return true;
1927
1928 // struct_declaration
1929
1930 // fully_specified_type
1931 TType memberType;
1932 if (! acceptFullySpecifiedType(memberType)) {
1933 expected("member type");
1934 return false;
1935 }
1936
1937 // struct_declarator COMMA struct_declarator ...
1938 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001939 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001940 expected("member name");
1941 return false;
1942 }
1943
1944 // add it to the list of members
1945 TTypeLoc member = { new TType(EbtVoid), token.loc };
1946 member.type->shallowCopy(memberType);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001947 member.type->setFieldName(*idToken.string);
John Kesseniche6e74942016-06-11 16:43:14 -06001948 typeList->push_back(member);
1949
John Kesseniche6e74942016-06-11 16:43:14 -06001950 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001951 TArraySizes* arraySizes = nullptr;
1952 acceptArraySpecifier(arraySizes);
1953 if (arraySizes)
1954 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001955
John Kessenich7735b942016-09-05 12:40:06 -06001956 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001957
John Kessenich18adbdb2017-02-02 15:16:20 -07001958 // EQUAL assignment_expression
1959 if (acceptTokenClass(EHTokAssign)) {
1960 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
1961 TIntermTyped* expressionNode = nullptr;
1962 if (! acceptAssignmentExpression(expressionNode)) {
1963 expected("initializer");
1964 return false;
1965 }
1966 }
1967
John Kesseniche6e74942016-06-11 16:43:14 -06001968 // success on seeing the SEMICOLON coming up
1969 if (peekTokenClass(EHTokSemicolon))
1970 break;
1971
1972 // COMMA
1973 if (! acceptTokenClass(EHTokComma)) {
1974 expected(",");
1975 return false;
1976 }
1977
1978 } while (true);
1979
1980 // SEMI_COLON
1981 if (! acceptTokenClass(EHTokSemicolon)) {
1982 expected(";");
1983 return false;
1984 }
1985
1986 } while (true);
1987}
1988
John Kessenich5f934b02016-03-13 17:58:25 -06001989// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001990// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001991// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001992//
1993bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1994{
John Kessenich078d7f22016-03-14 10:02:11 -06001995 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001996 if (! acceptTokenClass(EHTokLeftParen))
1997 return false;
1998
John Kessenich71351de2016-06-08 12:50:56 -06001999 // VOID RIGHT_PAREN
2000 if (! acceptTokenClass(EHTokVoid)) {
2001 do {
2002 // parameter_declaration
2003 if (! acceptParameterDeclaration(function))
2004 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002005
John Kessenich71351de2016-06-08 12:50:56 -06002006 // COMMA
2007 if (! acceptTokenClass(EHTokComma))
2008 break;
2009 } while (true);
2010 }
John Kessenich5f934b02016-03-13 17:58:25 -06002011
John Kessenich078d7f22016-03-14 10:02:11 -06002012 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002013 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002014 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002015 return false;
2016 }
2017
2018 return true;
2019}
2020
steve-lunarg26d31452016-12-23 18:56:57 -07002021// default_parameter_declaration
2022// : EQUAL conditional_expression
2023// : EQUAL initializer
2024bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2025{
2026 node = nullptr;
2027
2028 // Valid not to have a default_parameter_declaration
2029 if (!acceptTokenClass(EHTokAssign))
2030 return true;
2031
2032 if (!acceptConditionalExpression(node)) {
2033 if (!acceptInitializer(node))
2034 return false;
2035
2036 // For initializer lists, we have to const-fold into a constructor for the type, so build
2037 // that.
2038 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
2039 if (constructor == nullptr) // cannot construct
2040 return false;
2041
2042 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002043 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002044 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002045
steve-lunarg26d31452016-12-23 18:56:57 -07002046 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2047 }
2048
2049 // If this is simply a constant, we can use it directly.
2050 if (node->getAsConstantUnion())
2051 return true;
2052
2053 // Otherwise, it has to be const-foldable.
2054 TIntermTyped* origNode = node;
2055
2056 node = intermediate.fold(node->getAsAggregate());
2057
2058 if (node != nullptr && origNode != node)
2059 return true;
2060
2061 parseContext.error(token.loc, "invalid default parameter value", "", "");
2062
2063 return false;
2064}
2065
John Kessenich5f934b02016-03-13 17:58:25 -06002066// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002067// : fully_specified_type post_decls [ = default_parameter_declaration ]
2068// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002069//
2070bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2071{
2072 // fully_specified_type
2073 TType* type = new TType;
2074 if (! acceptFullySpecifiedType(*type))
2075 return false;
2076
2077 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002078 HlslToken idToken;
2079 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002080
John Kessenich19b92ff2016-06-19 11:50:34 -06002081 // array_specifier
2082 TArraySizes* arraySizes = nullptr;
2083 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002084 if (arraySizes) {
2085 if (arraySizes->isImplicit()) {
2086 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2087 return false;
2088 }
2089
John Kessenich19b92ff2016-06-19 11:50:34 -06002090 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002091 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002092
2093 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002094 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002095
steve-lunarg26d31452016-12-23 18:56:57 -07002096 TIntermTyped* defaultValue;
2097 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2098 return false;
2099
John Kessenich5aa59e22016-06-17 15:50:47 -06002100 parseContext.paramFix(*type);
2101
steve-lunarg26d31452016-12-23 18:56:57 -07002102 // If any prior parameters have default values, all the parameters after that must as well.
2103 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2104 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2105 return false;
2106 }
2107
2108 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002109 function.addParameter(param);
2110
2111 return true;
2112}
2113
2114// Do the work to create the function definition in addition to
2115// parsing the body (compound_statement).
John Kessenich02467d82017-01-19 15:41:47 -07002116bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, TIntermNode*& node2, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06002117{
John Kessenicha3051662016-09-02 19:13:36 -06002118 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06002119 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06002120
John Kessenich077e0522016-06-09 02:02:17 -06002121 // This does a pushScope()
John Kessenich02467d82017-01-19 15:41:47 -07002122 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
John Kessenich5f934b02016-03-13 17:58:25 -06002123
2124 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002125 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002126 if (! acceptCompoundStatement(functionBody))
2127 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002128
John Kessenich02467d82017-01-19 15:41:47 -07002129 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
2130
2131 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002132}
2133
John Kessenich0d2b6de2016-06-05 11:23:11 -06002134// Accept an expression with parenthesis around it, where
2135// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002136// syntactically required ones like in "if ( expression )".
2137//
2138// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002139//
2140// Note this one is not set up to be speculative; as it gives
2141// errors if not found.
2142//
2143bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2144{
2145 // LEFT_PAREN
2146 if (! acceptTokenClass(EHTokLeftParen))
2147 expected("(");
2148
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002149 bool decl = false;
2150 TIntermNode* declNode = nullptr;
2151 decl = acceptControlDeclaration(declNode);
2152 if (decl) {
2153 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2154 expected("initialized declaration");
2155 return false;
2156 } else
2157 expression = declNode->getAsTyped();
2158 } else {
2159 // no declaration
2160 if (! acceptExpression(expression)) {
2161 expected("expression");
2162 return false;
2163 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002164 }
2165
2166 // RIGHT_PAREN
2167 if (! acceptTokenClass(EHTokRightParen))
2168 expected(")");
2169
2170 return true;
2171}
2172
John Kessenich34fb0362016-05-03 23:17:20 -06002173// The top-level full expression recognizer.
2174//
John Kessenich87142c72016-03-12 20:24:24 -07002175// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002176// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002177//
2178bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2179{
LoopDawgef764a22016-06-03 09:17:51 -06002180 node = nullptr;
2181
John Kessenich34fb0362016-05-03 23:17:20 -06002182 // assignment_expression
2183 if (! acceptAssignmentExpression(node))
2184 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002185
John Kessenich34fb0362016-05-03 23:17:20 -06002186 if (! peekTokenClass(EHTokComma))
2187 return true;
2188
2189 do {
2190 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002191 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002192 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002193
John Kessenich34fb0362016-05-03 23:17:20 -06002194 // ... assignment_expression
2195 TIntermTyped* rightNode = nullptr;
2196 if (! acceptAssignmentExpression(rightNode)) {
2197 expected("assignment expression");
2198 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002199 }
2200
John Kessenich34fb0362016-05-03 23:17:20 -06002201 node = intermediate.addComma(node, rightNode, loc);
2202
2203 if (! peekTokenClass(EHTokComma))
2204 return true;
2205 } while (true);
2206}
2207
John Kessenich07354242016-07-01 19:58:06 -06002208// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002209// : LEFT_BRACE RIGHT_BRACE
2210// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002211//
2212// initializer_list
2213// : assignment_expression COMMA assignment_expression COMMA ...
2214//
2215bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2216{
2217 // LEFT_BRACE
2218 if (! acceptTokenClass(EHTokLeftBrace))
2219 return false;
2220
John Kessenich98ad4852016-11-27 17:39:07 -07002221 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002222 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002223 if (acceptTokenClass(EHTokRightBrace)) {
2224 // a zero-length initializer list
2225 node = intermediate.makeAggregate(loc);
2226 return true;
2227 }
2228
2229 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002230 node = nullptr;
2231 do {
2232 // assignment_expression
2233 TIntermTyped* expr;
2234 if (! acceptAssignmentExpression(expr)) {
2235 expected("assignment expression in initializer list");
2236 return false;
2237 }
2238 node = intermediate.growAggregate(node, expr, loc);
2239
2240 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002241 if (acceptTokenClass(EHTokComma)) {
2242 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2243 return true;
John Kessenich07354242016-07-01 19:58:06 -06002244 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002245 }
John Kessenich07354242016-07-01 19:58:06 -06002246
2247 // RIGHT_BRACE
2248 if (acceptTokenClass(EHTokRightBrace))
2249 return true;
2250
2251 expected(", or }");
2252 return false;
2253 } while (true);
2254}
2255
John Kessenich34fb0362016-05-03 23:17:20 -06002256// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002257// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002258//
2259// a op (b op (c op d))
2260//
2261// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002262// : initializer
2263// | conditional_expression
2264// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002265//
2266bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2267{
John Kessenich07354242016-07-01 19:58:06 -06002268 // initializer
2269 if (peekTokenClass(EHTokLeftBrace)) {
2270 if (acceptInitializer(node))
2271 return true;
2272
2273 expected("initializer");
2274 return false;
2275 }
2276
John Kessenich00957f82016-07-27 10:39:57 -06002277 // conditional_expression
2278 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002279 return false;
2280
John Kessenich07354242016-07-01 19:58:06 -06002281 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002282 TOperator assignOp = HlslOpMap::assignment(peek());
2283 if (assignOp == EOpNull)
2284 return true;
2285
John Kessenich00957f82016-07-27 10:39:57 -06002286 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002287 TSourceLoc loc = token.loc;
2288 advanceToken();
2289
John Kessenich00957f82016-07-27 10:39:57 -06002290 // conditional_expression assign_op conditional_expression ...
2291 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002292 // gets the right-to-left associativity.
2293 TIntermTyped* rightNode = nullptr;
2294 if (! acceptAssignmentExpression(rightNode)) {
2295 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002296 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002297 }
2298
John Kessenichd21baed2016-09-16 03:05:12 -06002299 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002300 node = parseContext.handleLvalue(loc, "assign", node);
2301
John Kessenichfea226b2016-07-28 17:53:56 -06002302 if (node == nullptr) {
2303 parseContext.error(loc, "could not create assignment", "", "");
2304 return false;
2305 }
John Kessenich34fb0362016-05-03 23:17:20 -06002306
2307 if (! peekTokenClass(EHTokComma))
2308 return true;
2309
2310 return true;
2311}
2312
John Kessenich00957f82016-07-27 10:39:57 -06002313// Accept a conditional expression, which associates right-to-left,
2314// accomplished by the "true" expression calling down to lower
2315// precedence levels than this level.
2316//
2317// conditional_expression
2318// : binary_expression
2319// | binary_expression QUESTION expression COLON assignment_expression
2320//
2321bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2322{
2323 // binary_expression
2324 if (! acceptBinaryExpression(node, PlLogicalOr))
2325 return false;
2326
2327 if (! acceptTokenClass(EHTokQuestion))
2328 return true;
2329
2330 TIntermTyped* trueNode = nullptr;
2331 if (! acceptExpression(trueNode)) {
2332 expected("expression after ?");
2333 return false;
2334 }
2335 TSourceLoc loc = token.loc;
2336
2337 if (! acceptTokenClass(EHTokColon)) {
2338 expected(":");
2339 return false;
2340 }
2341
2342 TIntermTyped* falseNode = nullptr;
2343 if (! acceptAssignmentExpression(falseNode)) {
2344 expected("expression after :");
2345 return false;
2346 }
2347
2348 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2349
2350 return true;
2351}
2352
John Kessenich34fb0362016-05-03 23:17:20 -06002353// Accept a binary expression, for binary operations that
2354// associate left-to-right. This is, it is implicit, for example
2355//
2356// ((a op b) op c) op d
2357//
2358// binary_expression
2359// : expression op expression op expression ...
2360//
2361// where 'expression' is the next higher level in precedence.
2362//
2363bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2364{
2365 if (precedenceLevel > PlMul)
2366 return acceptUnaryExpression(node);
2367
2368 // assignment_expression
2369 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2370 return false;
2371
John Kessenich34fb0362016-05-03 23:17:20 -06002372 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002373 TOperator op = HlslOpMap::binary(peek());
2374 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2375 if (tokenLevel < precedenceLevel)
2376 return true;
2377
John Kessenich34fb0362016-05-03 23:17:20 -06002378 // ... op
2379 TSourceLoc loc = token.loc;
2380 advanceToken();
2381
2382 // ... expression
2383 TIntermTyped* rightNode = nullptr;
2384 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2385 expected("expression");
2386 return false;
2387 }
2388
2389 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002390 if (node == nullptr) {
2391 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2392 return false;
2393 }
John Kessenich34fb0362016-05-03 23:17:20 -06002394 } while (true);
2395}
2396
2397// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002398// : (type) unary_expression
2399// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002400// | - unary_expression
2401// | ! unary_expression
2402// | ~ unary_expression
2403// | ++ unary_expression
2404// | -- unary_expression
2405// | postfix_expression
2406//
2407bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2408{
John Kessenich1cc1a282016-06-03 16:55:49 -06002409 // (type) unary_expression
2410 // Have to look two steps ahead, because this could be, e.g., a
2411 // postfix_expression instead, since that also starts with at "(".
2412 if (acceptTokenClass(EHTokLeftParen)) {
2413 TType castType;
2414 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002415 if (acceptTokenClass(EHTokRightParen)) {
2416 // We've matched "(type)" now, get the expression to cast
2417 TSourceLoc loc = token.loc;
2418 if (! acceptUnaryExpression(node))
2419 return false;
2420
2421 // Hook it up like a constructor
2422 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2423 if (constructorFunction == nullptr) {
2424 expected("type that can be constructed");
2425 return false;
2426 }
2427 TIntermTyped* arguments = nullptr;
2428 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2429 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2430
2431 return true;
2432 } else {
2433 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2434 // the '(int' part. We must back up twice.
2435 recedeToken();
2436 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002437 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002438 } else {
2439 // This isn't a type cast, but it still started "(", so if it is a
2440 // unary expression, it can only be a postfix_expression, so try that.
2441 // Back it up first.
2442 recedeToken();
2443 return acceptPostfixExpression(node);
2444 }
2445 }
2446
2447 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002448 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002449
John Kessenich1cc1a282016-06-03 16:55:49 -06002450 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002451 if (unaryOp == EOpNull)
2452 return acceptPostfixExpression(node);
2453
2454 // op unary_expression
2455 TSourceLoc loc = token.loc;
2456 advanceToken();
2457 if (! acceptUnaryExpression(node))
2458 return false;
2459
2460 // + is a no-op
2461 if (unaryOp == EOpAdd)
2462 return true;
2463
2464 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002465
2466 // These unary ops require lvalues
2467 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2468 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002469
2470 return node != nullptr;
2471}
2472
2473// postfix_expression
2474// : LEFT_PAREN expression RIGHT_PAREN
2475// | literal
2476// | constructor
2477// | identifier
2478// | function_call
2479// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2480// | postfix_expression DOT IDENTIFIER
2481// | postfix_expression INC_OP
2482// | postfix_expression DEC_OP
2483//
2484bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2485{
2486 // Not implemented as self-recursive:
2487 // The logical "right recursion" is done with an loop at the end
2488
2489 // idToken will pick up either a variable or a function name in a function call
2490 HlslToken idToken;
2491
John Kessenich21472ae2016-06-04 11:46:33 -06002492 // Find something before the postfix operations, as they can't operate
2493 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002494 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002495 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002496 if (! acceptExpression(node)) {
2497 expected("expression");
2498 return false;
2499 }
2500 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002501 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002502 return false;
2503 }
John Kessenich34fb0362016-05-03 23:17:20 -06002504 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002505 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002506 } else if (acceptConstructor(node)) {
2507 // constructor (nothing else to do yet)
2508 } else if (acceptIdentifier(idToken)) {
2509 // identifier or function_call name
2510 if (! peekTokenClass(EHTokLeftParen)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -07002511 node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002512 } else if (acceptFunctionCall(idToken, node)) {
2513 // function_call (nothing else to do yet)
2514 } else {
2515 expected("function call arguments");
2516 return false;
2517 }
John Kessenich21472ae2016-06-04 11:46:33 -06002518 } else {
2519 // nothing found, can't post operate
2520 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002521 }
2522
steve-lunarga2b01a02016-11-28 17:09:54 -07002523 // This is to guarantee we do this no matter how we get out of the stack frame.
2524 // This way there's no bug if an early return forgets to do it.
2525 struct tFinalize {
2526 tFinalize(HlslParseContext& p) : parseContext(p) { }
2527 ~tFinalize() { parseContext.finalizeFlattening(); }
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002528 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002529 private:
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002530 const tFinalize& operator=(const tFinalize& f);
2531 tFinalize(const tFinalize& f);
steve-lunarga2b01a02016-11-28 17:09:54 -07002532 } finalize(parseContext);
2533
2534 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2535 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2536 // level: hence the init and finalize. Even though in practice these must be
2537 // constants, they are parsed no matter what.
2538 parseContext.initFlattening();
2539
John Kessenich21472ae2016-06-04 11:46:33 -06002540 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002541 do {
2542 TSourceLoc loc = token.loc;
2543 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002544
John Kessenich34fb0362016-05-03 23:17:20 -06002545 // Consume only a valid post-unary operator, otherwise we are done.
2546 switch (postOp) {
2547 case EOpIndexDirectStruct:
2548 case EOpIndexIndirect:
2549 case EOpPostIncrement:
2550 case EOpPostDecrement:
2551 advanceToken();
2552 break;
2553 default:
2554 return true;
2555 }
John Kessenich87142c72016-03-12 20:24:24 -07002556
John Kessenich34fb0362016-05-03 23:17:20 -06002557 // We have a valid post-unary operator, process it.
2558 switch (postOp) {
2559 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002560 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002561 // DOT IDENTIFIER
2562 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002563 HlslToken field;
2564 if (! acceptIdentifier(field)) {
2565 expected("swizzle or member");
2566 return false;
2567 }
LoopDawg4886f692016-06-29 10:58:58 -06002568
2569 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002570 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002571
2572 // In the event of a method node, we look for an open paren and accept the function call.
steve-lunarga2b01a02016-11-28 17:09:54 -07002573 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002574 if (! acceptFunctionCall(field, node, base)) {
2575 expected("function parameters");
2576 return false;
2577 }
2578 }
2579
John Kessenich34fb0362016-05-03 23:17:20 -06002580 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002581 }
John Kessenich34fb0362016-05-03 23:17:20 -06002582 case EOpIndexIndirect:
2583 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002584 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002585 TIntermTyped* indexNode = nullptr;
2586 if (! acceptExpression(indexNode) ||
2587 ! peekTokenClass(EHTokRightBracket)) {
2588 expected("expression followed by ']'");
2589 return false;
2590 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002591 advanceToken();
2592 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2593 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002594 }
2595 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002596 // INC_OP
2597 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002598 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002599 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002600 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002601 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002602 break;
2603 default:
2604 assert(0);
2605 break;
2606 }
2607 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002608}
2609
John Kessenichd016be12016-03-13 11:24:20 -06002610// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002611// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002612//
2613bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2614{
2615 // type
2616 TType type;
2617 if (acceptType(type)) {
2618 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2619 if (constructorFunction == nullptr)
2620 return false;
2621
2622 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002623 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002624 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002625 // It's possible this is a type keyword used as an identifier. Put the token back
2626 // for later use.
2627 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002628 return false;
2629 }
2630
2631 // hook it up
2632 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2633
2634 return true;
2635 }
2636
2637 return false;
2638}
2639
John Kessenich34fb0362016-05-03 23:17:20 -06002640// The function_call identifier was already recognized, and passed in as idToken.
2641//
2642// function_call
2643// : [idToken] arguments
2644//
LoopDawg4886f692016-06-29 10:58:58 -06002645bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002646{
John Kessenich4678ca92016-05-13 09:33:42 -06002647 // arguments
2648 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2649 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002650
2651 // methods have an implicit first argument of the calling object.
2652 if (base != nullptr)
2653 parseContext.handleFunctionArgument(function, arguments, base);
2654
John Kessenich4678ca92016-05-13 09:33:42 -06002655 if (! acceptArguments(function, arguments))
2656 return false;
2657
2658 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2659
2660 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002661}
2662
John Kessenich87142c72016-03-12 20:24:24 -07002663// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002664// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002665//
John Kessenichd016be12016-03-13 11:24:20 -06002666// The arguments are pushed onto the 'function' argument list and
2667// onto the 'arguments' aggregate.
2668//
John Kessenich4678ca92016-05-13 09:33:42 -06002669bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002670{
John Kessenich078d7f22016-03-14 10:02:11 -06002671 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002672 if (! acceptTokenClass(EHTokLeftParen))
2673 return false;
2674
2675 do {
John Kessenichd016be12016-03-13 11:24:20 -06002676 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002677 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002678 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002679 break;
John Kessenichd016be12016-03-13 11:24:20 -06002680
2681 // hook it up
2682 parseContext.handleFunctionArgument(function, arguments, arg);
2683
John Kessenich078d7f22016-03-14 10:02:11 -06002684 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002685 if (! acceptTokenClass(EHTokComma))
2686 break;
2687 } while (true);
2688
John Kessenich078d7f22016-03-14 10:02:11 -06002689 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002690 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002691 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002692 return false;
2693 }
2694
2695 return true;
2696}
2697
2698bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2699{
2700 switch (token.tokenClass) {
2701 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002702 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002703 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002704 case EHTokUintConstant:
2705 node = intermediate.addConstantUnion(token.u, token.loc, true);
2706 break;
John Kessenich87142c72016-03-12 20:24:24 -07002707 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002708 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002709 break;
2710 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002711 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002712 break;
2713 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002714 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002715 break;
John Kessenich86f71382016-09-19 20:23:18 -06002716 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07002717 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06002718 break;
John Kessenich87142c72016-03-12 20:24:24 -07002719
2720 default:
2721 return false;
2722 }
2723
2724 advanceToken();
2725
2726 return true;
2727}
2728
John Kessenich5f934b02016-03-13 17:58:25 -06002729// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002730// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002731//
John Kessenich21472ae2016-06-04 11:46:33 -06002732bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002733{
John Kessenich21472ae2016-06-04 11:46:33 -06002734 TIntermAggregate* compoundStatement = nullptr;
2735
John Kessenich34fb0362016-05-03 23:17:20 -06002736 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002737 if (! acceptTokenClass(EHTokLeftBrace))
2738 return false;
2739
2740 // statement statement ...
2741 TIntermNode* statement = nullptr;
2742 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002743 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2744 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2745 branch->getFlowOp() == EOpDefault)) {
2746 // hook up individual subsequences within a switch statement
2747 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2748 compoundStatement = nullptr;
2749 } else {
2750 // hook it up to the growing compound statement
2751 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2752 }
John Kessenich5f934b02016-03-13 17:58:25 -06002753 }
John Kessenich34fb0362016-05-03 23:17:20 -06002754 if (compoundStatement)
2755 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002756
John Kessenich21472ae2016-06-04 11:46:33 -06002757 retStatement = compoundStatement;
2758
John Kessenich34fb0362016-05-03 23:17:20 -06002759 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002760 return acceptTokenClass(EHTokRightBrace);
2761}
2762
John Kessenich0d2b6de2016-06-05 11:23:11 -06002763bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2764{
2765 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002766 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002767 parseContext.popScope();
2768
2769 return result;
2770}
2771
John Kessenich077e0522016-06-09 02:02:17 -06002772bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002773{
John Kessenich077e0522016-06-09 02:02:17 -06002774 parseContext.pushScope();
2775 bool result = acceptCompoundStatement(statement);
2776 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002777
2778 return result;
2779}
2780
John Kessenich5f934b02016-03-13 17:58:25 -06002781// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002782// : attributes attributed_statement
2783//
2784// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002785// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002786// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002787// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002788// | declaration_statement
2789// | selection_statement
2790// | switch_statement
2791// | case_label
2792// | iteration_statement
2793// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002794//
2795bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2796{
John Kessenich21472ae2016-06-04 11:46:33 -06002797 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002798
John Kessenich21472ae2016-06-04 11:46:33 -06002799 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002800 TAttributeMap attributes;
2801 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002802
John Kessenich21472ae2016-06-04 11:46:33 -06002803 // attributed_statement
2804 switch (peek()) {
2805 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002806 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002807
John Kessenich21472ae2016-06-04 11:46:33 -06002808 case EHTokIf:
2809 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002810
John Kessenich21472ae2016-06-04 11:46:33 -06002811 case EHTokSwitch:
2812 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002813
John Kessenich21472ae2016-06-04 11:46:33 -06002814 case EHTokFor:
2815 case EHTokDo:
2816 case EHTokWhile:
2817 return acceptIterationStatement(statement);
2818
2819 case EHTokContinue:
2820 case EHTokBreak:
2821 case EHTokDiscard:
2822 case EHTokReturn:
2823 return acceptJumpStatement(statement);
2824
2825 case EHTokCase:
2826 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002827 case EHTokDefault:
2828 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002829
2830 case EHTokSemicolon:
2831 return acceptTokenClass(EHTokSemicolon);
2832
2833 case EHTokRightBrace:
2834 // Performance: not strictly necessary, but stops a bunch of hunting early,
2835 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002836 return false;
2837
John Kessenich21472ae2016-06-04 11:46:33 -06002838 default:
2839 {
2840 // declaration
2841 if (acceptDeclaration(statement))
2842 return true;
2843
2844 // expression
2845 TIntermTyped* node;
2846 if (acceptExpression(node))
2847 statement = node;
2848 else
2849 return false;
2850
2851 // SEMICOLON (following an expression)
2852 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002853 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002854 return false;
2855 }
2856 }
2857 }
2858
John Kessenich5f934b02016-03-13 17:58:25 -06002859 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002860}
2861
John Kessenich21472ae2016-06-04 11:46:33 -06002862// attributes
2863// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2864//
2865// attribute:
2866// : UNROLL
2867// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2868// | FASTOPT
2869// | ALLOW_UAV_CONDITION
2870// | BRANCH
2871// | FLATTEN
2872// | FORCECASE
2873// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002874// | DOMAIN
2875// | EARLYDEPTHSTENCIL
2876// | INSTANCE
2877// | MAXTESSFACTOR
2878// | OUTPUTCONTROLPOINTS
2879// | OUTPUTTOPOLOGY
2880// | PARTITIONING
2881// | PATCHCONSTANTFUNC
2882// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002883//
steve-lunarg1868b142016-10-20 13:07:10 -06002884void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002885{
steve-lunarg1868b142016-10-20 13:07:10 -06002886 // For now, accept the [ XXX(X) ] syntax, but drop all but
2887 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002888 // TODO: subset to correct set? Pass on?
2889 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002890 HlslToken idToken;
2891
John Kessenich0d2b6de2016-06-05 11:23:11 -06002892 // LEFT_BRACKET?
2893 if (! acceptTokenClass(EHTokLeftBracket))
2894 return;
2895
2896 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002897 if (acceptIdentifier(idToken)) {
2898 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002899 } else if (! peekTokenClass(EHTokRightBracket)) {
2900 expected("identifier");
2901 advanceToken();
2902 }
2903
steve-lunarga22f7db2016-11-11 08:17:44 -07002904 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002905
2906 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002907 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002908 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002909
John Kessenich0d2b6de2016-06-05 11:23:11 -06002910 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002911 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07002912
steve-lunarga22f7db2016-11-11 08:17:44 -07002913 while (acceptAssignmentExpression(node)) {
2914 expectingExpression = false;
2915 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002916 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002917 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002918 }
2919
steve-lunarga22f7db2016-11-11 08:17:44 -07002920 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002921 if (! acceptTokenClass(EHTokRightParen))
2922 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002923
2924 // Error for partial or missing expression
2925 if (expectingExpression || expressions->getSequence().empty())
2926 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002927 }
2928
2929 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002930 if (!acceptTokenClass(EHTokRightBracket)) {
2931 expected("]");
2932 return;
2933 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002934
steve-lunarg1868b142016-10-20 13:07:10 -06002935 // Add any values we found into the attribute map. This accepts
2936 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002937 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002938 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002939}
2940
John Kessenich0d2b6de2016-06-05 11:23:11 -06002941// selection_statement
2942// : IF LEFT_PAREN expression RIGHT_PAREN statement
2943// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2944//
John Kessenich21472ae2016-06-04 11:46:33 -06002945bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2946{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002947 TSourceLoc loc = token.loc;
2948
2949 // IF
2950 if (! acceptTokenClass(EHTokIf))
2951 return false;
2952
2953 // so that something declared in the condition is scoped to the lifetimes
2954 // of the then-else statements
2955 parseContext.pushScope();
2956
2957 // LEFT_PAREN expression RIGHT_PAREN
2958 TIntermTyped* condition;
2959 if (! acceptParenExpression(condition))
2960 return false;
2961
2962 // create the child statements
2963 TIntermNodePair thenElse = { nullptr, nullptr };
2964
2965 // then statement
2966 if (! acceptScopedStatement(thenElse.node1)) {
2967 expected("then statement");
2968 return false;
2969 }
2970
2971 // ELSE
2972 if (acceptTokenClass(EHTokElse)) {
2973 // else statement
2974 if (! acceptScopedStatement(thenElse.node2)) {
2975 expected("else statement");
2976 return false;
2977 }
2978 }
2979
2980 // Put the pieces together
2981 statement = intermediate.addSelection(condition, thenElse, loc);
2982 parseContext.popScope();
2983
2984 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002985}
2986
John Kessenichd02dc5d2016-07-01 00:04:11 -06002987// switch_statement
2988// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2989//
John Kessenich21472ae2016-06-04 11:46:33 -06002990bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2991{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002992 // SWITCH
2993 TSourceLoc loc = token.loc;
2994 if (! acceptTokenClass(EHTokSwitch))
2995 return false;
2996
2997 // LEFT_PAREN expression RIGHT_PAREN
2998 parseContext.pushScope();
2999 TIntermTyped* switchExpression;
3000 if (! acceptParenExpression(switchExpression)) {
3001 parseContext.popScope();
3002 return false;
3003 }
3004
3005 // compound_statement
3006 parseContext.pushSwitchSequence(new TIntermSequence);
3007 bool statementOkay = acceptCompoundStatement(statement);
3008 if (statementOkay)
3009 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
3010
3011 parseContext.popSwitchSequence();
3012 parseContext.popScope();
3013
3014 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003015}
3016
John Kessenich119f8f62016-06-05 15:44:07 -06003017// iteration_statement
3018// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3019// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3020// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3021//
3022// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06003023bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
3024{
John Kessenich119f8f62016-06-05 15:44:07 -06003025 TSourceLoc loc = token.loc;
3026 TIntermTyped* condition = nullptr;
3027
3028 EHlslTokenClass loop = peek();
3029 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3030
3031 // WHILE or DO or FOR
3032 advanceToken();
3033
3034 switch (loop) {
3035 case EHTokWhile:
3036 // so that something declared in the condition is scoped to the lifetime
3037 // of the while sub-statement
3038 parseContext.pushScope();
3039 parseContext.nestLooping();
3040
3041 // LEFT_PAREN condition RIGHT_PAREN
3042 if (! acceptParenExpression(condition))
3043 return false;
3044
3045 // statement
3046 if (! acceptScopedStatement(statement)) {
3047 expected("while sub-statement");
3048 return false;
3049 }
3050
3051 parseContext.unnestLooping();
3052 parseContext.popScope();
3053
3054 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
3055
3056 return true;
3057
3058 case EHTokDo:
3059 parseContext.nestLooping();
3060
3061 if (! acceptTokenClass(EHTokLeftBrace))
3062 expected("{");
3063
3064 // statement
3065 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
3066 expected("do sub-statement");
3067 return false;
3068 }
3069
3070 if (! acceptTokenClass(EHTokRightBrace))
3071 expected("}");
3072
3073 // WHILE
3074 if (! acceptTokenClass(EHTokWhile)) {
3075 expected("while");
3076 return false;
3077 }
3078
3079 // LEFT_PAREN condition RIGHT_PAREN
3080 TIntermTyped* condition;
3081 if (! acceptParenExpression(condition))
3082 return false;
3083
3084 if (! acceptTokenClass(EHTokSemicolon))
3085 expected(";");
3086
3087 parseContext.unnestLooping();
3088
3089 statement = intermediate.addLoop(statement, condition, 0, false, loc);
3090
3091 return true;
3092
3093 case EHTokFor:
3094 {
3095 // LEFT_PAREN
3096 if (! acceptTokenClass(EHTokLeftParen))
3097 expected("(");
3098
3099 // so that something declared in the condition is scoped to the lifetime
3100 // of the for sub-statement
3101 parseContext.pushScope();
3102
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003103 // initializer
3104 TIntermNode* initNode = nullptr;
3105 if (! acceptControlDeclaration(initNode)) {
3106 TIntermTyped* initExpr = nullptr;
3107 acceptExpression(initExpr);
3108 initNode = initExpr;
3109 }
3110 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06003111 if (! acceptTokenClass(EHTokSemicolon))
3112 expected(";");
3113
3114 parseContext.nestLooping();
3115
3116 // condition SEMI_COLON
3117 acceptExpression(condition);
3118 if (! acceptTokenClass(EHTokSemicolon))
3119 expected(";");
3120
3121 // iterator SEMI_COLON
3122 TIntermTyped* iterator = nullptr;
3123 acceptExpression(iterator);
3124 if (! acceptTokenClass(EHTokRightParen))
3125 expected(")");
3126
3127 // statement
3128 if (! acceptScopedStatement(statement)) {
3129 expected("for sub-statement");
3130 return false;
3131 }
3132
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003133 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06003134
3135 parseContext.popScope();
3136 parseContext.unnestLooping();
3137
3138 return true;
3139 }
3140
3141 default:
3142 return false;
3143 }
John Kessenich21472ae2016-06-04 11:46:33 -06003144}
3145
3146// jump_statement
3147// : CONTINUE SEMICOLON
3148// | BREAK SEMICOLON
3149// | DISCARD SEMICOLON
3150// | RETURN SEMICOLON
3151// | RETURN expression SEMICOLON
3152//
3153bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3154{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003155 EHlslTokenClass jump = peek();
3156 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003157 case EHTokContinue:
3158 case EHTokBreak:
3159 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003160 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003161 advanceToken();
3162 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003163 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003164 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003165 return false;
3166 }
John Kessenich21472ae2016-06-04 11:46:33 -06003167
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003168 switch (jump) {
3169 case EHTokContinue:
3170 statement = intermediate.addBranch(EOpContinue, token.loc);
3171 break;
3172 case EHTokBreak:
3173 statement = intermediate.addBranch(EOpBreak, token.loc);
3174 break;
3175 case EHTokDiscard:
3176 statement = intermediate.addBranch(EOpKill, token.loc);
3177 break;
3178
3179 case EHTokReturn:
3180 {
3181 // expression
3182 TIntermTyped* node;
3183 if (acceptExpression(node)) {
3184 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003185 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003186 } else
3187 statement = intermediate.addBranch(EOpReturn, token.loc);
3188 break;
3189 }
3190
3191 default:
3192 assert(0);
3193 return false;
3194 }
3195
3196 // SEMICOLON
3197 if (! acceptTokenClass(EHTokSemicolon))
3198 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003199
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003200 return true;
3201}
John Kessenich21472ae2016-06-04 11:46:33 -06003202
John Kessenichd02dc5d2016-07-01 00:04:11 -06003203// case_label
3204// : CASE expression COLON
3205//
John Kessenich21472ae2016-06-04 11:46:33 -06003206bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3207{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003208 TSourceLoc loc = token.loc;
3209 if (! acceptTokenClass(EHTokCase))
3210 return false;
3211
3212 TIntermTyped* expression;
3213 if (! acceptExpression(expression)) {
3214 expected("case expression");
3215 return false;
3216 }
3217
3218 if (! acceptTokenClass(EHTokColon)) {
3219 expected(":");
3220 return false;
3221 }
3222
3223 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3224
3225 return true;
3226}
3227
3228// default_label
3229// : DEFAULT COLON
3230//
3231bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3232{
3233 TSourceLoc loc = token.loc;
3234 if (! acceptTokenClass(EHTokDefault))
3235 return false;
3236
3237 if (! acceptTokenClass(EHTokColon)) {
3238 expected(":");
3239 return false;
3240 }
3241
3242 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3243
3244 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003245}
3246
John Kessenich19b92ff2016-06-19 11:50:34 -06003247// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003248// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3249// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003250//
3251void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3252{
3253 arraySizes = nullptr;
3254
steve-lunarg7b211a32016-10-13 12:26:18 -06003255 // Early-out if there aren't any array dimensions
3256 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003257 return;
3258
steve-lunarg7b211a32016-10-13 12:26:18 -06003259 // If we get here, we have at least one array dimension. This will track the sizes we find.
John Kessenich19b92ff2016-06-19 11:50:34 -06003260 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003261
3262 // Collect each array dimension.
3263 while (acceptTokenClass(EHTokLeftBracket)) {
3264 TSourceLoc loc = token.loc;
3265 TIntermTyped* sizeExpr = nullptr;
3266
3267 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
3268 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3269
3270 if (! acceptTokenClass(EHTokRightBracket)) {
3271 expected("]");
3272 return;
3273 }
3274
3275 if (hasArraySize) {
3276 TArraySize arraySize;
3277 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3278 arraySizes->addInnerSize(arraySize);
3279 } else {
3280 arraySizes->addInnerSize(0); // sized by initializers.
3281 }
steve-lunarg265c0612016-09-27 10:57:35 -06003282 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003283}
3284
John Kessenich630dd7d2016-06-12 23:52:12 -06003285// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003286// : COLON semantic // optional
3287// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3288// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003289// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003290// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003291//
John Kessenich7735b942016-09-05 12:40:06 -06003292void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003293{
John Kessenich630dd7d2016-06-12 23:52:12 -06003294 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003295 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003296 if (acceptTokenClass(EHTokColon)) {
3297 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003298 if (peekTokenClass(EHTokLayout))
3299 acceptLayoutQualifierList(qualifier);
3300 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003301 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003302 if (! acceptTokenClass(EHTokLeftParen)) {
3303 expected("(");
3304 return;
3305 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003306 HlslToken locationToken;
3307 if (! acceptIdentifier(locationToken)) {
3308 expected("c[subcomponent][.component]");
3309 return;
3310 }
3311 HlslToken componentToken;
3312 if (acceptTokenClass(EHTokDot)) {
3313 if (! acceptIdentifier(componentToken)) {
3314 expected("component");
3315 return;
3316 }
3317 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003318 if (! acceptTokenClass(EHTokRightParen)) {
3319 expected(")");
3320 break;
3321 }
John Kessenich7735b942016-09-05 12:40:06 -06003322 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003323 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003324 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06003325 return;
3326 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003327 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3328 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003329 if (! acceptTokenClass(EHTokLeftParen)) {
3330 expected("(");
3331 return;
3332 }
John Kessenichb38f0712016-07-30 10:29:54 -06003333 HlslToken registerDesc; // for Type#
3334 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003335 if (! acceptIdentifier(registerDesc)) {
3336 expected("register number description");
3337 return;
3338 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003339 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3340 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003341 // Then we didn't really see the registerDesc yet, it was
3342 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003343 profile = registerDesc;
3344 if (! acceptIdentifier(registerDesc)) {
3345 expected("register number description");
3346 return;
3347 }
3348 }
John Kessenichb38f0712016-07-30 10:29:54 -06003349 int subComponent = 0;
3350 if (acceptTokenClass(EHTokLeftBracket)) {
3351 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3352 if (! peekTokenClass(EHTokIntConstant)) {
3353 expected("literal integer");
3354 return;
3355 }
3356 subComponent = token.i;
3357 advanceToken();
3358 if (! acceptTokenClass(EHTokRightBracket)) {
3359 expected("]");
3360 break;
3361 }
3362 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003363 // (COMMA SPACEN)opt
3364 HlslToken spaceDesc;
3365 if (acceptTokenClass(EHTokComma)) {
3366 if (! acceptIdentifier(spaceDesc)) {
3367 expected ("space identifier");
3368 return;
3369 }
3370 }
3371 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003372 if (! acceptTokenClass(EHTokRightParen)) {
3373 expected(")");
3374 break;
3375 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003376 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003377 } else {
3378 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003379 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003380 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003381 } else if (peekTokenClass(EHTokLeftAngle))
3382 acceptAnnotations(qualifier);
3383 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003384 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003385
John Kessenich630dd7d2016-06-12 23:52:12 -06003386 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003387}
3388
John Kesseniche01a9bc2016-03-12 20:11:22 -07003389} // end namespace glslang