blob: a891b68f14e2516dfb3132bc8d54b1a7f9138588 [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 Kessenich7a41f962017-03-22 11:38:22 -060078// IDENTIFIER
79// THIS
80// type that can be used as IDENTIFIER
81//
John Kessenichaecd4972016-03-14 10:46:34 -060082// Only process the next token if it is an identifier.
83// Return true if it was an identifier.
84bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
85{
John Kessenich7a41f962017-03-22 11:38:22 -060086 // IDENTIFIER
John Kessenichaecd4972016-03-14 10:46:34 -060087 if (peekTokenClass(EHTokIdentifier)) {
88 idToken = token;
89 advanceToken();
90 return true;
91 }
92
John Kessenich7a41f962017-03-22 11:38:22 -060093 // THIS
94 // -> maps to the IDENTIFIER spelled with the internal special name for 'this'
95 if (peekTokenClass(EHTokThis)) {
96 idToken = token;
97 advanceToken();
98 idToken.tokenClass = EHTokIdentifier;
99 idToken.string = NewPoolTString(intermediate.implicitThisName);
100 return true;
101 }
102
103 // type that can be used as IDENTIFIER
104
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700105 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
106 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
107 // valid identifier, nor is "linear". This code special cases the known instances of this, so
108 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -0700109
John Kessenich0320d092017-06-13 22:22:52 -0600110 const char* idString = getTypeString(peek());
111 if (idString == nullptr)
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700112 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700113
John Kessenich0320d092017-06-13 22:22:52 -0600114 token.string = NewPoolTString(idString);
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700115 token.tokenClass = EHTokIdentifier;
John Kessenich0320d092017-06-13 22:22:52 -0600116 idToken = token;
117 typeIdentifiers = true;
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700118
119 advanceToken();
120
121 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600122}
123
John Kesseniche01a9bc2016-03-12 20:11:22 -0700124// compilationUnit
John Kessenich8f9fdc92017-03-30 16:22:26 -0600125// : declaration_list EOF
John Kesseniche01a9bc2016-03-12 20:11:22 -0700126//
127bool HlslGrammar::acceptCompilationUnit()
128{
John Kessenichd016be12016-03-13 11:24:20 -0600129 TIntermNode* unitNode = nullptr;
130
John Kessenich8f9fdc92017-03-30 16:22:26 -0600131 if (! acceptDeclarationList(unitNode))
132 return false;
steve-lunargcb88de52016-08-03 07:04:18 -0600133
John Kessenich8f9fdc92017-03-30 16:22:26 -0600134 if (! peekTokenClass(EHTokNone))
135 return false;
John Kesseniche01a9bc2016-03-12 20:11:22 -0700136
John Kessenichd016be12016-03-13 11:24:20 -0600137 // set root of AST
John Kessenichca71d942017-03-07 20:44:09 -0700138 if (unitNode && !unitNode->getAsAggregate())
139 unitNode = intermediate.growAggregate(nullptr, unitNode);
John Kessenich078d7f22016-03-14 10:02:11 -0600140 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600141
John Kesseniche01a9bc2016-03-12 20:11:22 -0700142 return true;
143}
144
John Kessenich8f9fdc92017-03-30 16:22:26 -0600145// Recognize the following, but with the extra condition that it can be
146// successfully terminated by EOF or '}'.
147//
148// declaration_list
149// : list of declaration_or_semicolon followed by EOF or RIGHT_BRACE
150//
151// declaration_or_semicolon
152// : declaration
153// : SEMICOLON
154//
155bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList)
156{
157 do {
158 // HLSL allows extra semicolons between global declarations
159 do { } while (acceptTokenClass(EHTokSemicolon));
160
161 // EOF or RIGHT_BRACE
162 if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace))
163 return true;
164
165 // declaration
166 if (! acceptDeclaration(nodeList))
167 return false;
168 } while (true);
169
170 return true;
171}
172
LoopDawg4886f692016-06-29 10:58:58 -0600173// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700174// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600175//
176// sampler_state_assignment
177// : sampler_state_identifier EQUAL value SEMICOLON
178//
179// sampler_state_identifier
180// : ADDRESSU
181// | ADDRESSV
182// | ADDRESSW
183// | BORDERCOLOR
184// | FILTER
185// | MAXANISOTROPY
186// | MAXLOD
187// | MINLOD
188// | MIPLODBIAS
189//
190bool HlslGrammar::acceptSamplerState()
191{
192 // TODO: this should be genericized to accept a list of valid tokens and
193 // return token/value pairs. Presently it is specific to texture values.
194
195 if (! acceptTokenClass(EHTokLeftBrace))
196 return true;
197
198 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700199
LoopDawg4886f692016-06-29 10:58:58 -0600200 do {
201 // read state name
202 HlslToken state;
203 if (! acceptIdentifier(state))
204 break; // end of list
205
206 // FXC accepts any case
207 TString stateName = *state.string;
208 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
209
210 if (! acceptTokenClass(EHTokAssign)) {
211 expected("assign");
212 return false;
213 }
214
215 if (stateName == "minlod" || stateName == "maxlod") {
216 if (! peekTokenClass(EHTokIntConstant)) {
217 expected("integer");
218 return false;
219 }
220
221 TIntermTyped* lod = nullptr;
222 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
223 return false;
224 } else if (stateName == "maxanisotropy") {
225 if (! peekTokenClass(EHTokIntConstant)) {
226 expected("integer");
227 return false;
228 }
229
230 TIntermTyped* maxAnisotropy = nullptr;
231 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
232 return false;
233 } else if (stateName == "filter") {
234 HlslToken filterMode;
235 if (! acceptIdentifier(filterMode)) {
236 expected("filter mode");
237 return false;
238 }
239 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
240 HlslToken addrMode;
241 if (! acceptIdentifier(addrMode)) {
242 expected("texture address mode");
243 return false;
244 }
245 } else if (stateName == "miplodbias") {
246 TIntermTyped* lodBias = nullptr;
247 if (! acceptLiteral(lodBias)) {
248 expected("lod bias");
249 return false;
250 }
251 } else if (stateName == "bordercolor") {
252 return false;
253 } else {
254 expected("texture state");
255 return false;
256 }
257
258 // SEMICOLON
259 if (! acceptTokenClass(EHTokSemicolon)) {
260 expected("semicolon");
261 return false;
262 }
263 } while (true);
264
265 if (! acceptTokenClass(EHTokRightBrace))
266 return false;
267
268 return true;
269}
270
271// sampler_declaration_dx9
272// : SAMPLER identifier EQUAL sampler_type sampler_state
273//
John Kesseniche4821e42016-07-16 10:19:43 -0600274bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600275{
276 if (! acceptTokenClass(EHTokSampler))
277 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700278
LoopDawg4886f692016-06-29 10:58:58 -0600279 // TODO: remove this when DX9 style declarations are implemented.
280 unimplemented("Direct3D 9 sampler declaration");
281
282 // read sampler name
283 HlslToken name;
284 if (! acceptIdentifier(name)) {
285 expected("sampler name");
286 return false;
287 }
288
289 if (! acceptTokenClass(EHTokAssign)) {
290 expected("=");
291 return false;
292 }
293
294 return false;
295}
296
John Kesseniche01a9bc2016-03-12 20:11:22 -0700297// declaration
John Kessenich77ea30b2017-09-30 14:34:50 -0600298// : attributes attributed_declaration
299// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
300//
301// attributed_declaration
LoopDawg4886f692016-06-29 10:58:58 -0600302// : sampler_declaration_dx9 post_decls SEMICOLON
John Kessenich054378d2017-06-19 15:13:26 -0600303// | fully_specified_type // for cbuffer/tbuffer
304// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer
John Kessenich630dd7d2016-06-12 23:52:12 -0600305// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600306// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600307// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700308//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600309// declarator_list
310// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600311//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600312// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600313// : identifier array_specifier post_decls
314// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600315// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600316//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600317// Parsing has to go pretty far in to know whether it's a variable, prototype, or
318// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600319// as above. (The 'identifier' in the first item in init_declarator list is the
320// same as 'identifier' for function declarations.)
321//
John Kessenichca71d942017-03-07 20:44:09 -0700322// This can generate more than one subtree, one per initializer or a function body.
323// All initializer subtrees are put in their own aggregate node, making one top-level
324// node for all the initializers. Each function created is a top-level node to grow
325// into the passed-in nodeList.
John Kessenichd016be12016-03-13 11:24:20 -0600326//
John Kessenichca71d942017-03-07 20:44:09 -0700327// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
328// each top-level node the declaration creates. Otherwise, if only one top-level
329// node in generated here, that is want is returned in nodeList.
John Kessenich02467d82017-01-19 15:41:47 -0700330//
John Kessenichca71d942017-03-07 20:44:09 -0700331bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700332{
John Kessenich8f9fdc92017-03-30 16:22:26 -0600333 // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
334 if (acceptTokenClass(EHTokNamespace)) {
335 HlslToken namespaceToken;
336 if (!acceptIdentifier(namespaceToken)) {
337 expected("namespace name");
338 return false;
339 }
340 parseContext.pushNamespace(*namespaceToken.string);
341 if (!acceptTokenClass(EHTokLeftBrace)) {
342 expected("{");
343 return false;
344 }
345 if (!acceptDeclarationList(nodeList)) {
346 expected("declaration list");
347 return false;
348 }
349 if (!acceptTokenClass(EHTokRightBrace)) {
350 expected("}");
351 return false;
352 }
353 parseContext.popNamespace();
354 return true;
355 }
356
John Kessenich54ee28f2017-03-11 14:13:00 -0700357 bool declarator_list = false; // true when processing comma separation
John Kessenichd016be12016-03-13 11:24:20 -0600358
steve-lunarg1868b142016-10-20 13:07:10 -0600359 // attributes
John Kessenich088d52b2017-03-11 17:55:28 -0700360 TFunctionDeclarator declarator;
361 acceptAttributes(declarator.attributes);
steve-lunarg1868b142016-10-20 13:07:10 -0600362
John Kessenich5e69ec62016-07-05 00:02:40 -0600363 // typedef
364 bool typedefDecl = acceptTokenClass(EHTokTypedef);
365
John Kesseniche82061d2016-09-27 14:38:57 -0600366 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600367
368 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600369 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
370 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
371 // HLSL shaders, this will have to be a master level switch
372 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700373 // For that reason, this line is commented out
John Kessenichca71d942017-03-07 20:44:09 -0700374 // if (acceptSamplerDeclarationDX9(declaredType))
375 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600376
John Kessenich2fcdd642017-06-19 15:41:11 -0600377 bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer));
LoopDawg4886f692016-06-29 10:58:58 -0600378 // fully_specified_type
John Kessenich132cf532018-01-02 11:27:54 -0700379 if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes, forbidDeclarators))
John Kessenich87142c72016-03-12 20:24:24 -0700380 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600381
John Kessenich2fcdd642017-06-19 15:41:11 -0600382 // cbuffer and tbuffer end with the closing '}'.
383 // No semicolon is included.
384 if (forbidDeclarators)
385 return true;
386
John Kessenich054378d2017-06-19 15:13:26 -0600387 // declarator_list
388 // : declarator
389 // : identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600390 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700391 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600392 while (acceptIdentifier(idToken)) {
John Kessenich9855bda2017-09-11 21:48:19 -0600393 TString *fullName = idToken.string;
John Kessenich8f9fdc92017-03-30 16:22:26 -0600394 if (parseContext.symbolTable.atGlobalLevel())
395 parseContext.getFullNamespaceName(fullName);
John Kessenich78388722017-03-08 18:53:51 -0700396 if (peekTokenClass(EHTokLeftParen)) {
397 // looks like function parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600398
John Kessenich78388722017-03-08 18:53:51 -0700399 // Potentially rename shader entry point function. No-op most of the time.
John Kessenich8f9fdc92017-03-30 16:22:26 -0600400 parseContext.renameShaderFunction(fullName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600401
John Kessenich78388722017-03-08 18:53:51 -0700402 // function_parameters
John Kessenich8f9fdc92017-03-30 16:22:26 -0600403 declarator.function = new TFunction(fullName, declaredType);
John Kessenich088d52b2017-03-11 17:55:28 -0700404 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700405 expected("function parameter list");
406 return false;
407 }
408
John Kessenich630dd7d2016-06-12 23:52:12 -0600409 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700410 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600411
John Kessenichd5ed0b62016-07-04 17:32:45 -0600412 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700413 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600414 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700415 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600416 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600417 if (typedefDecl)
418 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700419 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600420 } else {
421 if (typedefDecl)
422 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700423 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600424 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600425 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600426 // A variable declaration. Fix the storage qualifier if it's a global.
427 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
428 declaredType.getQualifier().storage = EvqUniform;
429
John Kessenichecba76f2017-01-06 00:34:48 -0700430 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600431 // the number of types can expand when arrayness is different.
432 TType variableType;
433 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600434
John Kesseniche82061d2016-09-27 14:38:57 -0600435 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600436 TArraySizes* arraySizes = nullptr;
437 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600438
John Kesseniche82061d2016-09-27 14:38:57 -0600439 // Fix arrayness in the variableType
440 if (declaredType.isImplicitlySizedArray()) {
441 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
442 // of different sizes, for this case sharing the shallow copy of arrayness
443 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
444 variableType.newArraySizes(declaredType.getArraySizes());
445 }
446 if (arraySizes || variableType.isArray()) {
447 // In the most general case, arrayness is potentially coming both from the
448 // declared type and from the variable: "int[] a[];" or just one or the other.
449 // Merge it all to the variableType, so all arrayness is part of the variableType.
450 parseContext.arrayDimMerge(variableType, arraySizes);
451 }
452
LoopDawg4886f692016-06-29 10:58:58 -0600453 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600454 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600455 if (! acceptSamplerState())
456 return false;
457 }
458
John Kessenichd5ed0b62016-07-04 17:32:45 -0600459 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600460 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600461
462 // EQUAL assignment_expression
463 TIntermTyped* expressionNode = nullptr;
464 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600465 if (typedefDecl)
466 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600467 if (! acceptAssignmentExpression(expressionNode)) {
468 expected("initializer");
469 return false;
470 }
471 }
472
John Kessenich6dbc0a72016-09-27 19:13:05 -0600473 // TODO: things scoped within an annotation need their own name space;
474 // TODO: strings are not yet handled.
475 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
476 if (typedefDecl)
John Kessenich8f9fdc92017-03-30 16:22:26 -0600477 parseContext.declareTypedef(idToken.loc, *fullName, variableType);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600478 else if (variableType.getBasicType() == EbtBlock) {
John Kessenich8116cfc2017-12-09 04:42:42 -0700479 if (expressionNode)
480 parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", "");
steve-lunarga766b832017-04-25 09:30:28 -0600481 parseContext.declareBlock(idToken.loc, variableType, fullName,
482 variableType.isArray() ? &variableType.getArraySizes() : nullptr);
steve-lunarg8e26feb2017-04-10 08:19:21 -0600483 parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
484 } else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700485 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600486 // this isn't really an individual variable, but a member of the $Global buffer
John Kessenich8f9fdc92017-03-30 16:22:26 -0600487 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600488 } else {
489 // Declare the variable and add any initializer code to the AST.
490 // The top-level node is always made into an aggregate, as that's
491 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700492 initializers = intermediate.growAggregate(initializers,
John Kessenich8f9fdc92017-03-30 16:22:26 -0600493 parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
John Kessenichca71d942017-03-07 20:44:09 -0700494 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600495 }
496 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600497 }
John Kessenich5f934b02016-03-13 17:58:25 -0600498 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600499
John Kessenich054378d2017-06-19 15:13:26 -0600500 // COMMA
501 if (acceptTokenClass(EHTokComma))
John Kessenich54ee28f2017-03-11 14:13:00 -0700502 declarator_list = true;
John Kessenich2fcdd642017-06-19 15:41:11 -0600503 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600504
John Kessenichca71d942017-03-07 20:44:09 -0700505 // The top-level initializer node is a sequence.
506 if (initializers != nullptr)
507 initializers->setOperator(EOpSequence);
508
509 // Add the initializers' aggregate to the nodeList we were handed.
510 if (nodeList)
511 nodeList = intermediate.growAggregate(nodeList, initializers);
512 else
513 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700514
John Kessenich2fcdd642017-06-19 15:41:11 -0600515 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600516 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich2fcdd642017-06-19 15:41:11 -0600517 // This may have been a false detection of what appeared to be a declaration, but
518 // was actually an assignment such as "float = 4", where "float" is an identifier.
519 // We put the token back to let further parsing happen for cases where that may
520 // happen. This errors on the side of caution, and mostly triggers the error.
John Kessenich13075c62017-04-11 09:51:32 -0600521 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700522 recedeToken();
John Kessenich13075c62017-04-11 09:51:32 -0600523 return false;
John Kessenich13075c62017-04-11 09:51:32 -0600524 } else {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700525 expected(";");
John Kessenich13075c62017-04-11 09:51:32 -0600526 return false;
527 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600528 }
John Kessenichecba76f2017-01-06 00:34:48 -0700529
John Kesseniche01a9bc2016-03-12 20:11:22 -0700530 return true;
531}
532
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600533// control_declaration
534// : fully_specified_type identifier EQUAL expression
535//
536bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
537{
538 node = nullptr;
John Kessenich046bae02017-12-23 17:29:45 -0700539 TAttributeMap attributes;
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600540
541 // fully_specified_type
542 TType type;
John Kessenich046bae02017-12-23 17:29:45 -0700543 if (! acceptFullySpecifiedType(type, attributes))
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600544 return false;
545
John Kessenich057df292017-03-06 18:18:37 -0700546 // filter out type casts
547 if (peekTokenClass(EHTokLeftParen)) {
548 recedeToken();
549 return false;
550 }
551
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600552 // identifier
553 HlslToken idToken;
554 if (! acceptIdentifier(idToken)) {
555 expected("identifier");
556 return false;
557 }
558
559 // EQUAL
560 TIntermTyped* expressionNode = nullptr;
561 if (! acceptTokenClass(EHTokAssign)) {
562 expected("=");
563 return false;
564 }
565
566 // expression
567 if (! acceptExpression(expressionNode)) {
568 expected("initializer");
569 return false;
570 }
571
John Kesseniche82061d2016-09-27 14:38:57 -0600572 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600573
574 return true;
575}
576
John Kessenich87142c72016-03-12 20:24:24 -0700577// fully_specified_type
578// : type_specifier
579// | type_qualifier type_specifier
580//
John Kessenich046bae02017-12-23 17:29:45 -0700581bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
John Kessenich87142c72016-03-12 20:24:24 -0700582{
John Kessenich54ee28f2017-03-11 14:13:00 -0700583 TIntermNode* nodeList = nullptr;
John Kessenich046bae02017-12-23 17:29:45 -0700584 return acceptFullySpecifiedType(type, nodeList, attributes);
John Kessenich54ee28f2017-03-11 14:13:00 -0700585}
John Kessenich132cf532018-01-02 11:27:54 -0700586bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes, bool forbidDeclarators)
John Kessenich54ee28f2017-03-11 14:13:00 -0700587{
John Kessenich87142c72016-03-12 20:24:24 -0700588 // type_qualifier
589 TQualifier qualifier;
590 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600591 if (! acceptQualifier(qualifier))
592 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600593 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700594
595 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700596 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700597 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700598 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700599 // qualifier. Back it out, if we did.
600 if (qualifier.sample)
601 recedeToken();
602
John Kessenich87142c72016-03-12 20:24:24 -0700603 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700604 }
John Kessenich046bae02017-12-23 17:29:45 -0700605
John Kessenich3d157c52016-07-25 16:05:33 -0600606 if (type.getBasicType() == EbtBlock) {
607 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600608 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich046bae02017-12-23 17:29:45 -0700609
610 // merge in the attributes
611 parseContext.transferTypeAttributes(attributes, type);
612
John Kessenich3d157c52016-07-25 16:05:33 -0600613 // further, it can create an anonymous instance of the block
John Kessenich798d0052018-01-02 13:07:14 -0700614 // (cbuffer and tbuffer don't consume the next identifier, and
615 // should set forbidDeclarators)
John Kessenich132cf532018-01-02 11:27:54 -0700616 if (forbidDeclarators || peek() != EHTokIdentifier)
John Kessenich3d157c52016-07-25 16:05:33 -0600617 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600618 } else {
619 // Some qualifiers are set when parsing the type. Merge those with
620 // whatever comes from acceptQualifier.
621 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700622
steve-lunargbb0183f2016-10-04 16:58:14 -0600623 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600624 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700625
steve-lunarg08e0c082017-03-29 20:01:13 -0600626 if (type.getQualifier().storage == EvqOut ||
steve-lunarg5da1f032017-02-12 17:50:28 -0700627 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700628 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700629 qualifier.readonly = type.getQualifier().readonly;
630 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700631
John Kessenichecd08bc2017-08-07 23:40:05 -0600632 if (type.isBuiltIn())
steve-lunarg08e0c082017-03-29 20:01:13 -0600633 qualifier.builtIn = type.getQualifier().builtIn;
634
John Kessenich046bae02017-12-23 17:29:45 -0700635 type.getQualifier() = qualifier;
636
637 // merge in the attributes
638 parseContext.transferTypeAttributes(attributes, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600639 }
John Kessenich87142c72016-03-12 20:24:24 -0700640
641 return true;
642}
643
John Kessenich630dd7d2016-06-12 23:52:12 -0600644// type_qualifier
645// : qualifier qualifier ...
646//
647// Zero or more of these, so this can't return false.
648//
John Kessenichb9e39122016-08-17 10:22:08 -0600649bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700650{
John Kessenich630dd7d2016-06-12 23:52:12 -0600651 do {
652 switch (peek()) {
653 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600654 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600655 break;
656 case EHTokExtern:
657 // TODO: no meaning in glslang?
658 break;
659 case EHTokShared:
660 // TODO: hint
661 break;
662 case EHTokGroupShared:
663 qualifier.storage = EvqShared;
664 break;
665 case EHTokUniform:
666 qualifier.storage = EvqUniform;
667 break;
668 case EHTokConst:
669 qualifier.storage = EvqConst;
670 break;
671 case EHTokVolatile:
672 qualifier.volatil = true;
673 break;
674 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600675 qualifier.smooth = true;
676 break;
677 case EHTokCentroid:
678 qualifier.centroid = true;
679 break;
680 case EHTokNointerpolation:
681 qualifier.flat = true;
682 break;
683 case EHTokNoperspective:
684 qualifier.nopersp = true;
685 break;
686 case EHTokSample:
687 qualifier.sample = true;
688 break;
689 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600690 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600691 break;
692 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600693 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600694 break;
695 case EHTokPrecise:
696 qualifier.noContraction = true;
697 break;
LoopDawg9249c702016-07-12 20:44:32 -0600698 case EHTokIn:
xavierb1d97532017-06-20 07:49:22 +0200699 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
LoopDawg9249c702016-07-12 20:44:32 -0600700 break;
701 case EHTokOut:
xavierb1d97532017-06-20 07:49:22 +0200702 qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
LoopDawg9249c702016-07-12 20:44:32 -0600703 break;
704 case EHTokInOut:
705 qualifier.storage = EvqInOut;
706 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600707 case EHTokLayout:
708 if (! acceptLayoutQualifierList(qualifier))
709 return false;
710 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700711 case EHTokGloballyCoherent:
712 qualifier.coherent = true;
713 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600714 case EHTokInline:
715 // TODO: map this to SPIR-V function control
716 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700717
718 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
719 // for output variables.
720 case EHTokPoint:
721 qualifier.storage = EvqIn;
722 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
723 return false;
724 break;
725 case EHTokLine:
726 qualifier.storage = EvqIn;
727 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
728 return false;
729 break;
730 case EHTokTriangle:
731 qualifier.storage = EvqIn;
732 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
733 return false;
734 break;
735 case EHTokLineAdj:
736 qualifier.storage = EvqIn;
737 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
738 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700739 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700740 case EHTokTriangleAdj:
741 qualifier.storage = EvqIn;
742 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
743 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700744 break;
745
John Kessenich630dd7d2016-06-12 23:52:12 -0600746 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600747 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600748 }
749 advanceToken();
750 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700751}
752
John Kessenichb9e39122016-08-17 10:22:08 -0600753// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600754// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600755//
756// layout_qualifier
757// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600758// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600759//
760// Zero or more of these, so this can't return false.
761//
762bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
763{
764 if (! acceptTokenClass(EHTokLayout))
765 return false;
766
767 // LEFT_PAREN
768 if (! acceptTokenClass(EHTokLeftParen))
769 return false;
770
771 do {
772 // identifier
773 HlslToken idToken;
774 if (! acceptIdentifier(idToken))
775 break;
776
777 // EQUAL expression
778 if (acceptTokenClass(EHTokAssign)) {
779 TIntermTyped* expr;
780 if (! acceptConditionalExpression(expr)) {
781 expected("expression");
782 return false;
783 }
784 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
785 } else
786 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
787
788 // COMMA
789 if (! acceptTokenClass(EHTokComma))
790 break;
791 } while (true);
792
793 // RIGHT_PAREN
794 if (! acceptTokenClass(EHTokRightParen)) {
795 expected(")");
796 return false;
797 }
798
799 return true;
800}
801
LoopDawg6daaa4f2016-06-23 19:13:48 -0600802// template_type
803// : FLOAT
804// | DOUBLE
805// | INT
806// | DWORD
807// | UINT
808// | BOOL
809//
steve-lunargf49cdf42016-11-17 15:04:20 -0700810bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600811{
812 switch (peek()) {
813 case EHTokFloat:
814 basicType = EbtFloat;
815 break;
816 case EHTokDouble:
817 basicType = EbtDouble;
818 break;
819 case EHTokInt:
820 case EHTokDword:
821 basicType = EbtInt;
822 break;
823 case EHTokUint:
824 basicType = EbtUint;
825 break;
826 case EHTokBool:
827 basicType = EbtBool;
828 break;
829 default:
830 return false;
831 }
832
833 advanceToken();
834
835 return true;
836}
837
838// vector_template_type
839// : VECTOR
840// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
841//
842bool HlslGrammar::acceptVectorTemplateType(TType& type)
843{
844 if (! acceptTokenClass(EHTokVector))
845 return false;
846
847 if (! acceptTokenClass(EHTokLeftAngle)) {
848 // in HLSL, 'vector' alone means float4.
849 new(&type) TType(EbtFloat, EvqTemporary, 4);
850 return true;
851 }
852
853 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700854 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600855 expected("scalar type");
856 return false;
857 }
858
859 // COMMA
860 if (! acceptTokenClass(EHTokComma)) {
861 expected(",");
862 return false;
863 }
864
865 // integer
866 if (! peekTokenClass(EHTokIntConstant)) {
867 expected("literal integer");
868 return false;
869 }
870
871 TIntermTyped* vecSize;
872 if (! acceptLiteral(vecSize))
873 return false;
874
875 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
876
877 new(&type) TType(basicType, EvqTemporary, vecSizeI);
878
879 if (vecSizeI == 1)
880 type.makeVector();
881
882 if (!acceptTokenClass(EHTokRightAngle)) {
883 expected("right angle bracket");
884 return false;
885 }
886
887 return true;
888}
889
890// matrix_template_type
891// : MATRIX
892// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
893//
894bool HlslGrammar::acceptMatrixTemplateType(TType& type)
895{
896 if (! acceptTokenClass(EHTokMatrix))
897 return false;
898
899 if (! acceptTokenClass(EHTokLeftAngle)) {
900 // in HLSL, 'matrix' alone means float4x4.
901 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
902 return true;
903 }
904
905 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700906 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600907 expected("scalar type");
908 return false;
909 }
910
911 // COMMA
912 if (! acceptTokenClass(EHTokComma)) {
913 expected(",");
914 return false;
915 }
916
917 // integer rows
918 if (! peekTokenClass(EHTokIntConstant)) {
919 expected("literal integer");
920 return false;
921 }
922
923 TIntermTyped* rows;
924 if (! acceptLiteral(rows))
925 return false;
926
927 // COMMA
928 if (! acceptTokenClass(EHTokComma)) {
929 expected(",");
930 return false;
931 }
John Kessenichecba76f2017-01-06 00:34:48 -0700932
LoopDawg6daaa4f2016-06-23 19:13:48 -0600933 // integer cols
934 if (! peekTokenClass(EHTokIntConstant)) {
935 expected("literal integer");
936 return false;
937 }
938
939 TIntermTyped* cols;
940 if (! acceptLiteral(cols))
941 return false;
942
943 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600944 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
945 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600946
947 if (!acceptTokenClass(EHTokRightAngle)) {
948 expected("right angle bracket");
949 return false;
950 }
951
952 return true;
953}
954
steve-lunargf49cdf42016-11-17 15:04:20 -0700955// layout_geometry
956// : LINESTREAM
957// | POINTSTREAM
958// | TRIANGLESTREAM
959//
960bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
961{
962 // read geometry type
963 const EHlslTokenClass geometryType = peek();
964
965 switch (geometryType) {
966 case EHTokPointStream: geometry = ElgPoints; break;
967 case EHTokLineStream: geometry = ElgLineStrip; break;
968 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
969 default:
970 return false; // not a layout geometry
971 }
972
973 advanceToken(); // consume the layout keyword
974 return true;
975}
976
steve-lunarg858c9282017-01-07 08:54:10 -0700977// tessellation_decl_type
978// : INPUTPATCH
979// | OUTPUTPATCH
980//
steve-lunarg067eb9b2017-04-01 15:34:48 -0600981bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
steve-lunarg858c9282017-01-07 08:54:10 -0700982{
983 // read geometry type
984 const EHlslTokenClass tessType = peek();
985
986 switch (tessType) {
steve-lunarg067eb9b2017-04-01 15:34:48 -0600987 case EHTokInputPatch: patchType = EbvInputPatch; break;
988 case EHTokOutputPatch: patchType = EbvOutputPatch; break;
steve-lunarg858c9282017-01-07 08:54:10 -0700989 default:
990 return false; // not a tessellation decl
991 }
992
993 advanceToken(); // consume the keyword
994 return true;
995}
996
997// tessellation_patch_template_type
998// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
999//
1000bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
1001{
steve-lunarg067eb9b2017-04-01 15:34:48 -06001002 TBuiltInVariable patchType;
1003
1004 if (! acceptTessellationDeclType(patchType))
steve-lunarg858c9282017-01-07 08:54:10 -07001005 return false;
1006
1007 if (! acceptTokenClass(EHTokLeftAngle))
1008 return false;
1009
1010 if (! acceptType(type)) {
1011 expected("tessellation patch type");
1012 return false;
1013 }
1014
1015 if (! acceptTokenClass(EHTokComma))
1016 return false;
1017
1018 // integer size
1019 if (! peekTokenClass(EHTokIntConstant)) {
1020 expected("literal integer");
1021 return false;
1022 }
1023
1024 TIntermTyped* size;
1025 if (! acceptLiteral(size))
1026 return false;
1027
1028 TArraySizes* arraySizes = new TArraySizes;
1029 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1030 type.newArraySizes(*arraySizes);
steve-lunarg067eb9b2017-04-01 15:34:48 -06001031 type.getQualifier().builtIn = patchType;
steve-lunarg858c9282017-01-07 08:54:10 -07001032
1033 if (! acceptTokenClass(EHTokRightAngle)) {
1034 expected("right angle bracket");
1035 return false;
1036 }
1037
1038 return true;
1039}
1040
steve-lunargf49cdf42016-11-17 15:04:20 -07001041// stream_out_template_type
1042// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1043//
1044bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1045{
1046 geometry = ElgNone;
1047
1048 if (! acceptOutputPrimitiveGeometry(geometry))
1049 return false;
1050
1051 if (! acceptTokenClass(EHTokLeftAngle))
1052 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001053
steve-lunargf49cdf42016-11-17 15:04:20 -07001054 if (! acceptType(type)) {
1055 expected("stream output type");
1056 return false;
1057 }
1058
steve-lunarg08e0c082017-03-29 20:01:13 -06001059 type.getQualifier().storage = EvqOut;
1060 type.getQualifier().builtIn = EbvGsOutputStream;
steve-lunargf49cdf42016-11-17 15:04:20 -07001061
1062 if (! acceptTokenClass(EHTokRightAngle)) {
1063 expected("right angle bracket");
1064 return false;
1065 }
1066
1067 return true;
1068}
John Kessenichecba76f2017-01-06 00:34:48 -07001069
John Kessenicha1e2d492016-09-20 13:22:58 -06001070// annotations
1071// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001072//
John Kessenicha1e2d492016-09-20 13:22:58 -06001073bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001074{
John Kessenicha1e2d492016-09-20 13:22:58 -06001075 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001076 return false;
1077
John Kessenicha1e2d492016-09-20 13:22:58 -06001078 // note that we are nesting a name space
1079 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001080
1081 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1082 do {
1083 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1084 while (acceptTokenClass(EHTokSemicolon))
1085 ;
1086
1087 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001088 break;
John Kessenich86f71382016-09-19 20:23:18 -06001089
1090 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001091 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001092 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001093 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001094 return false;
1095 }
1096 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001097
1098 parseContext.unnestAnnotations();
1099 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001100}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001101
LoopDawg7f93d562017-09-27 09:04:43 -06001102// subpass input type
1103// : SUBPASSINPUT
1104// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1105// | SUBPASSINPUTMS
1106// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1107bool HlslGrammar::acceptSubpassInputType(TType& type)
1108{
1109 // read subpass type
1110 const EHlslTokenClass subpassInputType = peek();
1111
1112 bool multisample;
1113
1114 switch (subpassInputType) {
1115 case EHTokSubpassInput: multisample = false; break;
1116 case EHTokSubpassInputMS: multisample = true; break;
1117 default:
1118 return false; // not a subpass input declaration
1119 }
1120
1121 advanceToken(); // consume the sampler type keyword
1122
1123 TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
1124
1125 if (acceptTokenClass(EHTokLeftAngle)) {
1126 if (! acceptType(subpassType)) {
1127 expected("scalar or vector type");
1128 return false;
1129 }
1130
1131 const TBasicType basicRetType = subpassType.getBasicType() ;
1132
1133 switch (basicRetType) {
1134 case EbtFloat:
1135 case EbtUint:
1136 case EbtInt:
1137 case EbtStruct:
1138 break;
1139 default:
1140 unimplemented("basic type in subpass input");
1141 return false;
1142 }
1143
1144 if (! acceptTokenClass(EHTokRightAngle)) {
1145 expected("right angle bracket");
1146 return false;
1147 }
1148 }
1149
1150 const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
1151 : subpassType.getBasicType();
1152
1153 TSampler sampler;
1154 sampler.setSubpass(subpassBasicType, multisample);
1155
1156 // Remember the declared return type. Function returns false on error.
1157 if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
1158 return false;
1159
1160 type.shallowCopy(TType(sampler, EvqUniform));
1161
1162 return true;
1163}
1164
LoopDawg4886f692016-06-29 10:58:58 -06001165// sampler_type
1166// : SAMPLER
1167// | SAMPLER1D
1168// | SAMPLER2D
1169// | SAMPLER3D
1170// | SAMPLERCUBE
1171// | SAMPLERSTATE
1172// | SAMPLERCOMPARISONSTATE
1173bool HlslGrammar::acceptSamplerType(TType& type)
1174{
1175 // read sampler type
1176 const EHlslTokenClass samplerType = peek();
1177
LoopDawga78b0292016-07-19 14:28:05 -06001178 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001179 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001180
LoopDawga78b0292016-07-19 14:28:05 -06001181 bool isShadow = false;
1182
LoopDawg4886f692016-06-29 10:58:58 -06001183 switch (samplerType) {
1184 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001185 case EHTokSampler1d: /*dim = Esd1D*/; break;
1186 case EHTokSampler2d: /*dim = Esd2D*/; break;
1187 case EHTokSampler3d: /*dim = Esd3D*/; break;
1188 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001189 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001190 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001191 default:
1192 return false; // not a sampler declaration
1193 }
1194
1195 advanceToken(); // consume the sampler type keyword
1196
1197 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001198
1199 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001200 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001201
1202 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1203
1204 return true;
1205}
1206
1207// texture_type
1208// | BUFFER
1209// | TEXTURE1D
1210// | TEXTURE1DARRAY
1211// | TEXTURE2D
1212// | TEXTURE2DARRAY
1213// | TEXTURE3D
1214// | TEXTURECUBE
1215// | TEXTURECUBEARRAY
1216// | TEXTURE2DMS
1217// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001218// | RWBUFFER
1219// | RWTEXTURE1D
1220// | RWTEXTURE1DARRAY
1221// | RWTEXTURE2D
1222// | RWTEXTURE2DARRAY
1223// | RWTEXTURE3D
1224
LoopDawg4886f692016-06-29 10:58:58 -06001225bool HlslGrammar::acceptTextureType(TType& type)
1226{
1227 const EHlslTokenClass textureType = peek();
1228
1229 TSamplerDim dim = EsdNone;
1230 bool array = false;
1231 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001232 bool image = false;
steve-lunargbf1537f2017-03-31 17:40:09 -06001233 bool combined = true;
LoopDawg4886f692016-06-29 10:58:58 -06001234
1235 switch (textureType) {
steve-lunargbf1537f2017-03-31 17:40:09 -06001236 case EHTokBuffer: dim = EsdBuffer; combined = false; break;
John Kessenichf36542f2017-03-31 14:39:30 -06001237 case EHTokTexture1d: dim = Esd1D; break;
1238 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1239 case EHTokTexture2d: dim = Esd2D; break;
1240 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1241 case EHTokTexture3d: dim = Esd3D; break;
1242 case EHTokTextureCube: dim = EsdCube; break;
1243 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1244 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1245 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1246 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1247 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1248 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1249 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1250 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1251 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001252 default:
1253 return false; // not a texture declaration
1254 }
1255
1256 advanceToken(); // consume the texture object keyword
1257
1258 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001259
LoopDawg4886f692016-06-29 10:58:58 -06001260 TIntermTyped* msCount = nullptr;
1261
steve-lunargbb0183f2016-10-04 16:58:14 -06001262 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001263 if (acceptTokenClass(EHTokLeftAngle)) {
1264 if (! acceptType(txType)) {
1265 expected("scalar or vector type");
1266 return false;
1267 }
1268
1269 const TBasicType basicRetType = txType.getBasicType() ;
1270
LoopDawg5ee05892017-07-31 13:41:42 -06001271 switch (basicRetType) {
1272 case EbtFloat:
1273 case EbtUint:
1274 case EbtInt:
1275 case EbtStruct:
1276 break;
1277 default:
LoopDawg4886f692016-06-29 10:58:58 -06001278 unimplemented("basic type in texture");
1279 return false;
1280 }
1281
steve-lunargd53f7172016-07-27 15:46:48 -06001282 // Buffers can handle small mats if they fit in 4 components
1283 if (dim == EsdBuffer && txType.isMatrix()) {
1284 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1285 expected("components < 4 in matrix buffer type");
1286 return false;
1287 }
1288
1289 // TODO: except we don't handle it yet...
1290 unimplemented("matrix type in buffer");
1291 return false;
1292 }
1293
LoopDawg5ee05892017-07-31 13:41:42 -06001294 if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
1295 expected("scalar, vector, or struct type");
LoopDawg4886f692016-06-29 10:58:58 -06001296 return false;
1297 }
1298
LoopDawg4886f692016-06-29 10:58:58 -06001299 if (ms && acceptTokenClass(EHTokComma)) {
1300 // read sample count for multisample types, if given
1301 if (! peekTokenClass(EHTokIntConstant)) {
1302 expected("multisample count");
1303 return false;
1304 }
1305
1306 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1307 return false;
1308 }
1309
1310 if (! acceptTokenClass(EHTokRightAngle)) {
1311 expected("right angle bracket");
1312 return false;
1313 }
1314 } else if (ms) {
1315 expected("texture type for multisample");
1316 return false;
John Kessenichf36542f2017-03-31 14:39:30 -06001317 } else if (image) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001318 expected("type for RWTexture/RWBuffer");
1319 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001320 }
1321
1322 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001323 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001324
1325 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001326 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001327
steve-lunarg4f2da272016-10-10 15:24:57 -06001328 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1329 if (image || dim == EsdBuffer)
1330 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001331
LoopDawg5ee05892017-07-31 13:41:42 -06001332 const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
1333 : txType.getBasicType();
1334
steve-lunargbb0183f2016-10-04 16:58:14 -06001335 // Non-image Buffers are combined
1336 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001337 sampler.set(txType.getBasicType(), dim, array);
1338 } else {
1339 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001340 if (image) {
LoopDawg5ee05892017-07-31 13:41:42 -06001341 sampler.setImage(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001342 } else {
LoopDawg5ee05892017-07-31 13:41:42 -06001343 sampler.setTexture(txBasicType, dim, array, shadow, ms);
steve-lunargbb0183f2016-10-04 16:58:14 -06001344 }
steve-lunargd53f7172016-07-27 15:46:48 -06001345 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001346
LoopDawg5ee05892017-07-31 13:41:42 -06001347 // Remember the declared return type. Function returns false on error.
1348 if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1349 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001350
steve-lunargbf1537f2017-03-31 17:40:09 -06001351 // Force uncombined, if necessary
1352 if (!combined)
1353 sampler.combined = false;
1354
LoopDawg4886f692016-06-29 10:58:58 -06001355 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001356 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001357
1358 return true;
1359}
1360
John Kessenich87142c72016-03-12 20:24:24 -07001361// If token is for a type, update 'type' with the type information,
1362// and return true and advance.
1363// Otherwise, return false, and don't advance
1364bool HlslGrammar::acceptType(TType& type)
1365{
John Kessenich54ee28f2017-03-11 14:13:00 -07001366 TIntermNode* nodeList = nullptr;
1367 return acceptType(type, nodeList);
1368}
1369bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1370{
steve-lunarg3226b082016-10-26 19:18:55 -06001371 // Basic types for min* types, broken out here in case of future
1372 // changes, e.g, to use native halfs.
1373 static const TBasicType min16float_bt = EbtFloat;
1374 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001375 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001376 static const TBasicType min16int_bt = EbtInt;
1377 static const TBasicType min12int_bt = EbtInt;
1378 static const TBasicType min16uint_bt = EbtUint;
1379
John Kessenich0320d092017-06-13 22:22:52 -06001380 // Some types might have turned into identifiers. Take the hit for checking
1381 // when this has happened.
1382 if (typeIdentifiers) {
1383 const char* identifierString = getTypeString(peek());
1384 if (identifierString != nullptr) {
1385 TString name = identifierString;
1386 // if it's an identifier, it's not a type
1387 if (parseContext.symbolTable.find(name) != nullptr)
1388 return false;
1389 }
1390 }
1391
LoopDawgfa39cff2017-11-14 14:55:40 -07001392 bool isUnorm = false;
1393 bool isSnorm = false;
1394
1395 // Accept snorm and unorm. Presently, this is ignored, save for an error check below.
1396 switch (peek()) {
1397 case EHTokUnorm:
1398 isUnorm = true;
1399 advanceToken(); // eat the token
1400 break;
1401 case EHTokSNorm:
1402 isSnorm = true;
1403 advanceToken(); // eat the token
1404 break;
1405 default:
1406 break;
1407 }
1408
John Kessenich9c86c6a2016-05-03 22:49:24 -06001409 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001410 case EHTokVector:
1411 return acceptVectorTemplateType(type);
1412 break;
1413
1414 case EHTokMatrix:
1415 return acceptMatrixTemplateType(type);
1416 break;
1417
steve-lunargf49cdf42016-11-17 15:04:20 -07001418 case EHTokPointStream: // fall through
1419 case EHTokLineStream: // ...
1420 case EHTokTriangleStream: // ...
1421 {
1422 TLayoutGeometry geometry;
1423 if (! acceptStreamOutTemplateType(type, geometry))
1424 return false;
1425
1426 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1427 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001428
steve-lunargf49cdf42016-11-17 15:04:20 -07001429 return true;
1430 }
1431
steve-lunarg858c9282017-01-07 08:54:10 -07001432 case EHTokInputPatch: // fall through
1433 case EHTokOutputPatch: // ...
1434 {
1435 if (! acceptTessellationPatchTemplateType(type))
1436 return false;
1437
1438 return true;
1439 }
1440
LoopDawg4886f692016-06-29 10:58:58 -06001441 case EHTokSampler: // fall through
1442 case EHTokSampler1d: // ...
1443 case EHTokSampler2d: // ...
1444 case EHTokSampler3d: // ...
1445 case EHTokSamplerCube: // ...
1446 case EHTokSamplerState: // ...
1447 case EHTokSamplerComparisonState: // ...
1448 return acceptSamplerType(type);
1449 break;
1450
LoopDawg7f93d562017-09-27 09:04:43 -06001451 case EHTokSubpassInput: // fall through
1452 case EHTokSubpassInputMS: // ...
1453 return acceptSubpassInputType(type);
1454 break;
1455
LoopDawg4886f692016-06-29 10:58:58 -06001456 case EHTokBuffer: // fall through
1457 case EHTokTexture1d: // ...
1458 case EHTokTexture1darray: // ...
1459 case EHTokTexture2d: // ...
1460 case EHTokTexture2darray: // ...
1461 case EHTokTexture3d: // ...
1462 case EHTokTextureCube: // ...
1463 case EHTokTextureCubearray: // ...
1464 case EHTokTexture2DMS: // ...
1465 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001466 case EHTokRWTexture1d: // ...
1467 case EHTokRWTexture1darray: // ...
1468 case EHTokRWTexture2d: // ...
1469 case EHTokRWTexture2darray: // ...
1470 case EHTokRWTexture3d: // ...
1471 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001472 return acceptTextureType(type);
1473 break;
1474
steve-lunarg5da1f032017-02-12 17:50:28 -07001475 case EHTokAppendStructuredBuffer:
1476 case EHTokByteAddressBuffer:
1477 case EHTokConsumeStructuredBuffer:
1478 case EHTokRWByteAddressBuffer:
1479 case EHTokRWStructuredBuffer:
1480 case EHTokStructuredBuffer:
1481 return acceptStructBufferType(type);
1482 break;
1483
LoopDawge5530b92017-11-08 19:48:11 -07001484 case EHTokTextureBuffer:
1485 return acceptTextureBufferType(type);
1486 break;
1487
steve-lunarga766b832017-04-25 09:30:28 -06001488 case EHTokConstantBuffer:
1489 return acceptConstantBufferType(type);
1490
John Kessenich27ffb292017-03-03 17:01:01 -07001491 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001492 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001493 case EHTokCBuffer:
1494 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001495 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001496
1497 case EHTokIdentifier:
1498 // An identifier could be for a user-defined type.
1499 // Note we cache the symbol table lookup, to save for a later rule
1500 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001501 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001502 advanceToken();
1503 return true;
1504 } else
1505 return false;
1506
John Kessenich71351de2016-06-08 12:50:56 -06001507 case EHTokVoid:
1508 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001509 break;
John Kessenich71351de2016-06-08 12:50:56 -06001510
John Kessenicha1e2d492016-09-20 13:22:58 -06001511 case EHTokString:
1512 new(&type) TType(EbtString);
1513 break;
1514
John Kessenich87142c72016-03-12 20:24:24 -07001515 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001516 new(&type) TType(EbtFloat);
1517 break;
John Kessenich87142c72016-03-12 20:24:24 -07001518 case EHTokFloat1:
1519 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001520 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001521 break;
John Kessenich87142c72016-03-12 20:24:24 -07001522 case EHTokFloat2:
1523 new(&type) TType(EbtFloat, EvqTemporary, 2);
1524 break;
1525 case EHTokFloat3:
1526 new(&type) TType(EbtFloat, EvqTemporary, 3);
1527 break;
1528 case EHTokFloat4:
1529 new(&type) TType(EbtFloat, EvqTemporary, 4);
1530 break;
1531
John Kessenich71351de2016-06-08 12:50:56 -06001532 case EHTokDouble:
1533 new(&type) TType(EbtDouble);
1534 break;
1535 case EHTokDouble1:
1536 new(&type) TType(EbtDouble);
1537 type.makeVector();
1538 break;
1539 case EHTokDouble2:
1540 new(&type) TType(EbtDouble, EvqTemporary, 2);
1541 break;
1542 case EHTokDouble3:
1543 new(&type) TType(EbtDouble, EvqTemporary, 3);
1544 break;
1545 case EHTokDouble4:
1546 new(&type) TType(EbtDouble, EvqTemporary, 4);
1547 break;
1548
1549 case EHTokInt:
1550 case EHTokDword:
1551 new(&type) TType(EbtInt);
1552 break;
1553 case EHTokInt1:
1554 new(&type) TType(EbtInt);
1555 type.makeVector();
1556 break;
John Kessenich87142c72016-03-12 20:24:24 -07001557 case EHTokInt2:
1558 new(&type) TType(EbtInt, EvqTemporary, 2);
1559 break;
1560 case EHTokInt3:
1561 new(&type) TType(EbtInt, EvqTemporary, 3);
1562 break;
1563 case EHTokInt4:
1564 new(&type) TType(EbtInt, EvqTemporary, 4);
1565 break;
1566
John Kessenich71351de2016-06-08 12:50:56 -06001567 case EHTokUint:
1568 new(&type) TType(EbtUint);
1569 break;
1570 case EHTokUint1:
1571 new(&type) TType(EbtUint);
1572 type.makeVector();
1573 break;
1574 case EHTokUint2:
1575 new(&type) TType(EbtUint, EvqTemporary, 2);
1576 break;
1577 case EHTokUint3:
1578 new(&type) TType(EbtUint, EvqTemporary, 3);
1579 break;
1580 case EHTokUint4:
1581 new(&type) TType(EbtUint, EvqTemporary, 4);
1582 break;
1583
1584 case EHTokBool:
1585 new(&type) TType(EbtBool);
1586 break;
1587 case EHTokBool1:
1588 new(&type) TType(EbtBool);
1589 type.makeVector();
1590 break;
John Kessenich87142c72016-03-12 20:24:24 -07001591 case EHTokBool2:
1592 new(&type) TType(EbtBool, EvqTemporary, 2);
1593 break;
1594 case EHTokBool3:
1595 new(&type) TType(EbtBool, EvqTemporary, 3);
1596 break;
1597 case EHTokBool4:
1598 new(&type) TType(EbtBool, EvqTemporary, 4);
1599 break;
1600
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001601 case EHTokHalf:
John Kessenich96f65522017-06-06 23:35:25 -06001602 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001603 break;
1604 case EHTokHalf1:
John Kessenich96f65522017-06-06 23:35:25 -06001605 new(&type) TType(half_bt, EvqTemporary);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001606 type.makeVector();
1607 break;
1608 case EHTokHalf2:
John Kessenich96f65522017-06-06 23:35:25 -06001609 new(&type) TType(half_bt, EvqTemporary, 2);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001610 break;
1611 case EHTokHalf3:
John Kessenich96f65522017-06-06 23:35:25 -06001612 new(&type) TType(half_bt, EvqTemporary, 3);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001613 break;
1614 case EHTokHalf4:
John Kessenich96f65522017-06-06 23:35:25 -06001615 new(&type) TType(half_bt, EvqTemporary, 4);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001616 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001617
steve-lunarg3226b082016-10-26 19:18:55 -06001618 case EHTokMin16float:
1619 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1620 break;
1621 case EHTokMin16float1:
1622 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1623 type.makeVector();
1624 break;
1625 case EHTokMin16float2:
1626 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1627 break;
1628 case EHTokMin16float3:
1629 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1630 break;
1631 case EHTokMin16float4:
1632 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1633 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001634
steve-lunarg3226b082016-10-26 19:18:55 -06001635 case EHTokMin10float:
1636 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1637 break;
1638 case EHTokMin10float1:
1639 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1640 type.makeVector();
1641 break;
1642 case EHTokMin10float2:
1643 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1644 break;
1645 case EHTokMin10float3:
1646 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1647 break;
1648 case EHTokMin10float4:
1649 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1650 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001651
steve-lunarg3226b082016-10-26 19:18:55 -06001652 case EHTokMin16int:
1653 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1654 break;
1655 case EHTokMin16int1:
1656 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1657 type.makeVector();
1658 break;
1659 case EHTokMin16int2:
1660 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1661 break;
1662 case EHTokMin16int3:
1663 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1664 break;
1665 case EHTokMin16int4:
1666 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1667 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001668
steve-lunarg3226b082016-10-26 19:18:55 -06001669 case EHTokMin12int:
1670 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1671 break;
1672 case EHTokMin12int1:
1673 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1674 type.makeVector();
1675 break;
1676 case EHTokMin12int2:
1677 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1678 break;
1679 case EHTokMin12int3:
1680 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1681 break;
1682 case EHTokMin12int4:
1683 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1684 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001685
steve-lunarg3226b082016-10-26 19:18:55 -06001686 case EHTokMin16uint:
1687 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1688 break;
1689 case EHTokMin16uint1:
1690 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1691 type.makeVector();
1692 break;
1693 case EHTokMin16uint2:
1694 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1695 break;
1696 case EHTokMin16uint3:
1697 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1698 break;
1699 case EHTokMin16uint4:
1700 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1701 break;
1702
John Kessenich0133c122016-05-20 12:17:26 -06001703 case EHTokInt1x1:
1704 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1705 break;
1706 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001707 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001708 break;
1709 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001710 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001711 break;
1712 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001713 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001714 break;
1715 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001716 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001717 break;
1718 case EHTokInt2x2:
1719 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1720 break;
1721 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001722 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001723 break;
1724 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001725 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001726 break;
1727 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001728 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001729 break;
1730 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001731 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001732 break;
1733 case EHTokInt3x3:
1734 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1735 break;
1736 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001737 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001738 break;
1739 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001740 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001741 break;
1742 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001743 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001744 break;
1745 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001746 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001747 break;
1748 case EHTokInt4x4:
1749 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1750 break;
1751
John Kessenich71351de2016-06-08 12:50:56 -06001752 case EHTokUint1x1:
1753 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1754 break;
1755 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001756 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001757 break;
1758 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001759 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001760 break;
1761 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001762 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001763 break;
1764 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001765 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001766 break;
1767 case EHTokUint2x2:
1768 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1769 break;
1770 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001771 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001772 break;
1773 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001774 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001775 break;
1776 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001777 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001778 break;
1779 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001780 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001781 break;
1782 case EHTokUint3x3:
1783 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1784 break;
1785 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001786 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001787 break;
1788 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001789 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001790 break;
1791 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001792 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001793 break;
1794 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001795 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001796 break;
1797 case EHTokUint4x4:
1798 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1799 break;
1800
1801 case EHTokBool1x1:
1802 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1803 break;
1804 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001805 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001806 break;
1807 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001808 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001809 break;
1810 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001811 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001812 break;
1813 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001814 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001815 break;
1816 case EHTokBool2x2:
1817 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1818 break;
1819 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001820 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001821 break;
1822 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001823 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001824 break;
1825 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001826 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001827 break;
1828 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001829 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001830 break;
1831 case EHTokBool3x3:
1832 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1833 break;
1834 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001835 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001836 break;
1837 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001838 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001839 break;
1840 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001841 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001842 break;
1843 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001844 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001845 break;
1846 case EHTokBool4x4:
1847 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1848 break;
1849
John Kessenich0133c122016-05-20 12:17:26 -06001850 case EHTokFloat1x1:
1851 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1852 break;
1853 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001854 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001855 break;
1856 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001857 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001858 break;
1859 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001860 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001861 break;
1862 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001863 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001864 break;
John Kessenich87142c72016-03-12 20:24:24 -07001865 case EHTokFloat2x2:
1866 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1867 break;
1868 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001869 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001870 break;
1871 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001872 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001873 break;
John Kessenich0133c122016-05-20 12:17:26 -06001874 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001875 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001876 break;
John Kessenich87142c72016-03-12 20:24:24 -07001877 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001878 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001879 break;
1880 case EHTokFloat3x3:
1881 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1882 break;
1883 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001884 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001885 break;
John Kessenich0133c122016-05-20 12:17:26 -06001886 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001887 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001888 break;
John Kessenich87142c72016-03-12 20:24:24 -07001889 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001890 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001891 break;
1892 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001893 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001894 break;
1895 case EHTokFloat4x4:
1896 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1897 break;
1898
John Kessenich96f65522017-06-06 23:35:25 -06001899 case EHTokHalf1x1:
1900 new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1901 break;
1902 case EHTokHalf1x2:
1903 new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1904 break;
1905 case EHTokHalf1x3:
1906 new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1907 break;
1908 case EHTokHalf1x4:
1909 new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1910 break;
1911 case EHTokHalf2x1:
1912 new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1913 break;
1914 case EHTokHalf2x2:
1915 new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1916 break;
1917 case EHTokHalf2x3:
1918 new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1919 break;
1920 case EHTokHalf2x4:
1921 new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1922 break;
1923 case EHTokHalf3x1:
1924 new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1925 break;
1926 case EHTokHalf3x2:
1927 new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1928 break;
1929 case EHTokHalf3x3:
1930 new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1931 break;
1932 case EHTokHalf3x4:
1933 new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
1934 break;
1935 case EHTokHalf4x1:
1936 new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
1937 break;
1938 case EHTokHalf4x2:
1939 new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
1940 break;
1941 case EHTokHalf4x3:
1942 new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
1943 break;
1944 case EHTokHalf4x4:
1945 new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
1946 break;
1947
John Kessenich0133c122016-05-20 12:17:26 -06001948 case EHTokDouble1x1:
1949 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1950 break;
1951 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001952 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001953 break;
1954 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001955 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001956 break;
1957 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001958 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001959 break;
1960 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001961 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001962 break;
1963 case EHTokDouble2x2:
1964 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1965 break;
1966 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001967 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001968 break;
1969 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001970 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001971 break;
1972 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001973 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001974 break;
1975 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001976 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001977 break;
1978 case EHTokDouble3x3:
1979 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1980 break;
1981 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001982 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001983 break;
1984 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001985 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001986 break;
1987 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001988 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001989 break;
1990 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001991 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001992 break;
1993 case EHTokDouble4x4:
1994 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1995 break;
1996
John Kessenich87142c72016-03-12 20:24:24 -07001997 default:
1998 return false;
1999 }
2000
2001 advanceToken();
2002
LoopDawgfa39cff2017-11-14 14:55:40 -07002003 if ((isUnorm || isSnorm) && !type.isFloatingDomain()) {
2004 parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", "");
2005 return false;
2006 }
2007
John Kessenich87142c72016-03-12 20:24:24 -07002008 return true;
2009}
2010
John Kesseniche6e74942016-06-11 16:43:14 -06002011// struct
John Kessenich3d157c52016-07-25 16:05:33 -06002012// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2013// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07002014// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06002015//
2016// struct_type
2017// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07002018// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06002019// | CBUFFER
2020// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06002021//
John Kessenich54ee28f2017-03-11 14:13:00 -07002022bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06002023{
John Kessenichb804de62016-09-05 12:19:18 -06002024 // This storage qualifier will tell us whether it's an AST
2025 // block type or just a generic structure type.
2026 TStorageQualifier storageQualifier = EvqTemporary;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002027 bool readonly = false;
John Kessenich3d157c52016-07-25 16:05:33 -06002028
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002029 if (acceptTokenClass(EHTokCBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002030 // CBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002031 storageQualifier = EvqUniform;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002032 } else if (acceptTokenClass(EHTokTBuffer)) {
John Kessenich2fcdd642017-06-19 15:41:11 -06002033 // TBUFFER
John Kessenichb804de62016-09-05 12:19:18 -06002034 storageQualifier = EvqBuffer;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002035 readonly = true;
John Kessenich054378d2017-06-19 15:13:26 -06002036 } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
2037 // Neither CLASS nor STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002038 return false;
John Kessenich054378d2017-06-19 15:13:26 -06002039 }
2040
2041 // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
John Kesseniche6e74942016-06-11 16:43:14 -06002042
LoopDawg7ee29ba2017-11-27 14:45:36 -07002043
2044 // IDENTIFIER. It might also be a keyword which can double as an identifier.
2045 // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal.
2046 // 'cbuffer int' is also legal, and 'struct int' appears rejected only because
2047 // it attempts to redefine the 'int' type.
2048 const char* idString = getTypeString(peek());
John Kesseniche6e74942016-06-11 16:43:14 -06002049 TString structName = "";
LoopDawg7ee29ba2017-11-27 14:45:36 -07002050 if (peekTokenClass(EHTokIdentifier) || idString != nullptr) {
2051 if (idString != nullptr)
2052 structName = *idString;
2053 else
2054 structName = *token.string;
John Kesseniche6e74942016-06-11 16:43:14 -06002055 advanceToken();
2056 }
2057
John Kessenich3d157c52016-07-25 16:05:33 -06002058 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002059 TQualifier postDeclQualifier;
2060 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07002061 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06002062
John Kessenichf3d88bd2017-03-19 12:24:29 -06002063 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07002064 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06002065 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07002066 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
2067 // struct_type IDENTIFIER
2068 return true;
2069 } else {
2070 expected("{");
2071 return false;
2072 }
John Kesseniche6e74942016-06-11 16:43:14 -06002073 }
2074
John Kessenichf3d88bd2017-03-19 12:24:29 -06002075
John Kesseniche6e74942016-06-11 16:43:14 -06002076 // struct_declaration_list
2077 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002078 // Save each member function so they can be processed after we have a fully formed 'this'.
2079 TVector<TFunctionDeclarator> functionDeclarators;
2080
2081 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06002082 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002083 parseContext.popNamespace();
2084
2085 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06002086 expected("struct member declarations");
2087 return false;
2088 }
2089
2090 // RIGHT_BRACE
2091 if (! acceptTokenClass(EHTokRightBrace)) {
2092 expected("}");
2093 return false;
2094 }
2095
2096 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06002097 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06002098 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06002099 else {
John Kessenich7735b942016-09-05 12:40:06 -06002100 postDeclQualifier.storage = storageQualifier;
steve-lunarg7b1dcd62017-04-20 13:16:23 -06002101 postDeclQualifier.readonly = readonly;
John Kessenich7735b942016-09-05 12:40:06 -06002102 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06002103 }
John Kesseniche6e74942016-06-11 16:43:14 -06002104
John Kessenich727b3742017-02-03 17:57:55 -07002105 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06002106
John Kessenich4960baa2017-03-19 18:09:59 -06002107 // For member functions: now that we know the type of 'this', go back and
2108 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
2109 // - parse the functions, their tokens were saved for deferred parsing (now)
2110 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
2111 // update signature
2112 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06002113 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06002114 }
2115
John Kessenichf3d88bd2017-03-19 12:24:29 -06002116 // All member functions get parsed inside the class/struct namespace and with the
2117 // class/struct members in a symbol-table level.
2118 parseContext.pushNamespace(structName);
John Kessenich0a2a0cd2017-05-16 23:16:26 -06002119 parseContext.pushThisScope(type, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06002120 bool deferredSuccess = true;
2121 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
2122 // parse body
2123 pushTokenStream(functionDeclarators[b].body);
2124 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
2125 deferredSuccess = false;
2126 popTokenStream();
2127 }
John Kessenich37789792017-03-21 23:56:40 -06002128 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06002129 parseContext.popNamespace();
2130
2131 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06002132}
2133
steve-lunarga766b832017-04-25 09:30:28 -06002134// constantbuffer
2135// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
2136bool HlslGrammar::acceptConstantBufferType(TType& type)
2137{
2138 if (! acceptTokenClass(EHTokConstantBuffer))
2139 return false;
2140
2141 if (! acceptTokenClass(EHTokLeftAngle)) {
2142 expected("left angle bracket");
2143 return false;
2144 }
2145
2146 TType templateType;
2147 if (! acceptType(templateType)) {
2148 expected("type");
2149 return false;
2150 }
2151
2152 if (! acceptTokenClass(EHTokRightAngle)) {
2153 expected("right angle bracket");
2154 return false;
2155 }
2156
2157 TQualifier postDeclQualifier;
2158 postDeclQualifier.clear();
2159 postDeclQualifier.storage = EvqUniform;
2160
2161 if (templateType.isStruct()) {
2162 // Make a block from the type parsed as the template argument
2163 TTypeList* typeList = templateType.getWritableStruct();
2164 new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2165
2166 type.getQualifier().storage = EvqUniform;
2167
2168 return true;
2169 } else {
2170 parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2171 return false;
2172 }
2173}
2174
LoopDawge5530b92017-11-08 19:48:11 -07002175// texture_buffer
2176// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE
2177bool HlslGrammar::acceptTextureBufferType(TType& type)
2178{
2179 if (! acceptTokenClass(EHTokTextureBuffer))
2180 return false;
2181
2182 if (! acceptTokenClass(EHTokLeftAngle)) {
2183 expected("left angle bracket");
2184 return false;
2185 }
2186
2187 TType templateType;
2188 if (! acceptType(templateType)) {
2189 expected("type");
2190 return false;
2191 }
2192
2193 if (! acceptTokenClass(EHTokRightAngle)) {
2194 expected("right angle bracket");
2195 return false;
2196 }
2197
2198 templateType.getQualifier().storage = EvqBuffer;
2199 templateType.getQualifier().readonly = true;
2200
2201 TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier());
2202
2203 blockType.getQualifier().storage = EvqBuffer;
2204 blockType.getQualifier().readonly = true;
2205
2206 type.shallowCopy(blockType);
2207
2208 return true;
2209}
2210
2211
steve-lunarg5da1f032017-02-12 17:50:28 -07002212// struct_buffer
2213// : APPENDSTRUCTUREDBUFFER
2214// | BYTEADDRESSBUFFER
2215// | CONSUMESTRUCTUREDBUFFER
2216// | RWBYTEADDRESSBUFFER
2217// | RWSTRUCTUREDBUFFER
2218// | STRUCTUREDBUFFER
2219bool HlslGrammar::acceptStructBufferType(TType& type)
2220{
2221 const EHlslTokenClass structBuffType = peek();
2222
2223 // TODO: globallycoherent
2224 bool hasTemplateType = true;
2225 bool readonly = false;
2226
2227 TStorageQualifier storage = EvqBuffer;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002228 TBuiltInVariable builtinType = EbvNone;
steve-lunarg5da1f032017-02-12 17:50:28 -07002229
2230 switch (structBuffType) {
2231 case EHTokAppendStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002232 builtinType = EbvAppendConsume;
2233 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002234 case EHTokByteAddressBuffer:
2235 hasTemplateType = false;
2236 readonly = true;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002237 builtinType = EbvByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002238 break;
2239 case EHTokConsumeStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002240 builtinType = EbvAppendConsume;
2241 break;
steve-lunarg5da1f032017-02-12 17:50:28 -07002242 case EHTokRWByteAddressBuffer:
2243 hasTemplateType = false;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002244 builtinType = EbvRWByteAddressBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002245 break;
2246 case EHTokRWStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002247 builtinType = EbvRWStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002248 break;
2249 case EHTokStructuredBuffer:
steve-lunarg8e26feb2017-04-10 08:19:21 -06002250 builtinType = EbvStructuredBuffer;
steve-lunarg5da1f032017-02-12 17:50:28 -07002251 readonly = true;
2252 break;
2253 default:
2254 return false; // not a structure buffer type
2255 }
2256
2257 advanceToken(); // consume the structure keyword
2258
2259 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
2260 TType* templateType = new TType;
2261
2262 if (hasTemplateType) {
2263 if (! acceptTokenClass(EHTokLeftAngle)) {
2264 expected("left angle bracket");
2265 return false;
2266 }
2267
2268 if (! acceptType(*templateType)) {
2269 expected("type");
2270 return false;
2271 }
2272 if (! acceptTokenClass(EHTokRightAngle)) {
2273 expected("right angle bracket");
2274 return false;
2275 }
2276 } else {
2277 // byte address buffers have no explicit type.
2278 TType uintType(EbtUint, storage);
2279 templateType->shallowCopy(uintType);
2280 }
2281
2282 // Create an unsized array out of that type.
2283 // TODO: does this work if it's already an array type?
2284 TArraySizes unsizedArray;
2285 unsizedArray.addInnerSize(UnsizedArraySize);
2286 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07002287 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07002288
2289 // field name is canonical for all structbuffers
2290 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07002291
steve-lunarg5da1f032017-02-12 17:50:28 -07002292 TTypeList* blockStruct = new TTypeList;
2293 TTypeLoc member = { templateType, token.loc };
2294 blockStruct->push_back(member);
2295
steve-lunargdd8287a2017-02-23 18:04:12 -07002296 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07002297 TType blockType(blockStruct, "", templateType->getQualifier());
2298
steve-lunargdd8287a2017-02-23 18:04:12 -07002299 blockType.getQualifier().storage = storage;
2300 blockType.getQualifier().readonly = readonly;
steve-lunarg8e26feb2017-04-10 08:19:21 -06002301 blockType.getQualifier().builtIn = builtinType;
steve-lunargdd8287a2017-02-23 18:04:12 -07002302
2303 // We may have created an equivalent type before, in which case we should use its
2304 // deep structure.
2305 parseContext.shareStructBufferType(blockType);
2306
steve-lunarg5da1f032017-02-12 17:50:28 -07002307 type.shallowCopy(blockType);
2308
2309 return true;
2310}
2311
John Kesseniche6e74942016-06-11 16:43:14 -06002312// struct_declaration_list
2313// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2314//
2315// struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002316// : attributes fully_specified_type struct_declarator COMMA struct_declarator ...
2317// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06002318//
2319// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06002320// : IDENTIFIER post_decls
2321// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07002322// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06002323//
John Kessenichaa3c64c2017-03-28 09:52:38 -06002324bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002325 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06002326{
2327 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002328 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06002329
2330 do {
2331 // success on seeing the RIGHT_BRACE coming up
2332 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002333 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002334
2335 // struct_declaration
John Kessenichcc951f82017-12-06 07:33:36 -07002336
2337 // attributes
2338 TAttributeMap attributes;
2339 acceptAttributes(attributes);
2340
John Kessenich54ee28f2017-03-11 14:13:00 -07002341 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002342
2343 // fully_specified_type
2344 TType memberType;
John Kessenich046bae02017-12-23 17:29:45 -07002345 if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002346 expected("member type");
2347 return false;
2348 }
2349
2350 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002351 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002352 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002353 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002354 expected("member name");
2355 return false;
2356 }
2357
John Kessenich54ee28f2017-03-11 14:13:00 -07002358 if (peekTokenClass(EHTokLeftParen)) {
2359 // function_parameters
2360 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002361 declarators.resize(declarators.size() + 1);
2362 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002363 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2364 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002365 if (functionDefinitionAccepted)
2366 break;
2367 }
2368 expected("member-function definition");
2369 return false;
2370 } else {
2371 // add it to the list of members
2372 TTypeLoc member = { new TType(EbtVoid), token.loc };
2373 member.type->shallowCopy(memberType);
2374 member.type->setFieldName(*idToken.string);
2375 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002376
John Kessenich54ee28f2017-03-11 14:13:00 -07002377 // array_specifier
2378 TArraySizes* arraySizes = nullptr;
2379 acceptArraySpecifier(arraySizes);
2380 if (arraySizes)
2381 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002382
John Kessenich54ee28f2017-03-11 14:13:00 -07002383 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002384
John Kessenich54ee28f2017-03-11 14:13:00 -07002385 // EQUAL assignment_expression
2386 if (acceptTokenClass(EHTokAssign)) {
2387 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2388 TIntermTyped* expressionNode = nullptr;
2389 if (! acceptAssignmentExpression(expressionNode)) {
2390 expected("initializer");
2391 return false;
2392 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002393 }
2394 }
John Kesseniche6e74942016-06-11 16:43:14 -06002395 // success on seeing the SEMICOLON coming up
2396 if (peekTokenClass(EHTokSemicolon))
2397 break;
2398
2399 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002400 if (acceptTokenClass(EHTokComma))
2401 declarator_list = true;
2402 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002403 expected(",");
2404 return false;
2405 }
2406
2407 } while (true);
2408
2409 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002410 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002411 expected(";");
2412 return false;
2413 }
2414
2415 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002416
John Kessenichb16f7e62017-03-11 19:32:47 -07002417 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002418}
2419
John Kessenich54ee28f2017-03-11 14:13:00 -07002420// member_function_definition
2421// | function_parameters post_decls compound_statement
2422//
2423// Expects type to have EvqGlobal for a static member and
2424// EvqTemporary for non-static member.
John Kessenich9855bda2017-09-11 21:48:19 -06002425bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName,
John Kessenichf3d88bd2017-03-19 12:24:29 -06002426 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002427{
John Kessenich54ee28f2017-03-11 14:13:00 -07002428 bool accepted = false;
2429
John Kessenich9855bda2017-09-11 21:48:19 -06002430 TString* functionName = &memberName;
John Kessenich4dc835c2017-03-28 23:43:10 -06002431 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002432 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002433 if (type.getQualifier().storage == EvqTemporary)
2434 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002435 else
2436 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002437
2438 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002439 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002440 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002441 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002442
2443 // compound_statement (function body definition)
2444 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002445 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002446 declarator.body = new TVector<HlslToken>;
2447 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002448 }
2449 } else
2450 expected("function parameter list");
2451
John Kessenich54ee28f2017-03-11 14:13:00 -07002452 return accepted;
2453}
2454
John Kessenich5f934b02016-03-13 17:58:25 -06002455// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002456// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002457// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002458//
2459bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2460{
John Kessenich078d7f22016-03-14 10:02:11 -06002461 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002462 if (! acceptTokenClass(EHTokLeftParen))
2463 return false;
2464
John Kessenich71351de2016-06-08 12:50:56 -06002465 // VOID RIGHT_PAREN
2466 if (! acceptTokenClass(EHTokVoid)) {
2467 do {
2468 // parameter_declaration
2469 if (! acceptParameterDeclaration(function))
2470 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002471
John Kessenich71351de2016-06-08 12:50:56 -06002472 // COMMA
2473 if (! acceptTokenClass(EHTokComma))
2474 break;
2475 } while (true);
2476 }
John Kessenich5f934b02016-03-13 17:58:25 -06002477
John Kessenich078d7f22016-03-14 10:02:11 -06002478 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002479 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002480 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002481 return false;
2482 }
2483
2484 return true;
2485}
2486
steve-lunarg26d31452016-12-23 18:56:57 -07002487// default_parameter_declaration
2488// : EQUAL conditional_expression
2489// : EQUAL initializer
2490bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2491{
2492 node = nullptr;
2493
2494 // Valid not to have a default_parameter_declaration
2495 if (!acceptTokenClass(EHTokAssign))
2496 return true;
2497
2498 if (!acceptConditionalExpression(node)) {
2499 if (!acceptInitializer(node))
2500 return false;
2501
2502 // For initializer lists, we have to const-fold into a constructor for the type, so build
2503 // that.
John Kessenichc633f642017-04-03 21:48:37 -06002504 TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
steve-lunarg26d31452016-12-23 18:56:57 -07002505 if (constructor == nullptr) // cannot construct
2506 return false;
2507
2508 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002509 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002510 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002511
steve-lunarg26d31452016-12-23 18:56:57 -07002512 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2513 }
2514
John Kessenichbb79abc2017-10-07 13:23:09 -06002515 if (node == nullptr)
2516 return false;
2517
steve-lunarg26d31452016-12-23 18:56:57 -07002518 // If this is simply a constant, we can use it directly.
2519 if (node->getAsConstantUnion())
2520 return true;
2521
2522 // Otherwise, it has to be const-foldable.
2523 TIntermTyped* origNode = node;
2524
2525 node = intermediate.fold(node->getAsAggregate());
2526
2527 if (node != nullptr && origNode != node)
2528 return true;
2529
2530 parseContext.error(token.loc, "invalid default parameter value", "", "");
2531
2532 return false;
2533}
2534
John Kessenich5f934b02016-03-13 17:58:25 -06002535// parameter_declaration
John Kessenich77ea30b2017-09-30 14:34:50 -06002536// : attributes attributed_declaration
2537//
2538// attributed_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002539// : fully_specified_type post_decls [ = default_parameter_declaration ]
2540// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002541//
2542bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2543{
John Kessenich77ea30b2017-09-30 14:34:50 -06002544 // attributes
2545 TAttributeMap attributes;
2546 acceptAttributes(attributes);
2547
John Kessenich5f934b02016-03-13 17:58:25 -06002548 // fully_specified_type
2549 TType* type = new TType;
John Kessenich046bae02017-12-23 17:29:45 -07002550 if (! acceptFullySpecifiedType(*type, attributes))
John Kessenich5f934b02016-03-13 17:58:25 -06002551 return false;
2552
2553 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002554 HlslToken idToken;
2555 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002556
John Kessenich19b92ff2016-06-19 11:50:34 -06002557 // array_specifier
2558 TArraySizes* arraySizes = nullptr;
2559 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002560 if (arraySizes) {
2561 if (arraySizes->isImplicit()) {
2562 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2563 return false;
2564 }
2565
John Kessenich19b92ff2016-06-19 11:50:34 -06002566 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002567 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002568
2569 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002570 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002571
steve-lunarg26d31452016-12-23 18:56:57 -07002572 TIntermTyped* defaultValue;
2573 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2574 return false;
2575
John Kessenich5aa59e22016-06-17 15:50:47 -06002576 parseContext.paramFix(*type);
2577
steve-lunarg26d31452016-12-23 18:56:57 -07002578 // If any prior parameters have default values, all the parameters after that must as well.
2579 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2580 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2581 return false;
2582 }
2583
2584 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002585 function.addParameter(param);
2586
2587 return true;
2588}
2589
2590// Do the work to create the function definition in addition to
2591// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002592//
2593// If 'deferredTokens' are passed in, just get the token stream,
2594// don't process.
2595//
2596bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2597 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002598{
John Kessenich088d52b2017-03-11 17:55:28 -07002599 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002600
John Kessenichb16f7e62017-03-11 19:32:47 -07002601 if (deferredTokens)
2602 return captureBlockTokens(*deferredTokens);
2603 else
John Kessenich4960baa2017-03-19 18:09:59 -06002604 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002605}
2606
2607bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2608{
2609 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002610 TIntermNode* entryPointNode = nullptr;
2611
John Kessenich077e0522016-06-09 02:02:17 -06002612 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002613 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2614 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002615
2616 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002617 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002618 if (! acceptCompoundStatement(functionBody))
2619 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002620
John Kessenich54ee28f2017-03-11 14:13:00 -07002621 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002622 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002623
2624 // Hook up the 1 or 2 function definitions.
2625 nodeList = intermediate.growAggregate(nodeList, functionNode);
2626 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002627
2628 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002629}
2630
John Kessenich0d2b6de2016-06-05 11:23:11 -06002631// Accept an expression with parenthesis around it, where
2632// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002633// syntactically required ones like in "if ( expression )".
2634//
2635// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002636//
2637// Note this one is not set up to be speculative; as it gives
2638// errors if not found.
2639//
2640bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2641{
John Kessenich7199a6d2017-11-29 16:32:46 -07002642 expression = nullptr;
2643
John Kessenich0d2b6de2016-06-05 11:23:11 -06002644 // LEFT_PAREN
2645 if (! acceptTokenClass(EHTokLeftParen))
2646 expected("(");
2647
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002648 bool decl = false;
2649 TIntermNode* declNode = nullptr;
2650 decl = acceptControlDeclaration(declNode);
2651 if (decl) {
2652 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2653 expected("initialized declaration");
2654 return false;
2655 } else
2656 expression = declNode->getAsTyped();
2657 } else {
2658 // no declaration
2659 if (! acceptExpression(expression)) {
2660 expected("expression");
2661 return false;
2662 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002663 }
2664
2665 // RIGHT_PAREN
2666 if (! acceptTokenClass(EHTokRightParen))
2667 expected(")");
2668
2669 return true;
2670}
2671
John Kessenich34fb0362016-05-03 23:17:20 -06002672// The top-level full expression recognizer.
2673//
John Kessenich87142c72016-03-12 20:24:24 -07002674// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002675// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002676//
2677bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2678{
LoopDawgef764a22016-06-03 09:17:51 -06002679 node = nullptr;
2680
John Kessenich34fb0362016-05-03 23:17:20 -06002681 // assignment_expression
2682 if (! acceptAssignmentExpression(node))
2683 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002684
John Kessenich34fb0362016-05-03 23:17:20 -06002685 if (! peekTokenClass(EHTokComma))
2686 return true;
2687
2688 do {
2689 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002690 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002691 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002692
John Kessenich34fb0362016-05-03 23:17:20 -06002693 // ... assignment_expression
2694 TIntermTyped* rightNode = nullptr;
2695 if (! acceptAssignmentExpression(rightNode)) {
2696 expected("assignment expression");
2697 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002698 }
2699
John Kessenich34fb0362016-05-03 23:17:20 -06002700 node = intermediate.addComma(node, rightNode, loc);
2701
2702 if (! peekTokenClass(EHTokComma))
2703 return true;
2704 } while (true);
2705}
2706
John Kessenich07354242016-07-01 19:58:06 -06002707// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002708// : LEFT_BRACE RIGHT_BRACE
2709// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002710//
2711// initializer_list
2712// : assignment_expression COMMA assignment_expression COMMA ...
2713//
2714bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2715{
2716 // LEFT_BRACE
2717 if (! acceptTokenClass(EHTokLeftBrace))
2718 return false;
2719
John Kessenich98ad4852016-11-27 17:39:07 -07002720 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002721 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002722 if (acceptTokenClass(EHTokRightBrace)) {
2723 // a zero-length initializer list
2724 node = intermediate.makeAggregate(loc);
2725 return true;
2726 }
2727
2728 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002729 node = nullptr;
2730 do {
2731 // assignment_expression
2732 TIntermTyped* expr;
2733 if (! acceptAssignmentExpression(expr)) {
2734 expected("assignment expression in initializer list");
2735 return false;
2736 }
LoopDawg0fca0ba2017-07-10 15:43:40 -06002737
2738 const bool firstNode = (node == nullptr);
2739
John Kessenich07354242016-07-01 19:58:06 -06002740 node = intermediate.growAggregate(node, expr, loc);
2741
LoopDawg0fca0ba2017-07-10 15:43:40 -06002742 // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2743 // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2744 // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2745 if (firstNode && expr->getQualifier().storage == EvqConst)
2746 node->getQualifier().storage = EvqConst;
2747 else if (expr->getQualifier().storage != EvqConst)
2748 node->getQualifier().storage = EvqTemporary;
2749
John Kessenich07354242016-07-01 19:58:06 -06002750 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002751 if (acceptTokenClass(EHTokComma)) {
2752 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2753 return true;
John Kessenich07354242016-07-01 19:58:06 -06002754 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002755 }
John Kessenich07354242016-07-01 19:58:06 -06002756
2757 // RIGHT_BRACE
2758 if (acceptTokenClass(EHTokRightBrace))
2759 return true;
2760
2761 expected(", or }");
2762 return false;
2763 } while (true);
2764}
2765
John Kessenich34fb0362016-05-03 23:17:20 -06002766// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002767// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002768//
2769// a op (b op (c op d))
2770//
2771// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002772// : initializer
2773// | conditional_expression
2774// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002775//
2776bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2777{
John Kessenich07354242016-07-01 19:58:06 -06002778 // initializer
2779 if (peekTokenClass(EHTokLeftBrace)) {
2780 if (acceptInitializer(node))
2781 return true;
2782
2783 expected("initializer");
2784 return false;
2785 }
2786
John Kessenich00957f82016-07-27 10:39:57 -06002787 // conditional_expression
2788 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002789 return false;
2790
John Kessenich07354242016-07-01 19:58:06 -06002791 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002792 TOperator assignOp = HlslOpMap::assignment(peek());
2793 if (assignOp == EOpNull)
2794 return true;
2795
John Kessenich00957f82016-07-27 10:39:57 -06002796 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002797 TSourceLoc loc = token.loc;
2798 advanceToken();
2799
John Kessenich00957f82016-07-27 10:39:57 -06002800 // conditional_expression assign_op conditional_expression ...
2801 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002802 // gets the right-to-left associativity.
2803 TIntermTyped* rightNode = nullptr;
2804 if (! acceptAssignmentExpression(rightNode)) {
2805 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002806 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002807 }
2808
John Kessenichd21baed2016-09-16 03:05:12 -06002809 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002810 node = parseContext.handleLvalue(loc, "assign", node);
2811
John Kessenichfea226b2016-07-28 17:53:56 -06002812 if (node == nullptr) {
2813 parseContext.error(loc, "could not create assignment", "", "");
2814 return false;
2815 }
John Kessenich34fb0362016-05-03 23:17:20 -06002816
2817 if (! peekTokenClass(EHTokComma))
2818 return true;
2819
2820 return true;
2821}
2822
John Kessenich00957f82016-07-27 10:39:57 -06002823// Accept a conditional expression, which associates right-to-left,
2824// accomplished by the "true" expression calling down to lower
2825// precedence levels than this level.
2826//
2827// conditional_expression
2828// : binary_expression
2829// | binary_expression QUESTION expression COLON assignment_expression
2830//
2831bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2832{
2833 // binary_expression
2834 if (! acceptBinaryExpression(node, PlLogicalOr))
2835 return false;
2836
2837 if (! acceptTokenClass(EHTokQuestion))
2838 return true;
2839
John Kessenich636b62d2017-04-11 19:45:00 -06002840 node = parseContext.convertConditionalExpression(token.loc, node, false);
John Kessenich7e997e22017-03-30 22:09:30 -06002841 if (node == nullptr)
2842 return false;
2843
John Kessenichf6deacd2017-06-06 19:52:55 -06002844 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
2845
John Kessenich00957f82016-07-27 10:39:57 -06002846 TIntermTyped* trueNode = nullptr;
2847 if (! acceptExpression(trueNode)) {
2848 expected("expression after ?");
2849 return false;
2850 }
2851 TSourceLoc loc = token.loc;
2852
2853 if (! acceptTokenClass(EHTokColon)) {
2854 expected(":");
2855 return false;
2856 }
2857
2858 TIntermTyped* falseNode = nullptr;
2859 if (! acceptAssignmentExpression(falseNode)) {
2860 expected("expression after :");
2861 return false;
2862 }
2863
John Kessenichf6deacd2017-06-06 19:52:55 -06002864 --parseContext.controlFlowNestingLevel;
2865
John Kessenich00957f82016-07-27 10:39:57 -06002866 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2867
2868 return true;
2869}
2870
John Kessenich34fb0362016-05-03 23:17:20 -06002871// Accept a binary expression, for binary operations that
2872// associate left-to-right. This is, it is implicit, for example
2873//
2874// ((a op b) op c) op d
2875//
2876// binary_expression
2877// : expression op expression op expression ...
2878//
2879// where 'expression' is the next higher level in precedence.
2880//
2881bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2882{
2883 if (precedenceLevel > PlMul)
2884 return acceptUnaryExpression(node);
2885
2886 // assignment_expression
2887 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2888 return false;
2889
John Kessenich34fb0362016-05-03 23:17:20 -06002890 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002891 TOperator op = HlslOpMap::binary(peek());
2892 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2893 if (tokenLevel < precedenceLevel)
2894 return true;
2895
John Kessenich34fb0362016-05-03 23:17:20 -06002896 // ... op
2897 TSourceLoc loc = token.loc;
2898 advanceToken();
2899
2900 // ... expression
2901 TIntermTyped* rightNode = nullptr;
2902 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2903 expected("expression");
2904 return false;
2905 }
2906
2907 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002908 if (node == nullptr) {
2909 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2910 return false;
2911 }
John Kessenich34fb0362016-05-03 23:17:20 -06002912 } while (true);
2913}
2914
2915// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002916// : (type) unary_expression
2917// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002918// | - unary_expression
2919// | ! unary_expression
2920// | ~ unary_expression
2921// | ++ unary_expression
2922// | -- unary_expression
2923// | postfix_expression
2924//
2925bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2926{
John Kessenich1cc1a282016-06-03 16:55:49 -06002927 // (type) unary_expression
2928 // Have to look two steps ahead, because this could be, e.g., a
2929 // postfix_expression instead, since that also starts with at "(".
2930 if (acceptTokenClass(EHTokLeftParen)) {
2931 TType castType;
2932 if (acceptType(castType)) {
John Kessenich82ae8c32017-06-13 23:13:10 -06002933 // recognize any array_specifier as part of the type
2934 TArraySizes* arraySizes = nullptr;
2935 acceptArraySpecifier(arraySizes);
2936 if (arraySizes != nullptr)
2937 castType.newArraySizes(*arraySizes);
2938 TSourceLoc loc = token.loc;
steve-lunarg5964c642016-07-30 07:38:55 -06002939 if (acceptTokenClass(EHTokRightParen)) {
2940 // We've matched "(type)" now, get the expression to cast
steve-lunarg5964c642016-07-30 07:38:55 -06002941 if (! acceptUnaryExpression(node))
2942 return false;
2943
2944 // Hook it up like a constructor
John Kessenichc633f642017-04-03 21:48:37 -06002945 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
steve-lunarg5964c642016-07-30 07:38:55 -06002946 if (constructorFunction == nullptr) {
2947 expected("type that can be constructed");
2948 return false;
2949 }
2950 TIntermTyped* arguments = nullptr;
2951 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2952 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2953
John Kessenichbb79abc2017-10-07 13:23:09 -06002954 return node != nullptr;
steve-lunarg5964c642016-07-30 07:38:55 -06002955 } else {
2956 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2957 // the '(int' part. We must back up twice.
2958 recedeToken();
2959 recedeToken();
John Kessenich82ae8c32017-06-13 23:13:10 -06002960
2961 // Note, there are no array constructors like
2962 // (float[2](...))
2963 if (arraySizes != nullptr)
2964 parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
John Kessenich1cc1a282016-06-03 16:55:49 -06002965 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002966 } else {
2967 // This isn't a type cast, but it still started "(", so if it is a
2968 // unary expression, it can only be a postfix_expression, so try that.
2969 // Back it up first.
2970 recedeToken();
2971 return acceptPostfixExpression(node);
2972 }
2973 }
2974
2975 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002976 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002977
John Kessenich1cc1a282016-06-03 16:55:49 -06002978 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002979 if (unaryOp == EOpNull)
2980 return acceptPostfixExpression(node);
2981
2982 // op unary_expression
2983 TSourceLoc loc = token.loc;
2984 advanceToken();
2985 if (! acceptUnaryExpression(node))
2986 return false;
2987
2988 // + is a no-op
2989 if (unaryOp == EOpAdd)
2990 return true;
2991
2992 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002993
2994 // These unary ops require lvalues
2995 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2996 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002997
2998 return node != nullptr;
2999}
3000
3001// postfix_expression
3002// : LEFT_PAREN expression RIGHT_PAREN
3003// | literal
3004// | constructor
John Kessenich8f9fdc92017-03-30 16:22:26 -06003005// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
John Kessenich34fb0362016-05-03 23:17:20 -06003006// | function_call
3007// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
3008// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003009// | postfix_expression DOT IDENTIFIER arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003010// | postfix_expression arguments
John Kessenich34fb0362016-05-03 23:17:20 -06003011// | postfix_expression INC_OP
3012// | postfix_expression DEC_OP
3013//
3014bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
3015{
3016 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07003017 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06003018
3019 // idToken will pick up either a variable or a function name in a function call
3020 HlslToken idToken;
3021
John Kessenich21472ae2016-06-04 11:46:33 -06003022 // Find something before the postfix operations, as they can't operate
3023 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07003024 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06003025 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003026 if (! acceptExpression(node)) {
3027 expected("expression");
3028 return false;
3029 }
3030 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003031 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003032 return false;
3033 }
John Kessenich34fb0362016-05-03 23:17:20 -06003034 } else if (acceptLiteral(node)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003035 // literal (nothing else to do yet)
John Kessenich34fb0362016-05-03 23:17:20 -06003036 } else if (acceptConstructor(node)) {
3037 // constructor (nothing else to do yet)
3038 } else if (acceptIdentifier(idToken)) {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003039 // user-type, namespace name, variable, or function name
3040 TString* fullName = idToken.string;
3041 while (acceptTokenClass(EHTokColonColon)) {
3042 // user-type or namespace name
3043 fullName = NewPoolTString(fullName->c_str());
3044 fullName->append(parseContext.scopeMangler);
3045 if (acceptIdentifier(idToken))
3046 fullName->append(*idToken.string);
3047 else {
3048 expected("identifier after ::");
John Kessenich54ee28f2017-03-11 14:13:00 -07003049 return false;
3050 }
John Kessenich8f9fdc92017-03-30 16:22:26 -06003051 }
3052 if (! peekTokenClass(EHTokLeftParen)) {
3053 node = parseContext.handleVariable(idToken.loc, fullName);
3054 } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
John Kessenich34fb0362016-05-03 23:17:20 -06003055 // function_call (nothing else to do yet)
3056 } else {
3057 expected("function call arguments");
3058 return false;
3059 }
John Kessenich21472ae2016-06-04 11:46:33 -06003060 } else {
3061 // nothing found, can't post operate
3062 return false;
John Kessenich87142c72016-03-12 20:24:24 -07003063 }
3064
John Kessenich21472ae2016-06-04 11:46:33 -06003065 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06003066 do {
3067 TSourceLoc loc = token.loc;
3068 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07003069
John Kessenich34fb0362016-05-03 23:17:20 -06003070 // Consume only a valid post-unary operator, otherwise we are done.
3071 switch (postOp) {
3072 case EOpIndexDirectStruct:
3073 case EOpIndexIndirect:
3074 case EOpPostIncrement:
3075 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07003076 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003077 advanceToken();
3078 break;
3079 default:
3080 return true;
3081 }
John Kessenich87142c72016-03-12 20:24:24 -07003082
John Kessenich34fb0362016-05-03 23:17:20 -06003083 // We have a valid post-unary operator, process it.
3084 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07003085 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06003086 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06003087 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003088 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07003089 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06003090 HlslToken field;
3091 if (! acceptIdentifier(field)) {
3092 expected("swizzle or member");
3093 return false;
3094 }
LoopDawg4886f692016-06-29 10:58:58 -06003095
John Kessenich516d92d2017-03-08 20:09:03 -07003096 if (peekTokenClass(EHTokLeftParen)) {
3097 // member function
3098 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06003099
John Kessenich516d92d2017-03-08 20:09:03 -07003100 // arguments
John Kessenich8f9fdc92017-03-30 16:22:26 -06003101 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
LoopDawg4886f692016-06-29 10:58:58 -06003102 expected("function parameters");
3103 return false;
3104 }
John Kessenich516d92d2017-03-08 20:09:03 -07003105 } else
3106 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06003107
John Kessenich34fb0362016-05-03 23:17:20 -06003108 break;
John Kessenich93a162a2016-06-17 17:16:27 -06003109 }
John Kessenich34fb0362016-05-03 23:17:20 -06003110 case EOpIndexIndirect:
3111 {
John Kessenich19b92ff2016-06-19 11:50:34 -06003112 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06003113 TIntermTyped* indexNode = nullptr;
3114 if (! acceptExpression(indexNode) ||
3115 ! peekTokenClass(EHTokRightBracket)) {
3116 expected("expression followed by ']'");
3117 return false;
3118 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003119 advanceToken();
3120 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
steve-lunarg2efd6c62017-04-06 20:22:20 -06003121 if (node == nullptr)
3122 return false;
John Kessenich19b92ff2016-06-19 11:50:34 -06003123 break;
John Kessenich34fb0362016-05-03 23:17:20 -06003124 }
3125 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003126 // INC_OP
3127 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06003128 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06003129 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06003130 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06003131 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06003132 break;
3133 default:
3134 assert(0);
3135 break;
3136 }
3137 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07003138}
3139
John Kessenichd016be12016-03-13 11:24:20 -06003140// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06003141// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06003142//
3143bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
3144{
3145 // type
3146 TType type;
3147 if (acceptType(type)) {
John Kessenichc633f642017-04-03 21:48:37 -06003148 TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
John Kessenichd016be12016-03-13 11:24:20 -06003149 if (constructorFunction == nullptr)
3150 return false;
3151
3152 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06003153 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003154 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07003155 // It's possible this is a type keyword used as an identifier. Put the token back
3156 // for later use.
3157 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06003158 return false;
3159 }
3160
3161 // hook it up
3162 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
3163
John Kessenichbb79abc2017-10-07 13:23:09 -06003164 return node != nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06003165 }
3166
3167 return false;
3168}
3169
John Kessenich34fb0362016-05-03 23:17:20 -06003170// The function_call identifier was already recognized, and passed in as idToken.
3171//
3172// function_call
3173// : [idToken] arguments
3174//
John Kessenich8f9fdc92017-03-30 16:22:26 -06003175bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
John Kessenich34fb0362016-05-03 23:17:20 -06003176{
John Kessenich54ee28f2017-03-11 14:13:00 -07003177 // name
3178 TString* functionName = nullptr;
John Kessenich8f9fdc92017-03-30 16:22:26 -06003179 if (baseObject == nullptr) {
3180 functionName = &name;
3181 } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
John Kessenich4960baa2017-03-19 18:09:59 -06003182 // Built-in methods are not in the symbol table as methods, but as global functions
3183 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06003184 functionName = NewPoolTString(BUILTIN_PREFIX);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003185 functionName->append(name);
John Kessenich4960baa2017-03-19 18:09:59 -06003186 } else {
John Kessenich8f9fdc92017-03-30 16:22:26 -06003187 if (! baseObject->getType().isStruct()) {
3188 expected("structure");
3189 return false;
3190 }
John Kessenich54ee28f2017-03-11 14:13:00 -07003191 functionName = NewPoolTString("");
John Kessenich8f9fdc92017-03-30 16:22:26 -06003192 functionName->append(baseObject->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06003193 parseContext.addScopeMangler(*functionName);
John Kessenich8f9fdc92017-03-30 16:22:26 -06003194 functionName->append(name);
John Kessenich5f12d2f2017-03-11 09:39:55 -07003195 }
LoopDawg4886f692016-06-29 10:58:58 -06003196
John Kessenich54ee28f2017-03-11 14:13:00 -07003197 // function
3198 TFunction* function = new TFunction(functionName, TType(EbtVoid));
3199
3200 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07003201 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003202 if (baseObject != nullptr) {
3203 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07003204 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06003205 }
John Kessenich4678ca92016-05-13 09:33:42 -06003206 if (! acceptArguments(function, arguments))
3207 return false;
3208
John Kessenich54ee28f2017-03-11 14:13:00 -07003209 // call
John Kessenich8f9fdc92017-03-30 16:22:26 -06003210 node = parseContext.handleFunctionCall(loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06003211
John Kessenichbb79abc2017-10-07 13:23:09 -06003212 return node != nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -06003213}
3214
John Kessenich87142c72016-03-12 20:24:24 -07003215// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06003216// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003217//
John Kessenichd016be12016-03-13 11:24:20 -06003218// The arguments are pushed onto the 'function' argument list and
3219// onto the 'arguments' aggregate.
3220//
John Kessenich4678ca92016-05-13 09:33:42 -06003221bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07003222{
John Kessenich078d7f22016-03-14 10:02:11 -06003223 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003224 if (! acceptTokenClass(EHTokLeftParen))
3225 return false;
3226
John Kessenich2aa12b12017-04-18 14:47:33 -06003227 // RIGHT_PAREN
3228 if (acceptTokenClass(EHTokRightParen))
3229 return true;
3230
3231 // must now be at least one expression...
John Kessenich87142c72016-03-12 20:24:24 -07003232 do {
John Kessenichd016be12016-03-13 11:24:20 -06003233 // expression
John Kessenich87142c72016-03-12 20:24:24 -07003234 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06003235 if (! acceptAssignmentExpression(arg))
John Kessenich2aa12b12017-04-18 14:47:33 -06003236 return false;
John Kessenichd016be12016-03-13 11:24:20 -06003237
3238 // hook it up
3239 parseContext.handleFunctionArgument(function, arguments, arg);
3240
John Kessenich078d7f22016-03-14 10:02:11 -06003241 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07003242 if (! acceptTokenClass(EHTokComma))
3243 break;
3244 } while (true);
3245
John Kessenich078d7f22016-03-14 10:02:11 -06003246 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07003247 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003248 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07003249 return false;
3250 }
3251
3252 return true;
3253}
3254
3255bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3256{
3257 switch (token.tokenClass) {
3258 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003259 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003260 break;
steve-lunarg2de32912016-07-28 14:49:48 -06003261 case EHTokUintConstant:
3262 node = intermediate.addConstantUnion(token.u, token.loc, true);
3263 break;
John Kessenich87142c72016-03-12 20:24:24 -07003264 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003265 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003266 break;
3267 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003268 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003269 break;
3270 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06003271 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07003272 break;
John Kessenich86f71382016-09-19 20:23:18 -06003273 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07003274 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06003275 break;
John Kessenich87142c72016-03-12 20:24:24 -07003276
3277 default:
3278 return false;
3279 }
3280
3281 advanceToken();
3282
3283 return true;
3284}
3285
John Kessenich0e071192017-06-06 11:37:33 -06003286// simple_statement
3287// : SEMICOLON
3288// | declaration_statement
3289// | expression SEMICOLON
3290//
3291bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3292{
3293 // SEMICOLON
3294 if (acceptTokenClass(EHTokSemicolon))
3295 return true;
3296
3297 // declaration
3298 if (acceptDeclaration(statement))
3299 return true;
3300
3301 // expression
3302 TIntermTyped* node;
3303 if (acceptExpression(node))
3304 statement = node;
3305 else
3306 return false;
3307
3308 // SEMICOLON (following an expression)
3309 if (acceptTokenClass(EHTokSemicolon))
3310 return true;
3311 else {
3312 expected(";");
3313 return false;
3314 }
3315}
3316
John Kessenich5f934b02016-03-13 17:58:25 -06003317// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06003318// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003319//
John Kessenich21472ae2016-06-04 11:46:33 -06003320bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07003321{
John Kessenich21472ae2016-06-04 11:46:33 -06003322 TIntermAggregate* compoundStatement = nullptr;
3323
John Kessenich34fb0362016-05-03 23:17:20 -06003324 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003325 if (! acceptTokenClass(EHTokLeftBrace))
3326 return false;
3327
3328 // statement statement ...
3329 TIntermNode* statement = nullptr;
3330 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06003331 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3332 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3333 branch->getFlowOp() == EOpDefault)) {
3334 // hook up individual subsequences within a switch statement
3335 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3336 compoundStatement = nullptr;
3337 } else {
3338 // hook it up to the growing compound statement
3339 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3340 }
John Kessenich5f934b02016-03-13 17:58:25 -06003341 }
John Kessenich34fb0362016-05-03 23:17:20 -06003342 if (compoundStatement)
3343 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06003344
John Kessenich21472ae2016-06-04 11:46:33 -06003345 retStatement = compoundStatement;
3346
John Kessenich34fb0362016-05-03 23:17:20 -06003347 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06003348 return acceptTokenClass(EHTokRightBrace);
3349}
3350
John Kessenich0d2b6de2016-06-05 11:23:11 -06003351bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3352{
3353 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06003354 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003355 parseContext.popScope();
3356
3357 return result;
3358}
3359
John Kessenich077e0522016-06-09 02:02:17 -06003360bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003361{
John Kessenich077e0522016-06-09 02:02:17 -06003362 parseContext.pushScope();
3363 bool result = acceptCompoundStatement(statement);
3364 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06003365
3366 return result;
3367}
3368
John Kessenich5f934b02016-03-13 17:58:25 -06003369// statement
John Kessenich21472ae2016-06-04 11:46:33 -06003370// : attributes attributed_statement
3371//
3372// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003373// : compound_statement
John Kessenich0e071192017-06-06 11:37:33 -06003374// | simple_statement
John Kessenich21472ae2016-06-04 11:46:33 -06003375// | selection_statement
3376// | switch_statement
3377// | case_label
John Kessenich0e071192017-06-06 11:37:33 -06003378// | default_label
John Kessenich21472ae2016-06-04 11:46:33 -06003379// | iteration_statement
3380// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06003381//
3382bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3383{
John Kessenich21472ae2016-06-04 11:46:33 -06003384 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06003385
John Kessenich21472ae2016-06-04 11:46:33 -06003386 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06003387 TAttributeMap attributes;
3388 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003389
John Kessenich21472ae2016-06-04 11:46:33 -06003390 // attributed_statement
3391 switch (peek()) {
3392 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06003393 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003394
John Kessenich21472ae2016-06-04 11:46:33 -06003395 case EHTokIf:
Rex Xu57e65922017-07-04 23:23:40 +08003396 return acceptSelectionStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003397
John Kessenich21472ae2016-06-04 11:46:33 -06003398 case EHTokSwitch:
Rex Xu57e65922017-07-04 23:23:40 +08003399 return acceptSwitchStatement(statement, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06003400
John Kessenich21472ae2016-06-04 11:46:33 -06003401 case EHTokFor:
3402 case EHTokDo:
3403 case EHTokWhile:
steve-lunargf1709e72017-05-02 20:14:50 -06003404 return acceptIterationStatement(statement, attributes);
John Kessenich21472ae2016-06-04 11:46:33 -06003405
3406 case EHTokContinue:
3407 case EHTokBreak:
3408 case EHTokDiscard:
3409 case EHTokReturn:
3410 return acceptJumpStatement(statement);
3411
3412 case EHTokCase:
3413 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003414 case EHTokDefault:
3415 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003416
John Kessenich21472ae2016-06-04 11:46:33 -06003417 case EHTokRightBrace:
3418 // Performance: not strictly necessary, but stops a bunch of hunting early,
3419 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003420 return false;
3421
John Kessenich21472ae2016-06-04 11:46:33 -06003422 default:
John Kessenich0e071192017-06-06 11:37:33 -06003423 return acceptSimpleStatement(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003424 }
3425
John Kessenich5f934b02016-03-13 17:58:25 -06003426 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003427}
3428
John Kessenich21472ae2016-06-04 11:46:33 -06003429// attributes
John Kessenich77ea30b2017-09-30 14:34:50 -06003430// : [zero or more:] bracketed-attribute
3431//
3432// bracketed-attribute:
3433// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
3434// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
3435//
3436// scoped-attribute:
3437// : attribute
3438// | namespace COLON COLON attribute
John Kessenich21472ae2016-06-04 11:46:33 -06003439//
3440// attribute:
3441// : UNROLL
3442// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3443// | FASTOPT
3444// | ALLOW_UAV_CONDITION
3445// | BRANCH
3446// | FLATTEN
3447// | FORCECASE
3448// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003449// | DOMAIN
3450// | EARLYDEPTHSTENCIL
3451// | INSTANCE
3452// | MAXTESSFACTOR
3453// | OUTPUTCONTROLPOINTS
3454// | OUTPUTTOPOLOGY
3455// | PARTITIONING
3456// | PATCHCONSTANTFUNC
3457// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003458//
steve-lunarg1868b142016-10-20 13:07:10 -06003459void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003460{
steve-lunarg1868b142016-10-20 13:07:10 -06003461 // For now, accept the [ XXX(X) ] syntax, but drop all but
3462 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003463 // TODO: subset to correct set? Pass on?
3464 do {
John Kessenich77ea30b2017-09-30 14:34:50 -06003465 HlslToken attributeToken;
steve-lunarg1868b142016-10-20 13:07:10 -06003466
John Kessenich0d2b6de2016-06-05 11:23:11 -06003467 // LEFT_BRACKET?
3468 if (! acceptTokenClass(EHTokLeftBracket))
3469 return;
John Kessenich77ea30b2017-09-30 14:34:50 -06003470 // another LEFT_BRACKET?
3471 bool doubleBrackets = false;
3472 if (acceptTokenClass(EHTokLeftBracket))
3473 doubleBrackets = true;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003474
John Kessenich77ea30b2017-09-30 14:34:50 -06003475 // attribute? (could be namespace; will adjust later)
3476 if (!acceptIdentifier(attributeToken)) {
3477 if (!peekTokenClass(EHTokRightBracket)) {
3478 expected("namespace or attribute identifier");
3479 advanceToken();
3480 }
3481 }
3482
3483 TString nameSpace;
3484 if (acceptTokenClass(EHTokColonColon)) {
3485 // namespace COLON COLON
3486 nameSpace = *attributeToken.string;
3487 // attribute
3488 if (!acceptIdentifier(attributeToken)) {
3489 expected("attribute identifier");
3490 return;
3491 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003492 }
3493
steve-lunarga22f7db2016-11-11 08:17:44 -07003494 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003495
3496 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003497 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003498 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003499
John Kessenich0d2b6de2016-06-05 11:23:11 -06003500 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003501 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003502
steve-lunarga22f7db2016-11-11 08:17:44 -07003503 while (acceptAssignmentExpression(node)) {
3504 expectingExpression = false;
3505 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003506 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003507 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003508 }
3509
steve-lunarga22f7db2016-11-11 08:17:44 -07003510 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003511 if (! acceptTokenClass(EHTokRightParen))
3512 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003513
3514 // Error for partial or missing expression
3515 if (expectingExpression || expressions->getSequence().empty())
3516 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003517 }
3518
3519 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003520 if (!acceptTokenClass(EHTokRightBracket)) {
3521 expected("]");
3522 return;
3523 }
John Kessenich77ea30b2017-09-30 14:34:50 -06003524 // another RIGHT_BRACKET?
3525 if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
3526 expected("]]");
3527 return;
3528 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003529
steve-lunarg1868b142016-10-20 13:07:10 -06003530 // Add any values we found into the attribute map. This accepts
3531 // (and ignores) values not mapping to a known TAttributeType;
John Kessenich77ea30b2017-09-30 14:34:50 -06003532 attributes.setAttribute(nameSpace, attributeToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003533 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003534}
3535
John Kessenich0d2b6de2016-06-05 11:23:11 -06003536// selection_statement
3537// : IF LEFT_PAREN expression RIGHT_PAREN statement
3538// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3539//
Rex Xu57e65922017-07-04 23:23:40 +08003540bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003541{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003542 TSourceLoc loc = token.loc;
3543
Rex Xu57e65922017-07-04 23:23:40 +08003544 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3545
John Kessenich0d2b6de2016-06-05 11:23:11 -06003546 // IF
3547 if (! acceptTokenClass(EHTokIf))
3548 return false;
3549
3550 // so that something declared in the condition is scoped to the lifetimes
3551 // of the then-else statements
3552 parseContext.pushScope();
3553
3554 // LEFT_PAREN expression RIGHT_PAREN
3555 TIntermTyped* condition;
3556 if (! acceptParenExpression(condition))
3557 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003558 condition = parseContext.convertConditionalExpression(loc, condition);
3559 if (condition == nullptr)
3560 return false;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003561
3562 // create the child statements
3563 TIntermNodePair thenElse = { nullptr, nullptr };
3564
John Kessenichf6deacd2017-06-06 19:52:55 -06003565 ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors
3566
John Kessenich0d2b6de2016-06-05 11:23:11 -06003567 // then statement
3568 if (! acceptScopedStatement(thenElse.node1)) {
3569 expected("then statement");
3570 return false;
3571 }
3572
3573 // ELSE
3574 if (acceptTokenClass(EHTokElse)) {
3575 // else statement
3576 if (! acceptScopedStatement(thenElse.node2)) {
3577 expected("else statement");
3578 return false;
3579 }
3580 }
3581
3582 // Put the pieces together
Rex Xu57e65922017-07-04 23:23:40 +08003583 statement = intermediate.addSelection(condition, thenElse, loc, control);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003584 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003585 --parseContext.controlFlowNestingLevel;
John Kessenich0d2b6de2016-06-05 11:23:11 -06003586
3587 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003588}
3589
John Kessenichd02dc5d2016-07-01 00:04:11 -06003590// switch_statement
3591// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3592//
Rex Xu57e65922017-07-04 23:23:40 +08003593bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003594{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003595 // SWITCH
3596 TSourceLoc loc = token.loc;
Rex Xu57e65922017-07-04 23:23:40 +08003597
3598 const TSelectionControl control = parseContext.handleSelectionControl(attributes);
3599
John Kessenichd02dc5d2016-07-01 00:04:11 -06003600 if (! acceptTokenClass(EHTokSwitch))
3601 return false;
3602
3603 // LEFT_PAREN expression RIGHT_PAREN
3604 parseContext.pushScope();
3605 TIntermTyped* switchExpression;
3606 if (! acceptParenExpression(switchExpression)) {
3607 parseContext.popScope();
3608 return false;
3609 }
3610
3611 // compound_statement
3612 parseContext.pushSwitchSequence(new TIntermSequence);
John Kessenichf6deacd2017-06-06 19:52:55 -06003613
3614 ++parseContext.controlFlowNestingLevel;
John Kessenichd02dc5d2016-07-01 00:04:11 -06003615 bool statementOkay = acceptCompoundStatement(statement);
John Kessenichf6deacd2017-06-06 19:52:55 -06003616 --parseContext.controlFlowNestingLevel;
3617
John Kessenichd02dc5d2016-07-01 00:04:11 -06003618 if (statementOkay)
Rex Xu57e65922017-07-04 23:23:40 +08003619 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003620
3621 parseContext.popSwitchSequence();
3622 parseContext.popScope();
3623
3624 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003625}
3626
John Kessenich119f8f62016-06-05 15:44:07 -06003627// iteration_statement
3628// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3629// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3630// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3631//
3632// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
steve-lunargf1709e72017-05-02 20:14:50 -06003633bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003634{
John Kessenich119f8f62016-06-05 15:44:07 -06003635 TSourceLoc loc = token.loc;
3636 TIntermTyped* condition = nullptr;
3637
3638 EHlslTokenClass loop = peek();
3639 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3640
3641 // WHILE or DO or FOR
3642 advanceToken();
steve-lunargf1709e72017-05-02 20:14:50 -06003643
3644 const TLoopControl control = parseContext.handleLoopControl(attributes);
John Kessenich119f8f62016-06-05 15:44:07 -06003645
3646 switch (loop) {
3647 case EHTokWhile:
3648 // so that something declared in the condition is scoped to the lifetime
3649 // of the while sub-statement
John Kessenichf6deacd2017-06-06 19:52:55 -06003650 parseContext.pushScope(); // this only needs to work right if no errors
John Kessenich119f8f62016-06-05 15:44:07 -06003651 parseContext.nestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003652 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003653
3654 // LEFT_PAREN condition RIGHT_PAREN
3655 if (! acceptParenExpression(condition))
3656 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003657 condition = parseContext.convertConditionalExpression(loc, condition);
3658 if (condition == nullptr)
3659 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003660
3661 // statement
3662 if (! acceptScopedStatement(statement)) {
3663 expected("while sub-statement");
3664 return false;
3665 }
3666
3667 parseContext.unnestLooping();
3668 parseContext.popScope();
John Kessenichf6deacd2017-06-06 19:52:55 -06003669 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003670
steve-lunargf1709e72017-05-02 20:14:50 -06003671 statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003672
3673 return true;
3674
3675 case EHTokDo:
John Kessenichf6deacd2017-06-06 19:52:55 -06003676 parseContext.nestLooping(); // this only needs to work right if no errors
3677 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003678
John Kessenich119f8f62016-06-05 15:44:07 -06003679 // statement
John Kessenich0c6f9362017-04-20 11:08:24 -06003680 if (! acceptScopedStatement(statement)) {
John Kessenich119f8f62016-06-05 15:44:07 -06003681 expected("do sub-statement");
3682 return false;
3683 }
3684
John Kessenich119f8f62016-06-05 15:44:07 -06003685 // WHILE
3686 if (! acceptTokenClass(EHTokWhile)) {
3687 expected("while");
3688 return false;
3689 }
3690
3691 // LEFT_PAREN condition RIGHT_PAREN
John Kessenich119f8f62016-06-05 15:44:07 -06003692 if (! acceptParenExpression(condition))
3693 return false;
John Kessenich7e997e22017-03-30 22:09:30 -06003694 condition = parseContext.convertConditionalExpression(loc, condition);
3695 if (condition == nullptr)
3696 return false;
John Kessenich119f8f62016-06-05 15:44:07 -06003697
3698 if (! acceptTokenClass(EHTokSemicolon))
3699 expected(";");
3700
3701 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003702 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003703
steve-lunargf1709e72017-05-02 20:14:50 -06003704 statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003705
3706 return true;
3707
3708 case EHTokFor:
3709 {
3710 // LEFT_PAREN
3711 if (! acceptTokenClass(EHTokLeftParen))
3712 expected("(");
3713
3714 // so that something declared in the condition is scoped to the lifetime
3715 // of the for sub-statement
3716 parseContext.pushScope();
3717
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003718 // initializer
3719 TIntermNode* initNode = nullptr;
John Kessenich0e071192017-06-06 11:37:33 -06003720 if (! acceptSimpleStatement(initNode))
3721 expected("for-loop initializer statement");
John Kessenich119f8f62016-06-05 15:44:07 -06003722
John Kessenichf6deacd2017-06-06 19:52:55 -06003723 parseContext.nestLooping(); // this only needs to work right if no errors
3724 ++parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003725
3726 // condition SEMI_COLON
3727 acceptExpression(condition);
3728 if (! acceptTokenClass(EHTokSemicolon))
3729 expected(";");
John Kessenich7e997e22017-03-30 22:09:30 -06003730 if (condition != nullptr) {
3731 condition = parseContext.convertConditionalExpression(loc, condition);
3732 if (condition == nullptr)
3733 return false;
3734 }
John Kessenich119f8f62016-06-05 15:44:07 -06003735
3736 // iterator SEMI_COLON
3737 TIntermTyped* iterator = nullptr;
3738 acceptExpression(iterator);
3739 if (! acceptTokenClass(EHTokRightParen))
3740 expected(")");
3741
3742 // statement
3743 if (! acceptScopedStatement(statement)) {
3744 expected("for sub-statement");
3745 return false;
3746 }
3747
steve-lunargf1709e72017-05-02 20:14:50 -06003748 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
John Kessenich119f8f62016-06-05 15:44:07 -06003749
3750 parseContext.popScope();
3751 parseContext.unnestLooping();
John Kessenichf6deacd2017-06-06 19:52:55 -06003752 --parseContext.controlFlowNestingLevel;
John Kessenich119f8f62016-06-05 15:44:07 -06003753
3754 return true;
3755 }
3756
3757 default:
3758 return false;
3759 }
John Kessenich21472ae2016-06-04 11:46:33 -06003760}
3761
3762// jump_statement
3763// : CONTINUE SEMICOLON
3764// | BREAK SEMICOLON
3765// | DISCARD SEMICOLON
3766// | RETURN SEMICOLON
3767// | RETURN expression SEMICOLON
3768//
3769bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3770{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003771 EHlslTokenClass jump = peek();
3772 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003773 case EHTokContinue:
3774 case EHTokBreak:
3775 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003776 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003777 advanceToken();
3778 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003779 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003780 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003781 return false;
3782 }
John Kessenich21472ae2016-06-04 11:46:33 -06003783
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003784 switch (jump) {
3785 case EHTokContinue:
3786 statement = intermediate.addBranch(EOpContinue, token.loc);
3787 break;
3788 case EHTokBreak:
3789 statement = intermediate.addBranch(EOpBreak, token.loc);
3790 break;
3791 case EHTokDiscard:
3792 statement = intermediate.addBranch(EOpKill, token.loc);
3793 break;
3794
3795 case EHTokReturn:
3796 {
3797 // expression
3798 TIntermTyped* node;
3799 if (acceptExpression(node)) {
3800 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003801 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003802 } else
3803 statement = intermediate.addBranch(EOpReturn, token.loc);
3804 break;
3805 }
3806
3807 default:
3808 assert(0);
3809 return false;
3810 }
3811
3812 // SEMICOLON
3813 if (! acceptTokenClass(EHTokSemicolon))
3814 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003815
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003816 return true;
3817}
John Kessenich21472ae2016-06-04 11:46:33 -06003818
John Kessenichd02dc5d2016-07-01 00:04:11 -06003819// case_label
3820// : CASE expression COLON
3821//
John Kessenich21472ae2016-06-04 11:46:33 -06003822bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3823{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003824 TSourceLoc loc = token.loc;
3825 if (! acceptTokenClass(EHTokCase))
3826 return false;
3827
3828 TIntermTyped* expression;
3829 if (! acceptExpression(expression)) {
3830 expected("case expression");
3831 return false;
3832 }
3833
3834 if (! acceptTokenClass(EHTokColon)) {
3835 expected(":");
3836 return false;
3837 }
3838
3839 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3840
3841 return true;
3842}
3843
3844// default_label
3845// : DEFAULT COLON
3846//
3847bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3848{
3849 TSourceLoc loc = token.loc;
3850 if (! acceptTokenClass(EHTokDefault))
3851 return false;
3852
3853 if (! acceptTokenClass(EHTokColon)) {
3854 expected(":");
3855 return false;
3856 }
3857
3858 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3859
3860 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003861}
3862
John Kessenich19b92ff2016-06-19 11:50:34 -06003863// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003864// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3865// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003866//
3867void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3868{
3869 arraySizes = nullptr;
3870
steve-lunarg7b211a32016-10-13 12:26:18 -06003871 // Early-out if there aren't any array dimensions
3872 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003873 return;
3874
steve-lunarg7b211a32016-10-13 12:26:18 -06003875 // 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 -06003876 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003877
3878 // Collect each array dimension.
3879 while (acceptTokenClass(EHTokLeftBracket)) {
3880 TSourceLoc loc = token.loc;
3881 TIntermTyped* sizeExpr = nullptr;
3882
John Kessenich057df292017-03-06 18:18:37 -07003883 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003884 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3885
3886 if (! acceptTokenClass(EHTokRightBracket)) {
3887 expected("]");
3888 return;
3889 }
3890
3891 if (hasArraySize) {
3892 TArraySize arraySize;
3893 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3894 arraySizes->addInnerSize(arraySize);
3895 } else {
3896 arraySizes->addInnerSize(0); // sized by initializers.
3897 }
steve-lunarg265c0612016-09-27 10:57:35 -06003898 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003899}
3900
John Kessenich630dd7d2016-06-12 23:52:12 -06003901// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003902// : COLON semantic // optional
3903// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3904// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003905// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003906// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003907//
John Kessenich854fe242017-03-02 14:30:59 -07003908// Return true if any tokens were accepted. That is,
3909// false can be returned on successfully recognizing nothing,
3910// not necessarily meaning bad syntax.
3911//
3912bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003913{
John Kessenich854fe242017-03-02 14:30:59 -07003914 bool found = false;
3915
John Kessenich630dd7d2016-06-12 23:52:12 -06003916 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003917 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003918 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003919 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003920 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003921 if (peekTokenClass(EHTokLayout))
3922 acceptLayoutQualifierList(qualifier);
3923 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003924 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003925 if (! acceptTokenClass(EHTokLeftParen)) {
3926 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003927 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003928 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003929 HlslToken locationToken;
3930 if (! acceptIdentifier(locationToken)) {
3931 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003932 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003933 }
3934 HlslToken componentToken;
3935 if (acceptTokenClass(EHTokDot)) {
3936 if (! acceptIdentifier(componentToken)) {
3937 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003938 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003939 }
3940 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003941 if (! acceptTokenClass(EHTokRightParen)) {
3942 expected(")");
3943 break;
3944 }
John Kessenich7735b942016-09-05 12:40:06 -06003945 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003946 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003947 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003948 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003949 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003950 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3951 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003952 if (! acceptTokenClass(EHTokLeftParen)) {
3953 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003954 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003955 }
John Kessenichb38f0712016-07-30 10:29:54 -06003956 HlslToken registerDesc; // for Type#
3957 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003958 if (! acceptIdentifier(registerDesc)) {
3959 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003960 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003961 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003962 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3963 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003964 // Then we didn't really see the registerDesc yet, it was
3965 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003966 profile = registerDesc;
3967 if (! acceptIdentifier(registerDesc)) {
3968 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003969 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003970 }
3971 }
John Kessenichb38f0712016-07-30 10:29:54 -06003972 int subComponent = 0;
3973 if (acceptTokenClass(EHTokLeftBracket)) {
3974 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3975 if (! peekTokenClass(EHTokIntConstant)) {
3976 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003977 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003978 }
3979 subComponent = token.i;
3980 advanceToken();
3981 if (! acceptTokenClass(EHTokRightBracket)) {
3982 expected("]");
3983 break;
3984 }
3985 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003986 // (COMMA SPACEN)opt
3987 HlslToken spaceDesc;
3988 if (acceptTokenClass(EHTokComma)) {
3989 if (! acceptIdentifier(spaceDesc)) {
3990 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003991 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003992 }
3993 }
3994 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003995 if (! acceptTokenClass(EHTokRightParen)) {
3996 expected(")");
3997 break;
3998 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003999 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06004000 } else {
4001 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06004002 TString semanticUpperCase = *idToken.string;
4003 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
4004 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06004005 }
John Kessenich854fe242017-03-02 14:30:59 -07004006 } else if (peekTokenClass(EHTokLeftAngle)) {
4007 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06004008 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07004009 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06004010 break;
John Kessenich078d7f22016-03-14 10:02:11 -06004011
John Kessenich630dd7d2016-06-12 23:52:12 -06004012 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07004013
4014 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06004015}
4016
John Kessenichb16f7e62017-03-11 19:32:47 -07004017//
4018// Get the stream of tokens from the scanner, but skip all syntactic/semantic
4019// processing.
4020//
4021bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
4022{
4023 if (! peekTokenClass(EHTokLeftBrace))
4024 return false;
4025
4026 int braceCount = 0;
4027
4028 do {
4029 switch (peek()) {
4030 case EHTokLeftBrace:
4031 ++braceCount;
4032 break;
4033 case EHTokRightBrace:
4034 --braceCount;
4035 break;
4036 case EHTokNone:
4037 // End of input before balance { } is bad...
4038 return false;
4039 default:
4040 break;
4041 }
4042
4043 tokens.push_back(token);
4044 advanceToken();
4045 } while (braceCount > 0);
4046
4047 return true;
4048}
4049
John Kessenich0320d092017-06-13 22:22:52 -06004050// Return a string for just the types that can also be declared as an identifier.
4051const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
4052{
4053 switch (tokenClass) {
4054 case EHTokSample: return "sample";
4055 case EHTokHalf: return "half";
4056 case EHTokHalf1x1: return "half1x1";
4057 case EHTokHalf1x2: return "half1x2";
4058 case EHTokHalf1x3: return "half1x3";
4059 case EHTokHalf1x4: return "half1x4";
4060 case EHTokHalf2x1: return "half2x1";
4061 case EHTokHalf2x2: return "half2x2";
4062 case EHTokHalf2x3: return "half2x3";
4063 case EHTokHalf2x4: return "half2x4";
4064 case EHTokHalf3x1: return "half3x1";
4065 case EHTokHalf3x2: return "half3x2";
4066 case EHTokHalf3x3: return "half3x3";
4067 case EHTokHalf3x4: return "half3x4";
4068 case EHTokHalf4x1: return "half4x1";
4069 case EHTokHalf4x2: return "half4x2";
4070 case EHTokHalf4x3: return "half4x3";
4071 case EHTokHalf4x4: return "half4x4";
4072 case EHTokBool: return "bool";
4073 case EHTokFloat: return "float";
4074 case EHTokDouble: return "double";
4075 case EHTokInt: return "int";
4076 case EHTokUint: return "uint";
4077 case EHTokMin16float: return "min16float";
4078 case EHTokMin10float: return "min10float";
4079 case EHTokMin16int: return "min16int";
4080 case EHTokMin12int: return "min12int";
LoopDawg7ee29ba2017-11-27 14:45:36 -07004081 case EHTokConstantBuffer: return "ConstantBuffer";
John Kessenichfd1e8a72017-12-29 20:59:13 -07004082 case EHTokLayout: return "layout";
John Kessenich0320d092017-06-13 22:22:52 -06004083 default:
4084 return nullptr;
4085 }
4086}
4087
John Kesseniche01a9bc2016-03-12 20:11:22 -07004088} // end namespace glslang