blob: 0e54be52a300cc75862268ee9278ee25651453b4 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
John Kessenich927608b2017-01-06 12:34:14 -07002// Copyright (C) 2016 Google, Inc.
3// Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
John Kessenich927608b2017-01-06 12:34:14 -07005// All rights reserved.
John Kesseniche01a9bc2016-03-12 20:11:22 -07006//
John Kessenich927608b2017-01-06 12:34:14 -07007// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
John Kesseniche01a9bc2016-03-12 20:11:22 -070010//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
John Kessenich927608b2017-01-06 12:34:14 -070023// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34// POSSIBILITY OF SUCH DAMAGE.
John Kesseniche01a9bc2016-03-12 20:11:22 -070035//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenichaecd4972016-03-14 10:46:34 -060078// Only process the next token if it is an identifier.
79// Return true if it was an identifier.
80bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
81{
82 if (peekTokenClass(EHTokIdentifier)) {
83 idToken = token;
84 advanceToken();
85 return true;
86 }
87
steve-lunarg5ca85ad2016-12-26 18:45:52 -070088 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
89 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
90 // valid identifier, nor is "linear". This code special cases the known instances of this, so
91 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -070092
steve-lunarg5ca85ad2016-12-26 18:45:52 -070093 TString* idString = nullptr;
94 switch (peek()) {
95 case EHTokSample: idString = NewPoolTString("sample"); break;
96 case EHTokHalf: idString = NewPoolTString("half"); break;
97 case EHTokBool: idString = NewPoolTString("bool"); break;
98 case EHTokFloat: idString = NewPoolTString("float"); break;
99 case EHTokDouble: idString = NewPoolTString("double"); break;
100 case EHTokInt: idString = NewPoolTString("int"); break;
101 case EHTokUint: idString = NewPoolTString("uint"); break;
102 case EHTokMin16float: idString = NewPoolTString("min16float"); break;
103 case EHTokMin10float: idString = NewPoolTString("min10float"); break;
104 case EHTokMin16int: idString = NewPoolTString("min16int"); break;
105 case EHTokMin12int: idString = NewPoolTString("min12int"); break;
106 default:
107 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700108 }
109
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700110 token.string = idString;
111 token.tokenClass = EHTokIdentifier;
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700112 idToken = token;
113
114 advanceToken();
115
116 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600117}
118
John Kesseniche01a9bc2016-03-12 20:11:22 -0700119// compilationUnit
120// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600121// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700122//
123bool HlslGrammar::acceptCompilationUnit()
124{
John Kessenichd016be12016-03-13 11:24:20 -0600125 TIntermNode* unitNode = nullptr;
126
John Kessenich9c86c6a2016-05-03 22:49:24 -0600127 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600128 // HLSL allows semicolons between global declarations, e.g, between functions.
129 if (acceptTokenClass(EHTokSemicolon))
130 continue;
131
John Kessenichd016be12016-03-13 11:24:20 -0600132 // externalDeclaration
John Kessenichca71d942017-03-07 20:44:09 -0700133 if (! acceptDeclaration(unitNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700134 return false;
135 }
136
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
LoopDawg4886f692016-06-29 10:58:58 -0600145// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700146// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600147//
148// sampler_state_assignment
149// : sampler_state_identifier EQUAL value SEMICOLON
150//
151// sampler_state_identifier
152// : ADDRESSU
153// | ADDRESSV
154// | ADDRESSW
155// | BORDERCOLOR
156// | FILTER
157// | MAXANISOTROPY
158// | MAXLOD
159// | MINLOD
160// | MIPLODBIAS
161//
162bool HlslGrammar::acceptSamplerState()
163{
164 // TODO: this should be genericized to accept a list of valid tokens and
165 // return token/value pairs. Presently it is specific to texture values.
166
167 if (! acceptTokenClass(EHTokLeftBrace))
168 return true;
169
170 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700171
LoopDawg4886f692016-06-29 10:58:58 -0600172 do {
173 // read state name
174 HlslToken state;
175 if (! acceptIdentifier(state))
176 break; // end of list
177
178 // FXC accepts any case
179 TString stateName = *state.string;
180 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
181
182 if (! acceptTokenClass(EHTokAssign)) {
183 expected("assign");
184 return false;
185 }
186
187 if (stateName == "minlod" || stateName == "maxlod") {
188 if (! peekTokenClass(EHTokIntConstant)) {
189 expected("integer");
190 return false;
191 }
192
193 TIntermTyped* lod = nullptr;
194 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
195 return false;
196 } else if (stateName == "maxanisotropy") {
197 if (! peekTokenClass(EHTokIntConstant)) {
198 expected("integer");
199 return false;
200 }
201
202 TIntermTyped* maxAnisotropy = nullptr;
203 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
204 return false;
205 } else if (stateName == "filter") {
206 HlslToken filterMode;
207 if (! acceptIdentifier(filterMode)) {
208 expected("filter mode");
209 return false;
210 }
211 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
212 HlslToken addrMode;
213 if (! acceptIdentifier(addrMode)) {
214 expected("texture address mode");
215 return false;
216 }
217 } else if (stateName == "miplodbias") {
218 TIntermTyped* lodBias = nullptr;
219 if (! acceptLiteral(lodBias)) {
220 expected("lod bias");
221 return false;
222 }
223 } else if (stateName == "bordercolor") {
224 return false;
225 } else {
226 expected("texture state");
227 return false;
228 }
229
230 // SEMICOLON
231 if (! acceptTokenClass(EHTokSemicolon)) {
232 expected("semicolon");
233 return false;
234 }
235 } while (true);
236
237 if (! acceptTokenClass(EHTokRightBrace))
238 return false;
239
240 return true;
241}
242
243// sampler_declaration_dx9
244// : SAMPLER identifier EQUAL sampler_type sampler_state
245//
John Kesseniche4821e42016-07-16 10:19:43 -0600246bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600247{
248 if (! acceptTokenClass(EHTokSampler))
249 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700250
LoopDawg4886f692016-06-29 10:58:58 -0600251 // TODO: remove this when DX9 style declarations are implemented.
252 unimplemented("Direct3D 9 sampler declaration");
253
254 // read sampler name
255 HlslToken name;
256 if (! acceptIdentifier(name)) {
257 expected("sampler name");
258 return false;
259 }
260
261 if (! acceptTokenClass(EHTokAssign)) {
262 expected("=");
263 return false;
264 }
265
266 return false;
267}
268
John Kesseniche01a9bc2016-03-12 20:11:22 -0700269// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600270// : sampler_declaration_dx9 post_decls SEMICOLON
271// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600272// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600273// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600274// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700275//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600276// declarator_list
277// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600278//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600279// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600280// : identifier array_specifier post_decls
281// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600282// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600283//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600284// Parsing has to go pretty far in to know whether it's a variable, prototype, or
285// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600286// as above. (The 'identifier' in the first item in init_declarator list is the
287// same as 'identifier' for function declarations.)
288//
John Kessenichca71d942017-03-07 20:44:09 -0700289// This can generate more than one subtree, one per initializer or a function body.
290// All initializer subtrees are put in their own aggregate node, making one top-level
291// node for all the initializers. Each function created is a top-level node to grow
292// into the passed-in nodeList.
John Kessenichd016be12016-03-13 11:24:20 -0600293//
John Kessenichca71d942017-03-07 20:44:09 -0700294// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
295// each top-level node the declaration creates. Otherwise, if only one top-level
296// node in generated here, that is want is returned in nodeList.
John Kessenich02467d82017-01-19 15:41:47 -0700297//
John Kessenichca71d942017-03-07 20:44:09 -0700298bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700299{
John Kessenich54ee28f2017-03-11 14:13:00 -0700300 bool declarator_list = false; // true when processing comma separation
John Kessenichd016be12016-03-13 11:24:20 -0600301
steve-lunarg1868b142016-10-20 13:07:10 -0600302 // attributes
John Kessenich088d52b2017-03-11 17:55:28 -0700303 TFunctionDeclarator declarator;
304 acceptAttributes(declarator.attributes);
steve-lunarg1868b142016-10-20 13:07:10 -0600305
John Kessenich5e69ec62016-07-05 00:02:40 -0600306 // typedef
307 bool typedefDecl = acceptTokenClass(EHTokTypedef);
308
John Kesseniche82061d2016-09-27 14:38:57 -0600309 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600310
311 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600312 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
313 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
314 // HLSL shaders, this will have to be a master level switch
315 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700316 // For that reason, this line is commented out
John Kessenichca71d942017-03-07 20:44:09 -0700317 // if (acceptSamplerDeclarationDX9(declaredType))
318 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600319
320 // fully_specified_type
John Kessenich54ee28f2017-03-11 14:13:00 -0700321 if (! acceptFullySpecifiedType(declaredType, nodeList))
John Kessenich87142c72016-03-12 20:24:24 -0700322 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600323
John Kessenich87142c72016-03-12 20:24:24 -0700324 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600325 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700326 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600327 while (acceptIdentifier(idToken)) {
John Kessenich78388722017-03-08 18:53:51 -0700328 if (peekTokenClass(EHTokLeftParen)) {
329 // looks like function parameters
330 TString* fnName = idToken.string;
steve-lunargf1e0c872016-10-31 15:13:43 -0600331
John Kessenich78388722017-03-08 18:53:51 -0700332 // Potentially rename shader entry point function. No-op most of the time.
333 parseContext.renameShaderFunction(fnName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600334
John Kessenich78388722017-03-08 18:53:51 -0700335 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -0700336 declarator.function = new TFunction(fnName, declaredType);
337 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700338 expected("function parameter list");
339 return false;
340 }
341
John Kessenich630dd7d2016-06-12 23:52:12 -0600342 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700343 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600344
John Kessenichd5ed0b62016-07-04 17:32:45 -0600345 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700346 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600347 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700348 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600349 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600350 if (typedefDecl)
351 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700352 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600353 } else {
354 if (typedefDecl)
355 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700356 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600357 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600358 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600359 // A variable declaration. Fix the storage qualifier if it's a global.
360 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
361 declaredType.getQualifier().storage = EvqUniform;
362
John Kessenichecba76f2017-01-06 00:34:48 -0700363 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600364 // the number of types can expand when arrayness is different.
365 TType variableType;
366 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600367
John Kesseniche82061d2016-09-27 14:38:57 -0600368 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600369 TArraySizes* arraySizes = nullptr;
370 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600371
John Kesseniche82061d2016-09-27 14:38:57 -0600372 // Fix arrayness in the variableType
373 if (declaredType.isImplicitlySizedArray()) {
374 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
375 // of different sizes, for this case sharing the shallow copy of arrayness
376 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
377 variableType.newArraySizes(declaredType.getArraySizes());
378 }
379 if (arraySizes || variableType.isArray()) {
380 // In the most general case, arrayness is potentially coming both from the
381 // declared type and from the variable: "int[] a[];" or just one or the other.
382 // Merge it all to the variableType, so all arrayness is part of the variableType.
383 parseContext.arrayDimMerge(variableType, arraySizes);
384 }
385
LoopDawg4886f692016-06-29 10:58:58 -0600386 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600387 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600388 if (! acceptSamplerState())
389 return false;
390 }
391
John Kessenichd5ed0b62016-07-04 17:32:45 -0600392 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600393 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600394
395 // EQUAL assignment_expression
396 TIntermTyped* expressionNode = nullptr;
397 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600398 if (typedefDecl)
399 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600400 if (! acceptAssignmentExpression(expressionNode)) {
401 expected("initializer");
402 return false;
403 }
404 }
405
John Kessenich6dbc0a72016-09-27 19:13:05 -0600406 // TODO: things scoped within an annotation need their own name space;
407 // TODO: strings are not yet handled.
408 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
409 if (typedefDecl)
410 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
411 else if (variableType.getBasicType() == EbtBlock)
steve-lunargdd8287a2017-02-23 18:04:12 -0700412 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600413 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700414 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600415 // this isn't really an individual variable, but a member of the $Global buffer
416 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
417 } else {
418 // Declare the variable and add any initializer code to the AST.
419 // The top-level node is always made into an aggregate, as that's
420 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700421 initializers = intermediate.growAggregate(initializers,
422 parseContext.declareVariable(idToken.loc, *idToken.string, variableType, expressionNode),
423 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600424 }
425 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600426 }
John Kessenich5f934b02016-03-13 17:58:25 -0600427 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600428
429 if (acceptTokenClass(EHTokComma)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700430 declarator_list = true;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600431 continue;
432 }
433 };
434
John Kessenichca71d942017-03-07 20:44:09 -0700435 // The top-level initializer node is a sequence.
436 if (initializers != nullptr)
437 initializers->setOperator(EOpSequence);
438
439 // Add the initializers' aggregate to the nodeList we were handed.
440 if (nodeList)
441 nodeList = intermediate.growAggregate(nodeList, initializers);
442 else
443 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700444
John Kessenich078d7f22016-03-14 10:02:11 -0600445 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600446 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700447 // This may have been a false detection of what appeared to be a declaration, but
448 // was actually an assignment such as "float = 4", where "float" is an identifier.
449 // We put the token back to let further parsing happen for cases where that may
450 // happen. This errors on the side of caution, and mostly triggers the error.
451
452 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
453 recedeToken();
454 else
455 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600456 return false;
457 }
John Kessenichecba76f2017-01-06 00:34:48 -0700458
John Kesseniche01a9bc2016-03-12 20:11:22 -0700459 return true;
460}
461
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600462// control_declaration
463// : fully_specified_type identifier EQUAL expression
464//
465bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
466{
467 node = nullptr;
468
469 // fully_specified_type
470 TType type;
471 if (! acceptFullySpecifiedType(type))
472 return false;
473
John Kessenich057df292017-03-06 18:18:37 -0700474 // filter out type casts
475 if (peekTokenClass(EHTokLeftParen)) {
476 recedeToken();
477 return false;
478 }
479
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600480 // identifier
481 HlslToken idToken;
482 if (! acceptIdentifier(idToken)) {
483 expected("identifier");
484 return false;
485 }
486
487 // EQUAL
488 TIntermTyped* expressionNode = nullptr;
489 if (! acceptTokenClass(EHTokAssign)) {
490 expected("=");
491 return false;
492 }
493
494 // expression
495 if (! acceptExpression(expressionNode)) {
496 expected("initializer");
497 return false;
498 }
499
John Kesseniche82061d2016-09-27 14:38:57 -0600500 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600501
502 return true;
503}
504
John Kessenich87142c72016-03-12 20:24:24 -0700505// fully_specified_type
506// : type_specifier
507// | type_qualifier type_specifier
508//
509bool HlslGrammar::acceptFullySpecifiedType(TType& type)
510{
John Kessenich54ee28f2017-03-11 14:13:00 -0700511 TIntermNode* nodeList = nullptr;
512 return acceptFullySpecifiedType(type, nodeList);
513}
514bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
515{
John Kessenich87142c72016-03-12 20:24:24 -0700516 // type_qualifier
517 TQualifier qualifier;
518 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600519 if (! acceptQualifier(qualifier))
520 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600521 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700522
523 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700524 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700525 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700526 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700527 // qualifier. Back it out, if we did.
528 if (qualifier.sample)
529 recedeToken();
530
John Kessenich87142c72016-03-12 20:24:24 -0700531 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700532 }
John Kessenich3d157c52016-07-25 16:05:33 -0600533 if (type.getBasicType() == EbtBlock) {
534 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600535 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600536 // further, it can create an anonymous instance of the block
537 if (peekTokenClass(EHTokSemicolon))
538 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600539 } else {
540 // Some qualifiers are set when parsing the type. Merge those with
541 // whatever comes from acceptQualifier.
542 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700543
steve-lunargbb0183f2016-10-04 16:58:14 -0600544 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600545 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700546
steve-lunargd3947d22017-03-19 12:40:12 -0600547 // Propagate sampler readonly qualifier for buffers
548 if (type.getBasicType() == EbtSampler)
549 qualifier.readonly = type.getQualifier().readonly;
550
steve-lunarg5da1f032017-02-12 17:50:28 -0700551 if (type.getQualifier().storage == EvqVaryingOut ||
552 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700553 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700554 qualifier.readonly = type.getQualifier().readonly;
555 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700556
557 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600558 }
John Kessenich87142c72016-03-12 20:24:24 -0700559
560 return true;
561}
562
John Kessenich630dd7d2016-06-12 23:52:12 -0600563// type_qualifier
564// : qualifier qualifier ...
565//
566// Zero or more of these, so this can't return false.
567//
John Kessenichb9e39122016-08-17 10:22:08 -0600568bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700569{
John Kessenich630dd7d2016-06-12 23:52:12 -0600570 do {
571 switch (peek()) {
572 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600573 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600574 break;
575 case EHTokExtern:
576 // TODO: no meaning in glslang?
577 break;
578 case EHTokShared:
579 // TODO: hint
580 break;
581 case EHTokGroupShared:
582 qualifier.storage = EvqShared;
583 break;
584 case EHTokUniform:
585 qualifier.storage = EvqUniform;
586 break;
587 case EHTokConst:
588 qualifier.storage = EvqConst;
589 break;
590 case EHTokVolatile:
591 qualifier.volatil = true;
592 break;
593 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600594 qualifier.smooth = true;
595 break;
596 case EHTokCentroid:
597 qualifier.centroid = true;
598 break;
599 case EHTokNointerpolation:
600 qualifier.flat = true;
601 break;
602 case EHTokNoperspective:
603 qualifier.nopersp = true;
604 break;
605 case EHTokSample:
606 qualifier.sample = true;
607 break;
608 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600609 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600610 break;
611 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600612 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600613 break;
614 case EHTokPrecise:
615 qualifier.noContraction = true;
616 break;
LoopDawg9249c702016-07-12 20:44:32 -0600617 case EHTokIn:
618 qualifier.storage = EvqIn;
619 break;
620 case EHTokOut:
621 qualifier.storage = EvqOut;
622 break;
623 case EHTokInOut:
624 qualifier.storage = EvqInOut;
625 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600626 case EHTokLayout:
627 if (! acceptLayoutQualifierList(qualifier))
628 return false;
629 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700630 case EHTokGloballyCoherent:
631 qualifier.coherent = true;
632 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600633 case EHTokInline:
634 // TODO: map this to SPIR-V function control
635 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700636
637 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
638 // for output variables.
639 case EHTokPoint:
640 qualifier.storage = EvqIn;
641 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
642 return false;
643 break;
644 case EHTokLine:
645 qualifier.storage = EvqIn;
646 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
647 return false;
648 break;
649 case EHTokTriangle:
650 qualifier.storage = EvqIn;
651 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
652 return false;
653 break;
654 case EHTokLineAdj:
655 qualifier.storage = EvqIn;
656 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
657 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700658 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700659 case EHTokTriangleAdj:
660 qualifier.storage = EvqIn;
661 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
662 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700663 break;
664
John Kessenich630dd7d2016-06-12 23:52:12 -0600665 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600666 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600667 }
668 advanceToken();
669 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700670}
671
John Kessenichb9e39122016-08-17 10:22:08 -0600672// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600673// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600674//
675// layout_qualifier
676// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600677// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600678//
679// Zero or more of these, so this can't return false.
680//
681bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
682{
683 if (! acceptTokenClass(EHTokLayout))
684 return false;
685
686 // LEFT_PAREN
687 if (! acceptTokenClass(EHTokLeftParen))
688 return false;
689
690 do {
691 // identifier
692 HlslToken idToken;
693 if (! acceptIdentifier(idToken))
694 break;
695
696 // EQUAL expression
697 if (acceptTokenClass(EHTokAssign)) {
698 TIntermTyped* expr;
699 if (! acceptConditionalExpression(expr)) {
700 expected("expression");
701 return false;
702 }
703 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
704 } else
705 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
706
707 // COMMA
708 if (! acceptTokenClass(EHTokComma))
709 break;
710 } while (true);
711
712 // RIGHT_PAREN
713 if (! acceptTokenClass(EHTokRightParen)) {
714 expected(")");
715 return false;
716 }
717
718 return true;
719}
720
LoopDawg6daaa4f2016-06-23 19:13:48 -0600721// template_type
722// : FLOAT
723// | DOUBLE
724// | INT
725// | DWORD
726// | UINT
727// | BOOL
728//
steve-lunargf49cdf42016-11-17 15:04:20 -0700729bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600730{
731 switch (peek()) {
732 case EHTokFloat:
733 basicType = EbtFloat;
734 break;
735 case EHTokDouble:
736 basicType = EbtDouble;
737 break;
738 case EHTokInt:
739 case EHTokDword:
740 basicType = EbtInt;
741 break;
742 case EHTokUint:
743 basicType = EbtUint;
744 break;
745 case EHTokBool:
746 basicType = EbtBool;
747 break;
748 default:
749 return false;
750 }
751
752 advanceToken();
753
754 return true;
755}
756
757// vector_template_type
758// : VECTOR
759// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
760//
761bool HlslGrammar::acceptVectorTemplateType(TType& type)
762{
763 if (! acceptTokenClass(EHTokVector))
764 return false;
765
766 if (! acceptTokenClass(EHTokLeftAngle)) {
767 // in HLSL, 'vector' alone means float4.
768 new(&type) TType(EbtFloat, EvqTemporary, 4);
769 return true;
770 }
771
772 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700773 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600774 expected("scalar type");
775 return false;
776 }
777
778 // COMMA
779 if (! acceptTokenClass(EHTokComma)) {
780 expected(",");
781 return false;
782 }
783
784 // integer
785 if (! peekTokenClass(EHTokIntConstant)) {
786 expected("literal integer");
787 return false;
788 }
789
790 TIntermTyped* vecSize;
791 if (! acceptLiteral(vecSize))
792 return false;
793
794 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
795
796 new(&type) TType(basicType, EvqTemporary, vecSizeI);
797
798 if (vecSizeI == 1)
799 type.makeVector();
800
801 if (!acceptTokenClass(EHTokRightAngle)) {
802 expected("right angle bracket");
803 return false;
804 }
805
806 return true;
807}
808
809// matrix_template_type
810// : MATRIX
811// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
812//
813bool HlslGrammar::acceptMatrixTemplateType(TType& type)
814{
815 if (! acceptTokenClass(EHTokMatrix))
816 return false;
817
818 if (! acceptTokenClass(EHTokLeftAngle)) {
819 // in HLSL, 'matrix' alone means float4x4.
820 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
821 return true;
822 }
823
824 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700825 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600826 expected("scalar type");
827 return false;
828 }
829
830 // COMMA
831 if (! acceptTokenClass(EHTokComma)) {
832 expected(",");
833 return false;
834 }
835
836 // integer rows
837 if (! peekTokenClass(EHTokIntConstant)) {
838 expected("literal integer");
839 return false;
840 }
841
842 TIntermTyped* rows;
843 if (! acceptLiteral(rows))
844 return false;
845
846 // COMMA
847 if (! acceptTokenClass(EHTokComma)) {
848 expected(",");
849 return false;
850 }
John Kessenichecba76f2017-01-06 00:34:48 -0700851
LoopDawg6daaa4f2016-06-23 19:13:48 -0600852 // integer cols
853 if (! peekTokenClass(EHTokIntConstant)) {
854 expected("literal integer");
855 return false;
856 }
857
858 TIntermTyped* cols;
859 if (! acceptLiteral(cols))
860 return false;
861
862 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600863 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
864 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600865
866 if (!acceptTokenClass(EHTokRightAngle)) {
867 expected("right angle bracket");
868 return false;
869 }
870
871 return true;
872}
873
steve-lunargf49cdf42016-11-17 15:04:20 -0700874// layout_geometry
875// : LINESTREAM
876// | POINTSTREAM
877// | TRIANGLESTREAM
878//
879bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
880{
881 // read geometry type
882 const EHlslTokenClass geometryType = peek();
883
884 switch (geometryType) {
885 case EHTokPointStream: geometry = ElgPoints; break;
886 case EHTokLineStream: geometry = ElgLineStrip; break;
887 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
888 default:
889 return false; // not a layout geometry
890 }
891
892 advanceToken(); // consume the layout keyword
893 return true;
894}
895
steve-lunarg858c9282017-01-07 08:54:10 -0700896// tessellation_decl_type
897// : INPUTPATCH
898// | OUTPUTPATCH
899//
900bool HlslGrammar::acceptTessellationDeclType()
901{
902 // read geometry type
903 const EHlslTokenClass tessType = peek();
904
905 switch (tessType) {
906 case EHTokInputPatch: break;
907 case EHTokOutputPatch: break;
908 default:
909 return false; // not a tessellation decl
910 }
911
912 advanceToken(); // consume the keyword
913 return true;
914}
915
916// tessellation_patch_template_type
917// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
918//
919bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
920{
921 if (! acceptTessellationDeclType())
922 return false;
923
924 if (! acceptTokenClass(EHTokLeftAngle))
925 return false;
926
927 if (! acceptType(type)) {
928 expected("tessellation patch type");
929 return false;
930 }
931
932 if (! acceptTokenClass(EHTokComma))
933 return false;
934
935 // integer size
936 if (! peekTokenClass(EHTokIntConstant)) {
937 expected("literal integer");
938 return false;
939 }
940
941 TIntermTyped* size;
942 if (! acceptLiteral(size))
943 return false;
944
945 TArraySizes* arraySizes = new TArraySizes;
946 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
947 type.newArraySizes(*arraySizes);
948
949 if (! acceptTokenClass(EHTokRightAngle)) {
950 expected("right angle bracket");
951 return false;
952 }
953
954 return true;
955}
956
steve-lunargf49cdf42016-11-17 15:04:20 -0700957// stream_out_template_type
958// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
959//
960bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
961{
962 geometry = ElgNone;
963
964 if (! acceptOutputPrimitiveGeometry(geometry))
965 return false;
966
967 if (! acceptTokenClass(EHTokLeftAngle))
968 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700969
steve-lunargf49cdf42016-11-17 15:04:20 -0700970 if (! acceptType(type)) {
971 expected("stream output type");
972 return false;
973 }
974
975 type.getQualifier().storage = EvqVaryingOut;
976
977 if (! acceptTokenClass(EHTokRightAngle)) {
978 expected("right angle bracket");
979 return false;
980 }
981
982 return true;
983}
John Kessenichecba76f2017-01-06 00:34:48 -0700984
John Kessenicha1e2d492016-09-20 13:22:58 -0600985// annotations
986// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600987//
John Kessenicha1e2d492016-09-20 13:22:58 -0600988bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600989{
John Kessenicha1e2d492016-09-20 13:22:58 -0600990 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600991 return false;
992
John Kessenicha1e2d492016-09-20 13:22:58 -0600993 // note that we are nesting a name space
994 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600995
996 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
997 do {
998 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
999 while (acceptTokenClass(EHTokSemicolon))
1000 ;
1001
1002 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001003 break;
John Kessenich86f71382016-09-19 20:23:18 -06001004
1005 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001006 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001007 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001008 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001009 return false;
1010 }
1011 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001012
1013 parseContext.unnestAnnotations();
1014 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001015}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001016
LoopDawg4886f692016-06-29 10:58:58 -06001017// sampler_type
1018// : SAMPLER
1019// | SAMPLER1D
1020// | SAMPLER2D
1021// | SAMPLER3D
1022// | SAMPLERCUBE
1023// | SAMPLERSTATE
1024// | SAMPLERCOMPARISONSTATE
1025bool HlslGrammar::acceptSamplerType(TType& type)
1026{
1027 // read sampler type
1028 const EHlslTokenClass samplerType = peek();
1029
LoopDawga78b0292016-07-19 14:28:05 -06001030 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001031 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001032
LoopDawga78b0292016-07-19 14:28:05 -06001033 bool isShadow = false;
1034
LoopDawg4886f692016-06-29 10:58:58 -06001035 switch (samplerType) {
1036 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001037 case EHTokSampler1d: /*dim = Esd1D*/; break;
1038 case EHTokSampler2d: /*dim = Esd2D*/; break;
1039 case EHTokSampler3d: /*dim = Esd3D*/; break;
1040 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001041 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001042 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001043 default:
1044 return false; // not a sampler declaration
1045 }
1046
1047 advanceToken(); // consume the sampler type keyword
1048
1049 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001050
1051 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001052 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001053
1054 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1055
1056 return true;
1057}
1058
1059// texture_type
1060// | BUFFER
1061// | TEXTURE1D
1062// | TEXTURE1DARRAY
1063// | TEXTURE2D
1064// | TEXTURE2DARRAY
1065// | TEXTURE3D
1066// | TEXTURECUBE
1067// | TEXTURECUBEARRAY
1068// | TEXTURE2DMS
1069// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001070// | RWBUFFER
1071// | RWTEXTURE1D
1072// | RWTEXTURE1DARRAY
1073// | RWTEXTURE2D
1074// | RWTEXTURE2DARRAY
1075// | RWTEXTURE3D
1076
LoopDawg4886f692016-06-29 10:58:58 -06001077bool HlslGrammar::acceptTextureType(TType& type)
1078{
1079 const EHlslTokenClass textureType = peek();
1080
1081 TSamplerDim dim = EsdNone;
1082 bool array = false;
1083 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001084 bool image = false;
steve-lunargcf2e7272017-03-17 13:19:42 -06001085 bool readonly = false;
LoopDawg4886f692016-06-29 10:58:58 -06001086
1087 switch (textureType) {
steve-lunargcf2e7272017-03-17 13:19:42 -06001088 case EHTokTexture1d: dim = Esd1D; break;
1089 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1090 case EHTokTexture2d: dim = Esd2D; break;
1091 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1092 case EHTokTexture3d: dim = Esd3D; break;
1093 case EHTokTextureCube: dim = EsdCube; break;
1094 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1095 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1096 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1097 case EHTokBuffer: dim = EsdBuffer; readonly=true; image=true; break;
1098 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1099 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1100 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1101 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1102 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1103 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001104 default:
1105 return false; // not a texture declaration
1106 }
1107
1108 advanceToken(); // consume the texture object keyword
1109
1110 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001111
LoopDawg4886f692016-06-29 10:58:58 -06001112 TIntermTyped* msCount = nullptr;
1113
steve-lunargbb0183f2016-10-04 16:58:14 -06001114 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001115 if (acceptTokenClass(EHTokLeftAngle)) {
1116 if (! acceptType(txType)) {
1117 expected("scalar or vector type");
1118 return false;
1119 }
1120
1121 const TBasicType basicRetType = txType.getBasicType() ;
1122
1123 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1124 unimplemented("basic type in texture");
1125 return false;
1126 }
1127
steve-lunargd53f7172016-07-27 15:46:48 -06001128 // Buffers can handle small mats if they fit in 4 components
1129 if (dim == EsdBuffer && txType.isMatrix()) {
1130 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1131 expected("components < 4 in matrix buffer type");
1132 return false;
1133 }
1134
1135 // TODO: except we don't handle it yet...
1136 unimplemented("matrix type in buffer");
1137 return false;
1138 }
1139
LoopDawg4886f692016-06-29 10:58:58 -06001140 if (!txType.isScalar() && !txType.isVector()) {
1141 expected("scalar or vector type");
1142 return false;
1143 }
1144
LoopDawg4886f692016-06-29 10:58:58 -06001145 if (ms && acceptTokenClass(EHTokComma)) {
1146 // read sample count for multisample types, if given
1147 if (! peekTokenClass(EHTokIntConstant)) {
1148 expected("multisample count");
1149 return false;
1150 }
1151
1152 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1153 return false;
1154 }
1155
1156 if (! acceptTokenClass(EHTokRightAngle)) {
1157 expected("right angle bracket");
1158 return false;
1159 }
1160 } else if (ms) {
1161 expected("texture type for multisample");
1162 return false;
steve-lunargcf2e7272017-03-17 13:19:42 -06001163 } else if (image && !readonly) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001164 expected("type for RWTexture/RWBuffer");
1165 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001166 }
1167
1168 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001169 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001170
1171 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001172 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001173
steve-lunarg4f2da272016-10-10 15:24:57 -06001174 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1175 if (image || dim == EsdBuffer)
1176 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001177
1178 // Non-image Buffers are combined
1179 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001180 sampler.set(txType.getBasicType(), dim, array);
1181 } else {
1182 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001183 if (image) {
1184 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1185 } else {
1186 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1187 }
steve-lunargd53f7172016-07-27 15:46:48 -06001188 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001189
1190 // Remember the declared vector size.
1191 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001192
LoopDawg4886f692016-06-29 10:58:58 -06001193 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1194
LoopDawg4886f692016-06-29 10:58:58 -06001195 type.getQualifier().layoutFormat = format;
steve-lunargcf2e7272017-03-17 13:19:42 -06001196 type.getQualifier().readonly = readonly;
LoopDawg4886f692016-06-29 10:58:58 -06001197
1198 return true;
1199}
1200
John Kessenich87142c72016-03-12 20:24:24 -07001201// If token is for a type, update 'type' with the type information,
1202// and return true and advance.
1203// Otherwise, return false, and don't advance
1204bool HlslGrammar::acceptType(TType& type)
1205{
John Kessenich54ee28f2017-03-11 14:13:00 -07001206 TIntermNode* nodeList = nullptr;
1207 return acceptType(type, nodeList);
1208}
1209bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1210{
steve-lunarg3226b082016-10-26 19:18:55 -06001211 // Basic types for min* types, broken out here in case of future
1212 // changes, e.g, to use native halfs.
1213 static const TBasicType min16float_bt = EbtFloat;
1214 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001215 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001216 static const TBasicType min16int_bt = EbtInt;
1217 static const TBasicType min12int_bt = EbtInt;
1218 static const TBasicType min16uint_bt = EbtUint;
1219
John Kessenich9c86c6a2016-05-03 22:49:24 -06001220 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001221 case EHTokVector:
1222 return acceptVectorTemplateType(type);
1223 break;
1224
1225 case EHTokMatrix:
1226 return acceptMatrixTemplateType(type);
1227 break;
1228
steve-lunargf49cdf42016-11-17 15:04:20 -07001229 case EHTokPointStream: // fall through
1230 case EHTokLineStream: // ...
1231 case EHTokTriangleStream: // ...
1232 {
1233 TLayoutGeometry geometry;
1234 if (! acceptStreamOutTemplateType(type, geometry))
1235 return false;
1236
1237 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1238 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001239
steve-lunargf49cdf42016-11-17 15:04:20 -07001240 return true;
1241 }
1242
steve-lunarg858c9282017-01-07 08:54:10 -07001243 case EHTokInputPatch: // fall through
1244 case EHTokOutputPatch: // ...
1245 {
1246 if (! acceptTessellationPatchTemplateType(type))
1247 return false;
1248
1249 return true;
1250 }
1251
LoopDawg4886f692016-06-29 10:58:58 -06001252 case EHTokSampler: // fall through
1253 case EHTokSampler1d: // ...
1254 case EHTokSampler2d: // ...
1255 case EHTokSampler3d: // ...
1256 case EHTokSamplerCube: // ...
1257 case EHTokSamplerState: // ...
1258 case EHTokSamplerComparisonState: // ...
1259 return acceptSamplerType(type);
1260 break;
1261
1262 case EHTokBuffer: // fall through
1263 case EHTokTexture1d: // ...
1264 case EHTokTexture1darray: // ...
1265 case EHTokTexture2d: // ...
1266 case EHTokTexture2darray: // ...
1267 case EHTokTexture3d: // ...
1268 case EHTokTextureCube: // ...
1269 case EHTokTextureCubearray: // ...
1270 case EHTokTexture2DMS: // ...
1271 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001272 case EHTokRWTexture1d: // ...
1273 case EHTokRWTexture1darray: // ...
1274 case EHTokRWTexture2d: // ...
1275 case EHTokRWTexture2darray: // ...
1276 case EHTokRWTexture3d: // ...
1277 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001278 return acceptTextureType(type);
1279 break;
1280
steve-lunarg5da1f032017-02-12 17:50:28 -07001281 case EHTokAppendStructuredBuffer:
1282 case EHTokByteAddressBuffer:
1283 case EHTokConsumeStructuredBuffer:
1284 case EHTokRWByteAddressBuffer:
1285 case EHTokRWStructuredBuffer:
1286 case EHTokStructuredBuffer:
1287 return acceptStructBufferType(type);
1288 break;
1289
John Kessenich27ffb292017-03-03 17:01:01 -07001290 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001291 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001292 case EHTokCBuffer:
1293 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001294 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001295
1296 case EHTokIdentifier:
1297 // An identifier could be for a user-defined type.
1298 // Note we cache the symbol table lookup, to save for a later rule
1299 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001300 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001301 advanceToken();
1302 return true;
1303 } else
1304 return false;
1305
John Kessenich71351de2016-06-08 12:50:56 -06001306 case EHTokVoid:
1307 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001308 break;
John Kessenich71351de2016-06-08 12:50:56 -06001309
John Kessenicha1e2d492016-09-20 13:22:58 -06001310 case EHTokString:
1311 new(&type) TType(EbtString);
1312 break;
1313
John Kessenich87142c72016-03-12 20:24:24 -07001314 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001315 new(&type) TType(EbtFloat);
1316 break;
John Kessenich87142c72016-03-12 20:24:24 -07001317 case EHTokFloat1:
1318 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001319 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001320 break;
John Kessenich87142c72016-03-12 20:24:24 -07001321 case EHTokFloat2:
1322 new(&type) TType(EbtFloat, EvqTemporary, 2);
1323 break;
1324 case EHTokFloat3:
1325 new(&type) TType(EbtFloat, EvqTemporary, 3);
1326 break;
1327 case EHTokFloat4:
1328 new(&type) TType(EbtFloat, EvqTemporary, 4);
1329 break;
1330
John Kessenich71351de2016-06-08 12:50:56 -06001331 case EHTokDouble:
1332 new(&type) TType(EbtDouble);
1333 break;
1334 case EHTokDouble1:
1335 new(&type) TType(EbtDouble);
1336 type.makeVector();
1337 break;
1338 case EHTokDouble2:
1339 new(&type) TType(EbtDouble, EvqTemporary, 2);
1340 break;
1341 case EHTokDouble3:
1342 new(&type) TType(EbtDouble, EvqTemporary, 3);
1343 break;
1344 case EHTokDouble4:
1345 new(&type) TType(EbtDouble, EvqTemporary, 4);
1346 break;
1347
1348 case EHTokInt:
1349 case EHTokDword:
1350 new(&type) TType(EbtInt);
1351 break;
1352 case EHTokInt1:
1353 new(&type) TType(EbtInt);
1354 type.makeVector();
1355 break;
John Kessenich87142c72016-03-12 20:24:24 -07001356 case EHTokInt2:
1357 new(&type) TType(EbtInt, EvqTemporary, 2);
1358 break;
1359 case EHTokInt3:
1360 new(&type) TType(EbtInt, EvqTemporary, 3);
1361 break;
1362 case EHTokInt4:
1363 new(&type) TType(EbtInt, EvqTemporary, 4);
1364 break;
1365
John Kessenich71351de2016-06-08 12:50:56 -06001366 case EHTokUint:
1367 new(&type) TType(EbtUint);
1368 break;
1369 case EHTokUint1:
1370 new(&type) TType(EbtUint);
1371 type.makeVector();
1372 break;
1373 case EHTokUint2:
1374 new(&type) TType(EbtUint, EvqTemporary, 2);
1375 break;
1376 case EHTokUint3:
1377 new(&type) TType(EbtUint, EvqTemporary, 3);
1378 break;
1379 case EHTokUint4:
1380 new(&type) TType(EbtUint, EvqTemporary, 4);
1381 break;
1382
1383 case EHTokBool:
1384 new(&type) TType(EbtBool);
1385 break;
1386 case EHTokBool1:
1387 new(&type) TType(EbtBool);
1388 type.makeVector();
1389 break;
John Kessenich87142c72016-03-12 20:24:24 -07001390 case EHTokBool2:
1391 new(&type) TType(EbtBool, EvqTemporary, 2);
1392 break;
1393 case EHTokBool3:
1394 new(&type) TType(EbtBool, EvqTemporary, 3);
1395 break;
1396 case EHTokBool4:
1397 new(&type) TType(EbtBool, EvqTemporary, 4);
1398 break;
1399
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001400 case EHTokHalf:
1401 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1402 break;
1403 case EHTokHalf1:
1404 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1405 type.makeVector();
1406 break;
1407 case EHTokHalf2:
1408 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1409 break;
1410 case EHTokHalf3:
1411 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1412 break;
1413 case EHTokHalf4:
1414 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1415 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001416
steve-lunarg3226b082016-10-26 19:18:55 -06001417 case EHTokMin16float:
1418 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1419 break;
1420 case EHTokMin16float1:
1421 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1422 type.makeVector();
1423 break;
1424 case EHTokMin16float2:
1425 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1426 break;
1427 case EHTokMin16float3:
1428 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1429 break;
1430 case EHTokMin16float4:
1431 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1432 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001433
steve-lunarg3226b082016-10-26 19:18:55 -06001434 case EHTokMin10float:
1435 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1436 break;
1437 case EHTokMin10float1:
1438 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1439 type.makeVector();
1440 break;
1441 case EHTokMin10float2:
1442 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1443 break;
1444 case EHTokMin10float3:
1445 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1446 break;
1447 case EHTokMin10float4:
1448 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1449 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001450
steve-lunarg3226b082016-10-26 19:18:55 -06001451 case EHTokMin16int:
1452 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1453 break;
1454 case EHTokMin16int1:
1455 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1456 type.makeVector();
1457 break;
1458 case EHTokMin16int2:
1459 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1460 break;
1461 case EHTokMin16int3:
1462 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1463 break;
1464 case EHTokMin16int4:
1465 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1466 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001467
steve-lunarg3226b082016-10-26 19:18:55 -06001468 case EHTokMin12int:
1469 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1470 break;
1471 case EHTokMin12int1:
1472 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1473 type.makeVector();
1474 break;
1475 case EHTokMin12int2:
1476 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1477 break;
1478 case EHTokMin12int3:
1479 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1480 break;
1481 case EHTokMin12int4:
1482 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1483 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001484
steve-lunarg3226b082016-10-26 19:18:55 -06001485 case EHTokMin16uint:
1486 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1487 break;
1488 case EHTokMin16uint1:
1489 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1490 type.makeVector();
1491 break;
1492 case EHTokMin16uint2:
1493 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1494 break;
1495 case EHTokMin16uint3:
1496 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1497 break;
1498 case EHTokMin16uint4:
1499 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1500 break;
1501
John Kessenich0133c122016-05-20 12:17:26 -06001502 case EHTokInt1x1:
1503 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1504 break;
1505 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001506 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001507 break;
1508 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001509 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001510 break;
1511 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001512 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001513 break;
1514 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001515 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001516 break;
1517 case EHTokInt2x2:
1518 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1519 break;
1520 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001521 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001522 break;
1523 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001524 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001525 break;
1526 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001527 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001528 break;
1529 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001530 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001531 break;
1532 case EHTokInt3x3:
1533 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1534 break;
1535 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001536 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001537 break;
1538 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001539 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001540 break;
1541 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001542 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001543 break;
1544 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001545 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001546 break;
1547 case EHTokInt4x4:
1548 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1549 break;
1550
John Kessenich71351de2016-06-08 12:50:56 -06001551 case EHTokUint1x1:
1552 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1553 break;
1554 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001555 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001556 break;
1557 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001558 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001559 break;
1560 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001561 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001562 break;
1563 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001564 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001565 break;
1566 case EHTokUint2x2:
1567 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1568 break;
1569 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001570 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001571 break;
1572 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001573 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001574 break;
1575 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001576 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001577 break;
1578 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001579 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001580 break;
1581 case EHTokUint3x3:
1582 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1583 break;
1584 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001585 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001586 break;
1587 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001588 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001589 break;
1590 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001591 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001592 break;
1593 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001594 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001595 break;
1596 case EHTokUint4x4:
1597 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1598 break;
1599
1600 case EHTokBool1x1:
1601 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1602 break;
1603 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001604 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001605 break;
1606 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001607 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001608 break;
1609 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001610 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001611 break;
1612 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001613 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001614 break;
1615 case EHTokBool2x2:
1616 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1617 break;
1618 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001619 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001620 break;
1621 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001622 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001623 break;
1624 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001625 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001626 break;
1627 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001628 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001629 break;
1630 case EHTokBool3x3:
1631 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1632 break;
1633 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001634 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001635 break;
1636 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001637 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001638 break;
1639 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001640 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001641 break;
1642 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001643 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001644 break;
1645 case EHTokBool4x4:
1646 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1647 break;
1648
John Kessenich0133c122016-05-20 12:17:26 -06001649 case EHTokFloat1x1:
1650 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1651 break;
1652 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001653 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001654 break;
1655 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001656 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001657 break;
1658 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001659 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001660 break;
1661 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001662 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001663 break;
John Kessenich87142c72016-03-12 20:24:24 -07001664 case EHTokFloat2x2:
1665 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1666 break;
1667 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001668 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001669 break;
1670 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001671 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001672 break;
John Kessenich0133c122016-05-20 12:17:26 -06001673 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001674 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001675 break;
John Kessenich87142c72016-03-12 20:24:24 -07001676 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001677 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001678 break;
1679 case EHTokFloat3x3:
1680 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1681 break;
1682 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001683 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001684 break;
John Kessenich0133c122016-05-20 12:17:26 -06001685 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001686 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001687 break;
John Kessenich87142c72016-03-12 20:24:24 -07001688 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001689 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001690 break;
1691 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001692 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001693 break;
1694 case EHTokFloat4x4:
1695 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1696 break;
1697
John Kessenich0133c122016-05-20 12:17:26 -06001698 case EHTokDouble1x1:
1699 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1700 break;
1701 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001702 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001703 break;
1704 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001705 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001706 break;
1707 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001708 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001709 break;
1710 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001711 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001712 break;
1713 case EHTokDouble2x2:
1714 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1715 break;
1716 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001717 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001718 break;
1719 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001720 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001721 break;
1722 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001723 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001724 break;
1725 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001726 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001727 break;
1728 case EHTokDouble3x3:
1729 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1730 break;
1731 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001732 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001733 break;
1734 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001735 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001736 break;
1737 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001738 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001739 break;
1740 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001741 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001742 break;
1743 case EHTokDouble4x4:
1744 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1745 break;
1746
John Kessenich87142c72016-03-12 20:24:24 -07001747 default:
1748 return false;
1749 }
1750
1751 advanceToken();
1752
1753 return true;
1754}
1755
John Kesseniche6e74942016-06-11 16:43:14 -06001756// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001757// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1758// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07001759// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06001760//
1761// struct_type
1762// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001763// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06001764// | CBUFFER
1765// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001766//
John Kessenich54ee28f2017-03-11 14:13:00 -07001767bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06001768{
John Kessenichb804de62016-09-05 12:19:18 -06001769 // This storage qualifier will tell us whether it's an AST
1770 // block type or just a generic structure type.
1771 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001772
1773 // CBUFFER
1774 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001775 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001776 // TBUFFER
1777 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001778 storageQualifier = EvqBuffer;
John Kessenich27ffb292017-03-03 17:01:01 -07001779 // CLASS
John Kesseniche6e74942016-06-11 16:43:14 -06001780 // STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001781 else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001782 return false;
1783
1784 // IDENTIFIER
1785 TString structName = "";
1786 if (peekTokenClass(EHTokIdentifier)) {
1787 structName = *token.string;
1788 advanceToken();
1789 }
1790
John Kessenich3d157c52016-07-25 16:05:33 -06001791 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001792 TQualifier postDeclQualifier;
1793 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07001794 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001795
John Kessenichf3d88bd2017-03-19 12:24:29 -06001796 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07001797 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06001798 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07001799 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
1800 // struct_type IDENTIFIER
1801 return true;
1802 } else {
1803 expected("{");
1804 return false;
1805 }
John Kesseniche6e74942016-06-11 16:43:14 -06001806 }
1807
John Kessenichf3d88bd2017-03-19 12:24:29 -06001808
John Kesseniche6e74942016-06-11 16:43:14 -06001809 // struct_declaration_list
1810 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06001811 // Save each member function so they can be processed after we have a fully formed 'this'.
1812 TVector<TFunctionDeclarator> functionDeclarators;
1813
1814 parseContext.pushNamespace(structName);
1815 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, structName, functionDeclarators);
1816 parseContext.popNamespace();
1817
1818 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06001819 expected("struct member declarations");
1820 return false;
1821 }
1822
1823 // RIGHT_BRACE
1824 if (! acceptTokenClass(EHTokRightBrace)) {
1825 expected("}");
1826 return false;
1827 }
1828
1829 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001830 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001831 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001832 else {
John Kessenich7735b942016-09-05 12:40:06 -06001833 postDeclQualifier.storage = storageQualifier;
1834 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001835 }
John Kesseniche6e74942016-06-11 16:43:14 -06001836
John Kessenich727b3742017-02-03 17:57:55 -07001837 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001838
John Kessenich4960baa2017-03-19 18:09:59 -06001839 // For member functions: now that we know the type of 'this', go back and
1840 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
1841 // - parse the functions, their tokens were saved for deferred parsing (now)
1842 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
1843 // update signature
1844 if (functionDeclarators[b].function->hasImplicitThis())
1845 functionDeclarators[b].function->addThisParameter(type);
1846 }
1847
John Kessenichf3d88bd2017-03-19 12:24:29 -06001848 // All member functions get parsed inside the class/struct namespace and with the
1849 // class/struct members in a symbol-table level.
1850 parseContext.pushNamespace(structName);
1851 bool deferredSuccess = true;
1852 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
1853 // parse body
1854 pushTokenStream(functionDeclarators[b].body);
1855 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
1856 deferredSuccess = false;
1857 popTokenStream();
1858 }
1859 parseContext.popNamespace();
1860
1861 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06001862}
1863
steve-lunarg5da1f032017-02-12 17:50:28 -07001864// struct_buffer
1865// : APPENDSTRUCTUREDBUFFER
1866// | BYTEADDRESSBUFFER
1867// | CONSUMESTRUCTUREDBUFFER
1868// | RWBYTEADDRESSBUFFER
1869// | RWSTRUCTUREDBUFFER
1870// | STRUCTUREDBUFFER
1871bool HlslGrammar::acceptStructBufferType(TType& type)
1872{
1873 const EHlslTokenClass structBuffType = peek();
1874
1875 // TODO: globallycoherent
1876 bool hasTemplateType = true;
1877 bool readonly = false;
1878
1879 TStorageQualifier storage = EvqBuffer;
1880
1881 switch (structBuffType) {
1882 case EHTokAppendStructuredBuffer:
1883 unimplemented("AppendStructuredBuffer");
1884 return false;
1885 case EHTokByteAddressBuffer:
1886 hasTemplateType = false;
1887 readonly = true;
1888 break;
1889 case EHTokConsumeStructuredBuffer:
1890 unimplemented("ConsumeStructuredBuffer");
1891 return false;
1892 case EHTokRWByteAddressBuffer:
1893 hasTemplateType = false;
1894 break;
1895 case EHTokRWStructuredBuffer:
1896 break;
1897 case EHTokStructuredBuffer:
1898 readonly = true;
1899 break;
1900 default:
1901 return false; // not a structure buffer type
1902 }
1903
1904 advanceToken(); // consume the structure keyword
1905
1906 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
1907 TType* templateType = new TType;
1908
1909 if (hasTemplateType) {
1910 if (! acceptTokenClass(EHTokLeftAngle)) {
1911 expected("left angle bracket");
1912 return false;
1913 }
1914
1915 if (! acceptType(*templateType)) {
1916 expected("type");
1917 return false;
1918 }
1919 if (! acceptTokenClass(EHTokRightAngle)) {
1920 expected("right angle bracket");
1921 return false;
1922 }
1923 } else {
1924 // byte address buffers have no explicit type.
1925 TType uintType(EbtUint, storage);
1926 templateType->shallowCopy(uintType);
1927 }
1928
1929 // Create an unsized array out of that type.
1930 // TODO: does this work if it's already an array type?
1931 TArraySizes unsizedArray;
1932 unsizedArray.addInnerSize(UnsizedArraySize);
1933 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07001934 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07001935
1936 // field name is canonical for all structbuffers
1937 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07001938
1939 // Create block type. TODO: hidden internal uint member when needed
steve-lunargdd8287a2017-02-23 18:04:12 -07001940
steve-lunarg5da1f032017-02-12 17:50:28 -07001941 TTypeList* blockStruct = new TTypeList;
1942 TTypeLoc member = { templateType, token.loc };
1943 blockStruct->push_back(member);
1944
steve-lunargdd8287a2017-02-23 18:04:12 -07001945 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07001946 TType blockType(blockStruct, "", templateType->getQualifier());
1947
steve-lunargdd8287a2017-02-23 18:04:12 -07001948 blockType.getQualifier().storage = storage;
1949 blockType.getQualifier().readonly = readonly;
1950
1951 // We may have created an equivalent type before, in which case we should use its
1952 // deep structure.
1953 parseContext.shareStructBufferType(blockType);
1954
steve-lunarg5da1f032017-02-12 17:50:28 -07001955 type.shallowCopy(blockType);
1956
1957 return true;
1958}
1959
John Kesseniche6e74942016-06-11 16:43:14 -06001960// struct_declaration_list
1961// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1962//
1963// struct_declaration
1964// : fully_specified_type struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07001965// | fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06001966//
1967// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001968// : IDENTIFIER post_decls
1969// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07001970// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06001971//
John Kessenichf3d88bd2017-03-19 12:24:29 -06001972bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, const TString& typeName,
1973 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06001974{
1975 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001976 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001977
1978 do {
1979 // success on seeing the RIGHT_BRACE coming up
1980 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07001981 break;
John Kesseniche6e74942016-06-11 16:43:14 -06001982
1983 // struct_declaration
John Kessenich54ee28f2017-03-11 14:13:00 -07001984
1985 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06001986
1987 // fully_specified_type
1988 TType memberType;
John Kessenich54ee28f2017-03-11 14:13:00 -07001989 if (! acceptFullySpecifiedType(memberType, nodeList)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001990 expected("member type");
1991 return false;
1992 }
1993
1994 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07001995 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06001996 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001997 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001998 expected("member name");
1999 return false;
2000 }
2001
John Kessenich54ee28f2017-03-11 14:13:00 -07002002 if (peekTokenClass(EHTokLeftParen)) {
2003 // function_parameters
2004 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002005 declarators.resize(declarators.size() + 1);
2006 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002007 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2008 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002009 if (functionDefinitionAccepted)
2010 break;
2011 }
2012 expected("member-function definition");
2013 return false;
2014 } else {
2015 // add it to the list of members
2016 TTypeLoc member = { new TType(EbtVoid), token.loc };
2017 member.type->shallowCopy(memberType);
2018 member.type->setFieldName(*idToken.string);
2019 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002020
John Kessenich54ee28f2017-03-11 14:13:00 -07002021 // array_specifier
2022 TArraySizes* arraySizes = nullptr;
2023 acceptArraySpecifier(arraySizes);
2024 if (arraySizes)
2025 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002026
John Kessenich54ee28f2017-03-11 14:13:00 -07002027 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002028
John Kessenich54ee28f2017-03-11 14:13:00 -07002029 // EQUAL assignment_expression
2030 if (acceptTokenClass(EHTokAssign)) {
2031 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2032 TIntermTyped* expressionNode = nullptr;
2033 if (! acceptAssignmentExpression(expressionNode)) {
2034 expected("initializer");
2035 return false;
2036 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002037 }
2038 }
John Kesseniche6e74942016-06-11 16:43:14 -06002039 // success on seeing the SEMICOLON coming up
2040 if (peekTokenClass(EHTokSemicolon))
2041 break;
2042
2043 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002044 if (acceptTokenClass(EHTokComma))
2045 declarator_list = true;
2046 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002047 expected(",");
2048 return false;
2049 }
2050
2051 } while (true);
2052
2053 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002054 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002055 expected(";");
2056 return false;
2057 }
2058
2059 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002060
John Kessenichb16f7e62017-03-11 19:32:47 -07002061 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002062}
2063
John Kessenich54ee28f2017-03-11 14:13:00 -07002064// member_function_definition
2065// | function_parameters post_decls compound_statement
2066//
2067// Expects type to have EvqGlobal for a static member and
2068// EvqTemporary for non-static member.
John Kessenichf3d88bd2017-03-19 12:24:29 -06002069bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, const TString& memberName,
2070 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002071{
John Kessenich54ee28f2017-03-11 14:13:00 -07002072 bool accepted = false;
2073
John Kessenichf3d88bd2017-03-19 12:24:29 -06002074 TString* functionName = parseContext.getFullNamespaceName(memberName);
John Kessenich088d52b2017-03-11 17:55:28 -07002075 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002076 if (type.getQualifier().storage == EvqTemporary)
2077 declarator.function->setImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002078
2079 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002080 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002081 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002082 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002083
2084 // compound_statement (function body definition)
2085 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002086 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002087 declarator.body = new TVector<HlslToken>;
2088 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002089 }
2090 } else
2091 expected("function parameter list");
2092
John Kessenich54ee28f2017-03-11 14:13:00 -07002093 return accepted;
2094}
2095
John Kessenich5f934b02016-03-13 17:58:25 -06002096// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002097// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002098// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002099//
2100bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2101{
John Kessenich078d7f22016-03-14 10:02:11 -06002102 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002103 if (! acceptTokenClass(EHTokLeftParen))
2104 return false;
2105
John Kessenich71351de2016-06-08 12:50:56 -06002106 // VOID RIGHT_PAREN
2107 if (! acceptTokenClass(EHTokVoid)) {
2108 do {
2109 // parameter_declaration
2110 if (! acceptParameterDeclaration(function))
2111 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002112
John Kessenich71351de2016-06-08 12:50:56 -06002113 // COMMA
2114 if (! acceptTokenClass(EHTokComma))
2115 break;
2116 } while (true);
2117 }
John Kessenich5f934b02016-03-13 17:58:25 -06002118
John Kessenich078d7f22016-03-14 10:02:11 -06002119 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002120 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002121 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002122 return false;
2123 }
2124
2125 return true;
2126}
2127
steve-lunarg26d31452016-12-23 18:56:57 -07002128// default_parameter_declaration
2129// : EQUAL conditional_expression
2130// : EQUAL initializer
2131bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2132{
2133 node = nullptr;
2134
2135 // Valid not to have a default_parameter_declaration
2136 if (!acceptTokenClass(EHTokAssign))
2137 return true;
2138
2139 if (!acceptConditionalExpression(node)) {
2140 if (!acceptInitializer(node))
2141 return false;
2142
2143 // For initializer lists, we have to const-fold into a constructor for the type, so build
2144 // that.
2145 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
2146 if (constructor == nullptr) // cannot construct
2147 return false;
2148
2149 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002150 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002151 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002152
steve-lunarg26d31452016-12-23 18:56:57 -07002153 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2154 }
2155
2156 // If this is simply a constant, we can use it directly.
2157 if (node->getAsConstantUnion())
2158 return true;
2159
2160 // Otherwise, it has to be const-foldable.
2161 TIntermTyped* origNode = node;
2162
2163 node = intermediate.fold(node->getAsAggregate());
2164
2165 if (node != nullptr && origNode != node)
2166 return true;
2167
2168 parseContext.error(token.loc, "invalid default parameter value", "", "");
2169
2170 return false;
2171}
2172
John Kessenich5f934b02016-03-13 17:58:25 -06002173// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002174// : fully_specified_type post_decls [ = default_parameter_declaration ]
2175// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002176//
2177bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2178{
2179 // fully_specified_type
2180 TType* type = new TType;
2181 if (! acceptFullySpecifiedType(*type))
2182 return false;
2183
2184 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002185 HlslToken idToken;
2186 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002187
John Kessenich19b92ff2016-06-19 11:50:34 -06002188 // array_specifier
2189 TArraySizes* arraySizes = nullptr;
2190 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002191 if (arraySizes) {
2192 if (arraySizes->isImplicit()) {
2193 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2194 return false;
2195 }
2196
John Kessenich19b92ff2016-06-19 11:50:34 -06002197 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002198 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002199
2200 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002201 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002202
steve-lunarg26d31452016-12-23 18:56:57 -07002203 TIntermTyped* defaultValue;
2204 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2205 return false;
2206
John Kessenich5aa59e22016-06-17 15:50:47 -06002207 parseContext.paramFix(*type);
2208
steve-lunarg26d31452016-12-23 18:56:57 -07002209 // If any prior parameters have default values, all the parameters after that must as well.
2210 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2211 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2212 return false;
2213 }
2214
2215 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002216 function.addParameter(param);
2217
2218 return true;
2219}
2220
2221// Do the work to create the function definition in addition to
2222// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002223//
2224// If 'deferredTokens' are passed in, just get the token stream,
2225// don't process.
2226//
2227bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2228 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002229{
John Kessenich088d52b2017-03-11 17:55:28 -07002230 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002231
John Kessenichb16f7e62017-03-11 19:32:47 -07002232 if (deferredTokens)
2233 return captureBlockTokens(*deferredTokens);
2234 else
John Kessenich4960baa2017-03-19 18:09:59 -06002235 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002236}
2237
2238bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2239{
2240 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002241 TIntermNode* entryPointNode = nullptr;
2242
John Kessenich077e0522016-06-09 02:02:17 -06002243 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002244 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2245 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002246
2247 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002248 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002249 if (! acceptCompoundStatement(functionBody))
2250 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002251
John Kessenich54ee28f2017-03-11 14:13:00 -07002252 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002253 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002254
2255 // Hook up the 1 or 2 function definitions.
2256 nodeList = intermediate.growAggregate(nodeList, functionNode);
2257 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002258
2259 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002260}
2261
John Kessenich0d2b6de2016-06-05 11:23:11 -06002262// Accept an expression with parenthesis around it, where
2263// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002264// syntactically required ones like in "if ( expression )".
2265//
2266// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002267//
2268// Note this one is not set up to be speculative; as it gives
2269// errors if not found.
2270//
2271bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2272{
2273 // LEFT_PAREN
2274 if (! acceptTokenClass(EHTokLeftParen))
2275 expected("(");
2276
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002277 bool decl = false;
2278 TIntermNode* declNode = nullptr;
2279 decl = acceptControlDeclaration(declNode);
2280 if (decl) {
2281 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2282 expected("initialized declaration");
2283 return false;
2284 } else
2285 expression = declNode->getAsTyped();
2286 } else {
2287 // no declaration
2288 if (! acceptExpression(expression)) {
2289 expected("expression");
2290 return false;
2291 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002292 }
2293
2294 // RIGHT_PAREN
2295 if (! acceptTokenClass(EHTokRightParen))
2296 expected(")");
2297
2298 return true;
2299}
2300
John Kessenich34fb0362016-05-03 23:17:20 -06002301// The top-level full expression recognizer.
2302//
John Kessenich87142c72016-03-12 20:24:24 -07002303// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002304// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002305//
2306bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2307{
LoopDawgef764a22016-06-03 09:17:51 -06002308 node = nullptr;
2309
John Kessenich34fb0362016-05-03 23:17:20 -06002310 // assignment_expression
2311 if (! acceptAssignmentExpression(node))
2312 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002313
John Kessenich34fb0362016-05-03 23:17:20 -06002314 if (! peekTokenClass(EHTokComma))
2315 return true;
2316
2317 do {
2318 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002319 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002320 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002321
John Kessenich34fb0362016-05-03 23:17:20 -06002322 // ... assignment_expression
2323 TIntermTyped* rightNode = nullptr;
2324 if (! acceptAssignmentExpression(rightNode)) {
2325 expected("assignment expression");
2326 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002327 }
2328
John Kessenich34fb0362016-05-03 23:17:20 -06002329 node = intermediate.addComma(node, rightNode, loc);
2330
2331 if (! peekTokenClass(EHTokComma))
2332 return true;
2333 } while (true);
2334}
2335
John Kessenich07354242016-07-01 19:58:06 -06002336// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002337// : LEFT_BRACE RIGHT_BRACE
2338// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002339//
2340// initializer_list
2341// : assignment_expression COMMA assignment_expression COMMA ...
2342//
2343bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2344{
2345 // LEFT_BRACE
2346 if (! acceptTokenClass(EHTokLeftBrace))
2347 return false;
2348
John Kessenich98ad4852016-11-27 17:39:07 -07002349 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002350 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002351 if (acceptTokenClass(EHTokRightBrace)) {
2352 // a zero-length initializer list
2353 node = intermediate.makeAggregate(loc);
2354 return true;
2355 }
2356
2357 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002358 node = nullptr;
2359 do {
2360 // assignment_expression
2361 TIntermTyped* expr;
2362 if (! acceptAssignmentExpression(expr)) {
2363 expected("assignment expression in initializer list");
2364 return false;
2365 }
2366 node = intermediate.growAggregate(node, expr, loc);
2367
2368 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002369 if (acceptTokenClass(EHTokComma)) {
2370 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2371 return true;
John Kessenich07354242016-07-01 19:58:06 -06002372 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002373 }
John Kessenich07354242016-07-01 19:58:06 -06002374
2375 // RIGHT_BRACE
2376 if (acceptTokenClass(EHTokRightBrace))
2377 return true;
2378
2379 expected(", or }");
2380 return false;
2381 } while (true);
2382}
2383
John Kessenich34fb0362016-05-03 23:17:20 -06002384// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002385// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002386//
2387// a op (b op (c op d))
2388//
2389// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002390// : initializer
2391// | conditional_expression
2392// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002393//
2394bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2395{
John Kessenich07354242016-07-01 19:58:06 -06002396 // initializer
2397 if (peekTokenClass(EHTokLeftBrace)) {
2398 if (acceptInitializer(node))
2399 return true;
2400
2401 expected("initializer");
2402 return false;
2403 }
2404
John Kessenich00957f82016-07-27 10:39:57 -06002405 // conditional_expression
2406 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002407 return false;
2408
John Kessenich07354242016-07-01 19:58:06 -06002409 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002410 TOperator assignOp = HlslOpMap::assignment(peek());
2411 if (assignOp == EOpNull)
2412 return true;
2413
John Kessenich00957f82016-07-27 10:39:57 -06002414 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002415 TSourceLoc loc = token.loc;
2416 advanceToken();
2417
John Kessenich00957f82016-07-27 10:39:57 -06002418 // conditional_expression assign_op conditional_expression ...
2419 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002420 // gets the right-to-left associativity.
2421 TIntermTyped* rightNode = nullptr;
2422 if (! acceptAssignmentExpression(rightNode)) {
2423 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002424 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002425 }
2426
John Kessenichd21baed2016-09-16 03:05:12 -06002427 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002428 node = parseContext.handleLvalue(loc, "assign", node);
2429
John Kessenichfea226b2016-07-28 17:53:56 -06002430 if (node == nullptr) {
2431 parseContext.error(loc, "could not create assignment", "", "");
2432 return false;
2433 }
John Kessenich34fb0362016-05-03 23:17:20 -06002434
2435 if (! peekTokenClass(EHTokComma))
2436 return true;
2437
2438 return true;
2439}
2440
John Kessenich00957f82016-07-27 10:39:57 -06002441// Accept a conditional expression, which associates right-to-left,
2442// accomplished by the "true" expression calling down to lower
2443// precedence levels than this level.
2444//
2445// conditional_expression
2446// : binary_expression
2447// | binary_expression QUESTION expression COLON assignment_expression
2448//
2449bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2450{
2451 // binary_expression
2452 if (! acceptBinaryExpression(node, PlLogicalOr))
2453 return false;
2454
2455 if (! acceptTokenClass(EHTokQuestion))
2456 return true;
2457
2458 TIntermTyped* trueNode = nullptr;
2459 if (! acceptExpression(trueNode)) {
2460 expected("expression after ?");
2461 return false;
2462 }
2463 TSourceLoc loc = token.loc;
2464
2465 if (! acceptTokenClass(EHTokColon)) {
2466 expected(":");
2467 return false;
2468 }
2469
2470 TIntermTyped* falseNode = nullptr;
2471 if (! acceptAssignmentExpression(falseNode)) {
2472 expected("expression after :");
2473 return false;
2474 }
2475
2476 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2477
2478 return true;
2479}
2480
John Kessenich34fb0362016-05-03 23:17:20 -06002481// Accept a binary expression, for binary operations that
2482// associate left-to-right. This is, it is implicit, for example
2483//
2484// ((a op b) op c) op d
2485//
2486// binary_expression
2487// : expression op expression op expression ...
2488//
2489// where 'expression' is the next higher level in precedence.
2490//
2491bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2492{
2493 if (precedenceLevel > PlMul)
2494 return acceptUnaryExpression(node);
2495
2496 // assignment_expression
2497 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2498 return false;
2499
John Kessenich34fb0362016-05-03 23:17:20 -06002500 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002501 TOperator op = HlslOpMap::binary(peek());
2502 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2503 if (tokenLevel < precedenceLevel)
2504 return true;
2505
John Kessenich34fb0362016-05-03 23:17:20 -06002506 // ... op
2507 TSourceLoc loc = token.loc;
2508 advanceToken();
2509
2510 // ... expression
2511 TIntermTyped* rightNode = nullptr;
2512 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2513 expected("expression");
2514 return false;
2515 }
2516
2517 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002518 if (node == nullptr) {
2519 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2520 return false;
2521 }
John Kessenich34fb0362016-05-03 23:17:20 -06002522 } while (true);
2523}
2524
2525// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002526// : (type) unary_expression
2527// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002528// | - unary_expression
2529// | ! unary_expression
2530// | ~ unary_expression
2531// | ++ unary_expression
2532// | -- unary_expression
2533// | postfix_expression
2534//
2535bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2536{
John Kessenich1cc1a282016-06-03 16:55:49 -06002537 // (type) unary_expression
2538 // Have to look two steps ahead, because this could be, e.g., a
2539 // postfix_expression instead, since that also starts with at "(".
2540 if (acceptTokenClass(EHTokLeftParen)) {
2541 TType castType;
2542 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002543 if (acceptTokenClass(EHTokRightParen)) {
2544 // We've matched "(type)" now, get the expression to cast
2545 TSourceLoc loc = token.loc;
2546 if (! acceptUnaryExpression(node))
2547 return false;
2548
2549 // Hook it up like a constructor
2550 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2551 if (constructorFunction == nullptr) {
2552 expected("type that can be constructed");
2553 return false;
2554 }
2555 TIntermTyped* arguments = nullptr;
2556 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2557 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2558
2559 return true;
2560 } else {
2561 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2562 // the '(int' part. We must back up twice.
2563 recedeToken();
2564 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002565 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002566 } else {
2567 // This isn't a type cast, but it still started "(", so if it is a
2568 // unary expression, it can only be a postfix_expression, so try that.
2569 // Back it up first.
2570 recedeToken();
2571 return acceptPostfixExpression(node);
2572 }
2573 }
2574
2575 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002576 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002577
John Kessenich1cc1a282016-06-03 16:55:49 -06002578 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002579 if (unaryOp == EOpNull)
2580 return acceptPostfixExpression(node);
2581
2582 // op unary_expression
2583 TSourceLoc loc = token.loc;
2584 advanceToken();
2585 if (! acceptUnaryExpression(node))
2586 return false;
2587
2588 // + is a no-op
2589 if (unaryOp == EOpAdd)
2590 return true;
2591
2592 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002593
2594 // These unary ops require lvalues
2595 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2596 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002597
2598 return node != nullptr;
2599}
2600
2601// postfix_expression
2602// : LEFT_PAREN expression RIGHT_PAREN
2603// | literal
2604// | constructor
2605// | identifier
2606// | function_call
2607// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2608// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002609// | postfix_expression DOT IDENTIFIER arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07002610// | postfix_expression COLONCOLON IDENTIFIER arguments
John Kessenich34fb0362016-05-03 23:17:20 -06002611// | postfix_expression INC_OP
2612// | postfix_expression DEC_OP
2613//
2614bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2615{
2616 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07002617 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06002618
2619 // idToken will pick up either a variable or a function name in a function call
2620 HlslToken idToken;
2621
John Kessenich54ee28f2017-03-11 14:13:00 -07002622 // scopeBase will pick up the type symbol on the left of '::'
John Kessenich4960baa2017-03-19 18:09:59 -06002623 TSymbol* scope = nullptr;
John Kessenich54ee28f2017-03-11 14:13:00 -07002624
John Kessenich21472ae2016-06-04 11:46:33 -06002625 // Find something before the postfix operations, as they can't operate
2626 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002627 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002628 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002629 if (! acceptExpression(node)) {
2630 expected("expression");
2631 return false;
2632 }
2633 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002634 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002635 return false;
2636 }
John Kessenich34fb0362016-05-03 23:17:20 -06002637 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002638 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002639 } else if (acceptConstructor(node)) {
2640 // constructor (nothing else to do yet)
2641 } else if (acceptIdentifier(idToken)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002642 // user-type, identifier, or function name
2643 if (peekTokenClass(EHTokColonColon)) {
2644 TType type;
John Kessenich4960baa2017-03-19 18:09:59 -06002645 scope = parseContext.lookupUserType(*idToken.string, type);
2646 if (scope == nullptr) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002647 expected("type left of ::");
2648 return false;
2649 }
2650 } else if (! peekTokenClass(EHTokLeftParen)) {
John Kessenichf4ba25e2017-03-21 18:35:04 -06002651 node = parseContext.handleVariable(idToken.loc, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002652 } else if (acceptFunctionCall(idToken, node)) {
2653 // function_call (nothing else to do yet)
2654 } else {
2655 expected("function call arguments");
2656 return false;
2657 }
John Kessenich21472ae2016-06-04 11:46:33 -06002658 } else {
2659 // nothing found, can't post operate
2660 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002661 }
2662
steve-lunarga2b01a02016-11-28 17:09:54 -07002663 // This is to guarantee we do this no matter how we get out of the stack frame.
2664 // This way there's no bug if an early return forgets to do it.
2665 struct tFinalize {
2666 tFinalize(HlslParseContext& p) : parseContext(p) { }
2667 ~tFinalize() { parseContext.finalizeFlattening(); }
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002668 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002669 private:
John Kessenichca71d942017-03-07 20:44:09 -07002670 const tFinalize& operator=(const tFinalize&) { return *this; }
John Kessenichefeefd92017-03-01 13:12:26 -07002671 tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
steve-lunarga2b01a02016-11-28 17:09:54 -07002672 } finalize(parseContext);
2673
2674 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2675 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2676 // level: hence the init and finalize. Even though in practice these must be
2677 // constants, they are parsed no matter what.
2678 parseContext.initFlattening();
2679
John Kessenich21472ae2016-06-04 11:46:33 -06002680 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002681 do {
2682 TSourceLoc loc = token.loc;
2683 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002684
John Kessenich34fb0362016-05-03 23:17:20 -06002685 // Consume only a valid post-unary operator, otherwise we are done.
2686 switch (postOp) {
2687 case EOpIndexDirectStruct:
2688 case EOpIndexIndirect:
2689 case EOpPostIncrement:
2690 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07002691 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002692 advanceToken();
2693 break;
2694 default:
2695 return true;
2696 }
John Kessenich87142c72016-03-12 20:24:24 -07002697
John Kessenich34fb0362016-05-03 23:17:20 -06002698 // We have a valid post-unary operator, process it.
2699 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002700 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002701 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002702 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002703 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002704 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06002705 HlslToken field;
2706 if (! acceptIdentifier(field)) {
2707 expected("swizzle or member");
2708 return false;
2709 }
LoopDawg4886f692016-06-29 10:58:58 -06002710
John Kessenich516d92d2017-03-08 20:09:03 -07002711 if (peekTokenClass(EHTokLeftParen)) {
2712 // member function
2713 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06002714
John Kessenich516d92d2017-03-08 20:09:03 -07002715 // arguments
John Kessenich4960baa2017-03-19 18:09:59 -06002716 if (! acceptFunctionCall(field, node, thisNode, scope)) {
LoopDawg4886f692016-06-29 10:58:58 -06002717 expected("function parameters");
2718 return false;
2719 }
John Kessenich516d92d2017-03-08 20:09:03 -07002720 } else
2721 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002722
John Kessenich34fb0362016-05-03 23:17:20 -06002723 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002724 }
John Kessenich34fb0362016-05-03 23:17:20 -06002725 case EOpIndexIndirect:
2726 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002727 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002728 TIntermTyped* indexNode = nullptr;
2729 if (! acceptExpression(indexNode) ||
2730 ! peekTokenClass(EHTokRightBracket)) {
2731 expected("expression followed by ']'");
2732 return false;
2733 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002734 advanceToken();
2735 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2736 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002737 }
2738 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002739 // INC_OP
2740 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002741 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002742 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002743 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002744 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002745 break;
2746 default:
2747 assert(0);
2748 break;
2749 }
2750 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002751}
2752
John Kessenichd016be12016-03-13 11:24:20 -06002753// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002754// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002755//
2756bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2757{
2758 // type
2759 TType type;
2760 if (acceptType(type)) {
2761 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2762 if (constructorFunction == nullptr)
2763 return false;
2764
2765 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002766 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002767 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002768 // It's possible this is a type keyword used as an identifier. Put the token back
2769 // for later use.
2770 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002771 return false;
2772 }
2773
2774 // hook it up
2775 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2776
2777 return true;
2778 }
2779
2780 return false;
2781}
2782
John Kessenich34fb0362016-05-03 23:17:20 -06002783// The function_call identifier was already recognized, and passed in as idToken.
2784//
2785// function_call
2786// : [idToken] arguments
2787//
John Kessenich54ee28f2017-03-11 14:13:00 -07002788bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, TIntermTyped* baseObject,
John Kessenich4960baa2017-03-19 18:09:59 -06002789 const TSymbol* scope)
John Kessenich34fb0362016-05-03 23:17:20 -06002790{
John Kessenich54ee28f2017-03-11 14:13:00 -07002791 // name
2792 TString* functionName = nullptr;
steve-lunarge7d07522017-03-19 18:12:37 -06002793 if ((baseObject == nullptr && scope == nullptr)) {
2794 functionName = callToken.string;
2795 } else if (parseContext.isBuiltInMethod(callToken.loc, baseObject, *callToken.string)) {
John Kessenich4960baa2017-03-19 18:09:59 -06002796 // Built-in methods are not in the symbol table as methods, but as global functions
2797 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06002798 functionName = NewPoolTString(BUILTIN_PREFIX);
2799 functionName->append(*callToken.string);
John Kessenich4960baa2017-03-19 18:09:59 -06002800 } else {
John Kessenich54ee28f2017-03-11 14:13:00 -07002801 functionName = NewPoolTString("");
John Kessenich4960baa2017-03-19 18:09:59 -06002802 if (baseObject != nullptr)
2803 functionName->append(baseObject->getType().getTypeName());
2804 else if (scope != nullptr)
2805 functionName->append(scope->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06002806 parseContext.addScopeMangler(*functionName);
John Kessenich54ee28f2017-03-11 14:13:00 -07002807 functionName->append(*callToken.string);
John Kessenich5f12d2f2017-03-11 09:39:55 -07002808 }
LoopDawg4886f692016-06-29 10:58:58 -06002809
John Kessenich54ee28f2017-03-11 14:13:00 -07002810 // function
2811 TFunction* function = new TFunction(functionName, TType(EbtVoid));
2812
2813 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07002814 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06002815 if (baseObject != nullptr) {
2816 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07002817 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06002818 }
John Kessenich4678ca92016-05-13 09:33:42 -06002819 if (! acceptArguments(function, arguments))
2820 return false;
2821
John Kessenich54ee28f2017-03-11 14:13:00 -07002822 // call
John Kessenich5f12d2f2017-03-11 09:39:55 -07002823 node = parseContext.handleFunctionCall(callToken.loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06002824
2825 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002826}
2827
John Kessenich87142c72016-03-12 20:24:24 -07002828// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002829// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002830//
John Kessenichd016be12016-03-13 11:24:20 -06002831// The arguments are pushed onto the 'function' argument list and
2832// onto the 'arguments' aggregate.
2833//
John Kessenich4678ca92016-05-13 09:33:42 -06002834bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002835{
John Kessenich078d7f22016-03-14 10:02:11 -06002836 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002837 if (! acceptTokenClass(EHTokLeftParen))
2838 return false;
2839
2840 do {
John Kessenichd016be12016-03-13 11:24:20 -06002841 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002842 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002843 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002844 break;
John Kessenichd016be12016-03-13 11:24:20 -06002845
2846 // hook it up
2847 parseContext.handleFunctionArgument(function, arguments, arg);
2848
John Kessenich078d7f22016-03-14 10:02:11 -06002849 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002850 if (! acceptTokenClass(EHTokComma))
2851 break;
2852 } while (true);
2853
John Kessenich078d7f22016-03-14 10:02:11 -06002854 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002855 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002856 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002857 return false;
2858 }
2859
2860 return true;
2861}
2862
2863bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2864{
2865 switch (token.tokenClass) {
2866 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002867 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002868 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002869 case EHTokUintConstant:
2870 node = intermediate.addConstantUnion(token.u, token.loc, true);
2871 break;
John Kessenich87142c72016-03-12 20:24:24 -07002872 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002873 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002874 break;
2875 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002876 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002877 break;
2878 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002879 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002880 break;
John Kessenich86f71382016-09-19 20:23:18 -06002881 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07002882 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06002883 break;
John Kessenich87142c72016-03-12 20:24:24 -07002884
2885 default:
2886 return false;
2887 }
2888
2889 advanceToken();
2890
2891 return true;
2892}
2893
John Kessenich5f934b02016-03-13 17:58:25 -06002894// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002895// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002896//
John Kessenich21472ae2016-06-04 11:46:33 -06002897bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002898{
John Kessenich21472ae2016-06-04 11:46:33 -06002899 TIntermAggregate* compoundStatement = nullptr;
2900
John Kessenich34fb0362016-05-03 23:17:20 -06002901 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002902 if (! acceptTokenClass(EHTokLeftBrace))
2903 return false;
2904
2905 // statement statement ...
2906 TIntermNode* statement = nullptr;
2907 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002908 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2909 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2910 branch->getFlowOp() == EOpDefault)) {
2911 // hook up individual subsequences within a switch statement
2912 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2913 compoundStatement = nullptr;
2914 } else {
2915 // hook it up to the growing compound statement
2916 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2917 }
John Kessenich5f934b02016-03-13 17:58:25 -06002918 }
John Kessenich34fb0362016-05-03 23:17:20 -06002919 if (compoundStatement)
2920 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002921
John Kessenich21472ae2016-06-04 11:46:33 -06002922 retStatement = compoundStatement;
2923
John Kessenich34fb0362016-05-03 23:17:20 -06002924 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002925 return acceptTokenClass(EHTokRightBrace);
2926}
2927
John Kessenich0d2b6de2016-06-05 11:23:11 -06002928bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2929{
2930 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002931 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002932 parseContext.popScope();
2933
2934 return result;
2935}
2936
John Kessenich077e0522016-06-09 02:02:17 -06002937bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002938{
John Kessenich077e0522016-06-09 02:02:17 -06002939 parseContext.pushScope();
2940 bool result = acceptCompoundStatement(statement);
2941 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002942
2943 return result;
2944}
2945
John Kessenich5f934b02016-03-13 17:58:25 -06002946// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002947// : attributes attributed_statement
2948//
2949// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002950// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002951// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002952// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002953// | declaration_statement
2954// | selection_statement
2955// | switch_statement
2956// | case_label
2957// | iteration_statement
2958// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002959//
2960bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2961{
John Kessenich21472ae2016-06-04 11:46:33 -06002962 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002963
John Kessenich21472ae2016-06-04 11:46:33 -06002964 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002965 TAttributeMap attributes;
2966 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002967
John Kessenich21472ae2016-06-04 11:46:33 -06002968 // attributed_statement
2969 switch (peek()) {
2970 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002971 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002972
John Kessenich21472ae2016-06-04 11:46:33 -06002973 case EHTokIf:
2974 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002975
John Kessenich21472ae2016-06-04 11:46:33 -06002976 case EHTokSwitch:
2977 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002978
John Kessenich21472ae2016-06-04 11:46:33 -06002979 case EHTokFor:
2980 case EHTokDo:
2981 case EHTokWhile:
2982 return acceptIterationStatement(statement);
2983
2984 case EHTokContinue:
2985 case EHTokBreak:
2986 case EHTokDiscard:
2987 case EHTokReturn:
2988 return acceptJumpStatement(statement);
2989
2990 case EHTokCase:
2991 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002992 case EHTokDefault:
2993 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002994
2995 case EHTokSemicolon:
2996 return acceptTokenClass(EHTokSemicolon);
2997
2998 case EHTokRightBrace:
2999 // Performance: not strictly necessary, but stops a bunch of hunting early,
3000 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003001 return false;
3002
John Kessenich21472ae2016-06-04 11:46:33 -06003003 default:
3004 {
3005 // declaration
3006 if (acceptDeclaration(statement))
3007 return true;
3008
3009 // expression
3010 TIntermTyped* node;
3011 if (acceptExpression(node))
3012 statement = node;
3013 else
3014 return false;
3015
3016 // SEMICOLON (following an expression)
3017 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003018 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06003019 return false;
3020 }
3021 }
3022 }
3023
John Kessenich5f934b02016-03-13 17:58:25 -06003024 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003025}
3026
John Kessenich21472ae2016-06-04 11:46:33 -06003027// attributes
3028// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
3029//
3030// attribute:
3031// : UNROLL
3032// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3033// | FASTOPT
3034// | ALLOW_UAV_CONDITION
3035// | BRANCH
3036// | FLATTEN
3037// | FORCECASE
3038// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003039// | DOMAIN
3040// | EARLYDEPTHSTENCIL
3041// | INSTANCE
3042// | MAXTESSFACTOR
3043// | OUTPUTCONTROLPOINTS
3044// | OUTPUTTOPOLOGY
3045// | PARTITIONING
3046// | PATCHCONSTANTFUNC
3047// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003048//
steve-lunarg1868b142016-10-20 13:07:10 -06003049void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003050{
steve-lunarg1868b142016-10-20 13:07:10 -06003051 // For now, accept the [ XXX(X) ] syntax, but drop all but
3052 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003053 // TODO: subset to correct set? Pass on?
3054 do {
steve-lunarg1868b142016-10-20 13:07:10 -06003055 HlslToken idToken;
3056
John Kessenich0d2b6de2016-06-05 11:23:11 -06003057 // LEFT_BRACKET?
3058 if (! acceptTokenClass(EHTokLeftBracket))
3059 return;
3060
3061 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06003062 if (acceptIdentifier(idToken)) {
3063 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06003064 } else if (! peekTokenClass(EHTokRightBracket)) {
3065 expected("identifier");
3066 advanceToken();
3067 }
3068
steve-lunarga22f7db2016-11-11 08:17:44 -07003069 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003070
3071 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003072 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003073 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003074
John Kessenich0d2b6de2016-06-05 11:23:11 -06003075 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003076 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003077
steve-lunarga22f7db2016-11-11 08:17:44 -07003078 while (acceptAssignmentExpression(node)) {
3079 expectingExpression = false;
3080 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003081 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003082 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003083 }
3084
steve-lunarga22f7db2016-11-11 08:17:44 -07003085 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003086 if (! acceptTokenClass(EHTokRightParen))
3087 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003088
3089 // Error for partial or missing expression
3090 if (expectingExpression || expressions->getSequence().empty())
3091 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003092 }
3093
3094 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003095 if (!acceptTokenClass(EHTokRightBracket)) {
3096 expected("]");
3097 return;
3098 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003099
steve-lunarg1868b142016-10-20 13:07:10 -06003100 // Add any values we found into the attribute map. This accepts
3101 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07003102 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003103 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003104}
3105
John Kessenich0d2b6de2016-06-05 11:23:11 -06003106// selection_statement
3107// : IF LEFT_PAREN expression RIGHT_PAREN statement
3108// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3109//
John Kessenich21472ae2016-06-04 11:46:33 -06003110bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
3111{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003112 TSourceLoc loc = token.loc;
3113
3114 // IF
3115 if (! acceptTokenClass(EHTokIf))
3116 return false;
3117
3118 // so that something declared in the condition is scoped to the lifetimes
3119 // of the then-else statements
3120 parseContext.pushScope();
3121
3122 // LEFT_PAREN expression RIGHT_PAREN
3123 TIntermTyped* condition;
3124 if (! acceptParenExpression(condition))
3125 return false;
3126
3127 // create the child statements
3128 TIntermNodePair thenElse = { nullptr, nullptr };
3129
3130 // then statement
3131 if (! acceptScopedStatement(thenElse.node1)) {
3132 expected("then statement");
3133 return false;
3134 }
3135
3136 // ELSE
3137 if (acceptTokenClass(EHTokElse)) {
3138 // else statement
3139 if (! acceptScopedStatement(thenElse.node2)) {
3140 expected("else statement");
3141 return false;
3142 }
3143 }
3144
3145 // Put the pieces together
3146 statement = intermediate.addSelection(condition, thenElse, loc);
3147 parseContext.popScope();
3148
3149 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003150}
3151
John Kessenichd02dc5d2016-07-01 00:04:11 -06003152// switch_statement
3153// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3154//
John Kessenich21472ae2016-06-04 11:46:33 -06003155bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
3156{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003157 // SWITCH
3158 TSourceLoc loc = token.loc;
3159 if (! acceptTokenClass(EHTokSwitch))
3160 return false;
3161
3162 // LEFT_PAREN expression RIGHT_PAREN
3163 parseContext.pushScope();
3164 TIntermTyped* switchExpression;
3165 if (! acceptParenExpression(switchExpression)) {
3166 parseContext.popScope();
3167 return false;
3168 }
3169
3170 // compound_statement
3171 parseContext.pushSwitchSequence(new TIntermSequence);
3172 bool statementOkay = acceptCompoundStatement(statement);
3173 if (statementOkay)
3174 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
3175
3176 parseContext.popSwitchSequence();
3177 parseContext.popScope();
3178
3179 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003180}
3181
John Kessenich119f8f62016-06-05 15:44:07 -06003182// iteration_statement
3183// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3184// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3185// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3186//
3187// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06003188bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
3189{
John Kessenich119f8f62016-06-05 15:44:07 -06003190 TSourceLoc loc = token.loc;
3191 TIntermTyped* condition = nullptr;
3192
3193 EHlslTokenClass loop = peek();
3194 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3195
3196 // WHILE or DO or FOR
3197 advanceToken();
3198
3199 switch (loop) {
3200 case EHTokWhile:
3201 // so that something declared in the condition is scoped to the lifetime
3202 // of the while sub-statement
3203 parseContext.pushScope();
3204 parseContext.nestLooping();
3205
3206 // LEFT_PAREN condition RIGHT_PAREN
3207 if (! acceptParenExpression(condition))
3208 return false;
3209
3210 // statement
3211 if (! acceptScopedStatement(statement)) {
3212 expected("while sub-statement");
3213 return false;
3214 }
3215
3216 parseContext.unnestLooping();
3217 parseContext.popScope();
3218
3219 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
3220
3221 return true;
3222
3223 case EHTokDo:
3224 parseContext.nestLooping();
3225
3226 if (! acceptTokenClass(EHTokLeftBrace))
3227 expected("{");
3228
3229 // statement
3230 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
3231 expected("do sub-statement");
3232 return false;
3233 }
3234
3235 if (! acceptTokenClass(EHTokRightBrace))
3236 expected("}");
3237
3238 // WHILE
3239 if (! acceptTokenClass(EHTokWhile)) {
3240 expected("while");
3241 return false;
3242 }
3243
3244 // LEFT_PAREN condition RIGHT_PAREN
3245 TIntermTyped* condition;
3246 if (! acceptParenExpression(condition))
3247 return false;
3248
3249 if (! acceptTokenClass(EHTokSemicolon))
3250 expected(";");
3251
3252 parseContext.unnestLooping();
3253
3254 statement = intermediate.addLoop(statement, condition, 0, false, loc);
3255
3256 return true;
3257
3258 case EHTokFor:
3259 {
3260 // LEFT_PAREN
3261 if (! acceptTokenClass(EHTokLeftParen))
3262 expected("(");
3263
3264 // so that something declared in the condition is scoped to the lifetime
3265 // of the for sub-statement
3266 parseContext.pushScope();
3267
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003268 // initializer
3269 TIntermNode* initNode = nullptr;
3270 if (! acceptControlDeclaration(initNode)) {
3271 TIntermTyped* initExpr = nullptr;
3272 acceptExpression(initExpr);
3273 initNode = initExpr;
3274 }
3275 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06003276 if (! acceptTokenClass(EHTokSemicolon))
3277 expected(";");
3278
3279 parseContext.nestLooping();
3280
3281 // condition SEMI_COLON
3282 acceptExpression(condition);
3283 if (! acceptTokenClass(EHTokSemicolon))
3284 expected(";");
3285
3286 // iterator SEMI_COLON
3287 TIntermTyped* iterator = nullptr;
3288 acceptExpression(iterator);
3289 if (! acceptTokenClass(EHTokRightParen))
3290 expected(")");
3291
3292 // statement
3293 if (! acceptScopedStatement(statement)) {
3294 expected("for sub-statement");
3295 return false;
3296 }
3297
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003298 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06003299
3300 parseContext.popScope();
3301 parseContext.unnestLooping();
3302
3303 return true;
3304 }
3305
3306 default:
3307 return false;
3308 }
John Kessenich21472ae2016-06-04 11:46:33 -06003309}
3310
3311// jump_statement
3312// : CONTINUE SEMICOLON
3313// | BREAK SEMICOLON
3314// | DISCARD SEMICOLON
3315// | RETURN SEMICOLON
3316// | RETURN expression SEMICOLON
3317//
3318bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3319{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003320 EHlslTokenClass jump = peek();
3321 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003322 case EHTokContinue:
3323 case EHTokBreak:
3324 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003325 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003326 advanceToken();
3327 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003328 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003329 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003330 return false;
3331 }
John Kessenich21472ae2016-06-04 11:46:33 -06003332
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003333 switch (jump) {
3334 case EHTokContinue:
3335 statement = intermediate.addBranch(EOpContinue, token.loc);
3336 break;
3337 case EHTokBreak:
3338 statement = intermediate.addBranch(EOpBreak, token.loc);
3339 break;
3340 case EHTokDiscard:
3341 statement = intermediate.addBranch(EOpKill, token.loc);
3342 break;
3343
3344 case EHTokReturn:
3345 {
3346 // expression
3347 TIntermTyped* node;
3348 if (acceptExpression(node)) {
3349 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003350 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003351 } else
3352 statement = intermediate.addBranch(EOpReturn, token.loc);
3353 break;
3354 }
3355
3356 default:
3357 assert(0);
3358 return false;
3359 }
3360
3361 // SEMICOLON
3362 if (! acceptTokenClass(EHTokSemicolon))
3363 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003364
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003365 return true;
3366}
John Kessenich21472ae2016-06-04 11:46:33 -06003367
John Kessenichd02dc5d2016-07-01 00:04:11 -06003368// case_label
3369// : CASE expression COLON
3370//
John Kessenich21472ae2016-06-04 11:46:33 -06003371bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3372{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003373 TSourceLoc loc = token.loc;
3374 if (! acceptTokenClass(EHTokCase))
3375 return false;
3376
3377 TIntermTyped* expression;
3378 if (! acceptExpression(expression)) {
3379 expected("case expression");
3380 return false;
3381 }
3382
3383 if (! acceptTokenClass(EHTokColon)) {
3384 expected(":");
3385 return false;
3386 }
3387
3388 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3389
3390 return true;
3391}
3392
3393// default_label
3394// : DEFAULT COLON
3395//
3396bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3397{
3398 TSourceLoc loc = token.loc;
3399 if (! acceptTokenClass(EHTokDefault))
3400 return false;
3401
3402 if (! acceptTokenClass(EHTokColon)) {
3403 expected(":");
3404 return false;
3405 }
3406
3407 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3408
3409 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003410}
3411
John Kessenich19b92ff2016-06-19 11:50:34 -06003412// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003413// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3414// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003415//
3416void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3417{
3418 arraySizes = nullptr;
3419
steve-lunarg7b211a32016-10-13 12:26:18 -06003420 // Early-out if there aren't any array dimensions
3421 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003422 return;
3423
steve-lunarg7b211a32016-10-13 12:26:18 -06003424 // 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 -06003425 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003426
3427 // Collect each array dimension.
3428 while (acceptTokenClass(EHTokLeftBracket)) {
3429 TSourceLoc loc = token.loc;
3430 TIntermTyped* sizeExpr = nullptr;
3431
John Kessenich057df292017-03-06 18:18:37 -07003432 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003433 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3434
3435 if (! acceptTokenClass(EHTokRightBracket)) {
3436 expected("]");
3437 return;
3438 }
3439
3440 if (hasArraySize) {
3441 TArraySize arraySize;
3442 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3443 arraySizes->addInnerSize(arraySize);
3444 } else {
3445 arraySizes->addInnerSize(0); // sized by initializers.
3446 }
steve-lunarg265c0612016-09-27 10:57:35 -06003447 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003448}
3449
John Kessenich630dd7d2016-06-12 23:52:12 -06003450// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003451// : COLON semantic // optional
3452// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3453// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003454// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003455// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003456//
John Kessenich854fe242017-03-02 14:30:59 -07003457// Return true if any tokens were accepted. That is,
3458// false can be returned on successfully recognizing nothing,
3459// not necessarily meaning bad syntax.
3460//
3461bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003462{
John Kessenich854fe242017-03-02 14:30:59 -07003463 bool found = false;
3464
John Kessenich630dd7d2016-06-12 23:52:12 -06003465 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003466 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003467 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003468 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003469 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003470 if (peekTokenClass(EHTokLayout))
3471 acceptLayoutQualifierList(qualifier);
3472 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003473 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003474 if (! acceptTokenClass(EHTokLeftParen)) {
3475 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003476 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003477 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003478 HlslToken locationToken;
3479 if (! acceptIdentifier(locationToken)) {
3480 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003481 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003482 }
3483 HlslToken componentToken;
3484 if (acceptTokenClass(EHTokDot)) {
3485 if (! acceptIdentifier(componentToken)) {
3486 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003487 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003488 }
3489 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003490 if (! acceptTokenClass(EHTokRightParen)) {
3491 expected(")");
3492 break;
3493 }
John Kessenich7735b942016-09-05 12:40:06 -06003494 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003495 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003496 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003497 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003498 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003499 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3500 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003501 if (! acceptTokenClass(EHTokLeftParen)) {
3502 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003503 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003504 }
John Kessenichb38f0712016-07-30 10:29:54 -06003505 HlslToken registerDesc; // for Type#
3506 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003507 if (! acceptIdentifier(registerDesc)) {
3508 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003509 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003510 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003511 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3512 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003513 // Then we didn't really see the registerDesc yet, it was
3514 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003515 profile = registerDesc;
3516 if (! acceptIdentifier(registerDesc)) {
3517 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003518 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003519 }
3520 }
John Kessenichb38f0712016-07-30 10:29:54 -06003521 int subComponent = 0;
3522 if (acceptTokenClass(EHTokLeftBracket)) {
3523 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3524 if (! peekTokenClass(EHTokIntConstant)) {
3525 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003526 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003527 }
3528 subComponent = token.i;
3529 advanceToken();
3530 if (! acceptTokenClass(EHTokRightBracket)) {
3531 expected("]");
3532 break;
3533 }
3534 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003535 // (COMMA SPACEN)opt
3536 HlslToken spaceDesc;
3537 if (acceptTokenClass(EHTokComma)) {
3538 if (! acceptIdentifier(spaceDesc)) {
3539 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003540 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003541 }
3542 }
3543 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003544 if (! acceptTokenClass(EHTokRightParen)) {
3545 expected(")");
3546 break;
3547 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003548 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003549 } else {
3550 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06003551 TString semanticUpperCase = *idToken.string;
3552 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
3553 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06003554 }
John Kessenich854fe242017-03-02 14:30:59 -07003555 } else if (peekTokenClass(EHTokLeftAngle)) {
3556 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06003557 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07003558 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06003559 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003560
John Kessenich630dd7d2016-06-12 23:52:12 -06003561 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07003562
3563 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06003564}
3565
John Kessenichb16f7e62017-03-11 19:32:47 -07003566//
3567// Get the stream of tokens from the scanner, but skip all syntactic/semantic
3568// processing.
3569//
3570bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
3571{
3572 if (! peekTokenClass(EHTokLeftBrace))
3573 return false;
3574
3575 int braceCount = 0;
3576
3577 do {
3578 switch (peek()) {
3579 case EHTokLeftBrace:
3580 ++braceCount;
3581 break;
3582 case EHTokRightBrace:
3583 --braceCount;
3584 break;
3585 case EHTokNone:
3586 // End of input before balance { } is bad...
3587 return false;
3588 default:
3589 break;
3590 }
3591
3592 tokens.push_back(token);
3593 advanceToken();
3594 } while (braceCount > 0);
3595
3596 return true;
3597}
3598
John Kesseniche01a9bc2016-03-12 20:11:22 -07003599} // end namespace glslang