blob: 155a5b81ffd20f6042df11b779e685e32b527ddc [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
John Kessenich927608b2017-01-06 12:34:14 -07002// Copyright (C) 2016 Google, Inc.
3// Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
John Kessenich927608b2017-01-06 12:34:14 -07005// All rights reserved.
John Kesseniche01a9bc2016-03-12 20:11:22 -07006//
John Kessenich927608b2017-01-06 12:34:14 -07007// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
John Kesseniche01a9bc2016-03-12 20:11:22 -070010//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
John Kessenich927608b2017-01-06 12:34:14 -070023// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34// POSSIBILITY OF SUCH DAMAGE.
John Kesseniche01a9bc2016-03-12 20:11:22 -070035//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenich7a41f962017-03-22 11:38:22 -060078// IDENTIFIER
79// THIS
80// type that can be used as IDENTIFIER
81//
John Kessenichaecd4972016-03-14 10:46:34 -060082// Only process the next token if it is an identifier.
83// Return true if it was an identifier.
84bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
85{
John Kessenich7a41f962017-03-22 11:38:22 -060086 // IDENTIFIER
John Kessenichaecd4972016-03-14 10:46:34 -060087 if (peekTokenClass(EHTokIdentifier)) {
88 idToken = token;
89 advanceToken();
90 return true;
91 }
92
John Kessenich7a41f962017-03-22 11:38:22 -060093 // THIS
94 // -> maps to the IDENTIFIER spelled with the internal special name for 'this'
95 if (peekTokenClass(EHTokThis)) {
96 idToken = token;
97 advanceToken();
98 idToken.tokenClass = EHTokIdentifier;
99 idToken.string = NewPoolTString(intermediate.implicitThisName);
100 return true;
101 }
102
103 // type that can be used as IDENTIFIER
104
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700105 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
106 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
107 // valid identifier, nor is "linear". This code special cases the known instances of this, so
108 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -0700109
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700110 TString* idString = nullptr;
111 switch (peek()) {
112 case EHTokSample: idString = NewPoolTString("sample"); break;
113 case EHTokHalf: idString = NewPoolTString("half"); break;
114 case EHTokBool: idString = NewPoolTString("bool"); break;
115 case EHTokFloat: idString = NewPoolTString("float"); break;
116 case EHTokDouble: idString = NewPoolTString("double"); break;
117 case EHTokInt: idString = NewPoolTString("int"); break;
118 case EHTokUint: idString = NewPoolTString("uint"); break;
119 case EHTokMin16float: idString = NewPoolTString("min16float"); break;
120 case EHTokMin10float: idString = NewPoolTString("min10float"); break;
121 case EHTokMin16int: idString = NewPoolTString("min16int"); break;
122 case EHTokMin12int: idString = NewPoolTString("min12int"); break;
123 default:
124 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700125 }
126
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700127 token.string = idString;
128 token.tokenClass = EHTokIdentifier;
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700129 idToken = token;
130
131 advanceToken();
132
133 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600134}
135
John Kesseniche01a9bc2016-03-12 20:11:22 -0700136// compilationUnit
137// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600138// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700139//
140bool HlslGrammar::acceptCompilationUnit()
141{
John Kessenichd016be12016-03-13 11:24:20 -0600142 TIntermNode* unitNode = nullptr;
143
John Kessenich9c86c6a2016-05-03 22:49:24 -0600144 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600145 // HLSL allows semicolons between global declarations, e.g, between functions.
146 if (acceptTokenClass(EHTokSemicolon))
147 continue;
148
John Kessenichd016be12016-03-13 11:24:20 -0600149 // externalDeclaration
John Kessenichca71d942017-03-07 20:44:09 -0700150 if (! acceptDeclaration(unitNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700151 return false;
152 }
153
John Kessenichd016be12016-03-13 11:24:20 -0600154 // set root of AST
John Kessenichca71d942017-03-07 20:44:09 -0700155 if (unitNode && !unitNode->getAsAggregate())
156 unitNode = intermediate.growAggregate(nullptr, unitNode);
John Kessenich078d7f22016-03-14 10:02:11 -0600157 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600158
John Kesseniche01a9bc2016-03-12 20:11:22 -0700159 return true;
160}
161
LoopDawg4886f692016-06-29 10:58:58 -0600162// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700163// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600164//
165// sampler_state_assignment
166// : sampler_state_identifier EQUAL value SEMICOLON
167//
168// sampler_state_identifier
169// : ADDRESSU
170// | ADDRESSV
171// | ADDRESSW
172// | BORDERCOLOR
173// | FILTER
174// | MAXANISOTROPY
175// | MAXLOD
176// | MINLOD
177// | MIPLODBIAS
178//
179bool HlslGrammar::acceptSamplerState()
180{
181 // TODO: this should be genericized to accept a list of valid tokens and
182 // return token/value pairs. Presently it is specific to texture values.
183
184 if (! acceptTokenClass(EHTokLeftBrace))
185 return true;
186
187 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700188
LoopDawg4886f692016-06-29 10:58:58 -0600189 do {
190 // read state name
191 HlslToken state;
192 if (! acceptIdentifier(state))
193 break; // end of list
194
195 // FXC accepts any case
196 TString stateName = *state.string;
197 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
198
199 if (! acceptTokenClass(EHTokAssign)) {
200 expected("assign");
201 return false;
202 }
203
204 if (stateName == "minlod" || stateName == "maxlod") {
205 if (! peekTokenClass(EHTokIntConstant)) {
206 expected("integer");
207 return false;
208 }
209
210 TIntermTyped* lod = nullptr;
211 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
212 return false;
213 } else if (stateName == "maxanisotropy") {
214 if (! peekTokenClass(EHTokIntConstant)) {
215 expected("integer");
216 return false;
217 }
218
219 TIntermTyped* maxAnisotropy = nullptr;
220 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
221 return false;
222 } else if (stateName == "filter") {
223 HlslToken filterMode;
224 if (! acceptIdentifier(filterMode)) {
225 expected("filter mode");
226 return false;
227 }
228 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
229 HlslToken addrMode;
230 if (! acceptIdentifier(addrMode)) {
231 expected("texture address mode");
232 return false;
233 }
234 } else if (stateName == "miplodbias") {
235 TIntermTyped* lodBias = nullptr;
236 if (! acceptLiteral(lodBias)) {
237 expected("lod bias");
238 return false;
239 }
240 } else if (stateName == "bordercolor") {
241 return false;
242 } else {
243 expected("texture state");
244 return false;
245 }
246
247 // SEMICOLON
248 if (! acceptTokenClass(EHTokSemicolon)) {
249 expected("semicolon");
250 return false;
251 }
252 } while (true);
253
254 if (! acceptTokenClass(EHTokRightBrace))
255 return false;
256
257 return true;
258}
259
260// sampler_declaration_dx9
261// : SAMPLER identifier EQUAL sampler_type sampler_state
262//
John Kesseniche4821e42016-07-16 10:19:43 -0600263bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600264{
265 if (! acceptTokenClass(EHTokSampler))
266 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700267
LoopDawg4886f692016-06-29 10:58:58 -0600268 // TODO: remove this when DX9 style declarations are implemented.
269 unimplemented("Direct3D 9 sampler declaration");
270
271 // read sampler name
272 HlslToken name;
273 if (! acceptIdentifier(name)) {
274 expected("sampler name");
275 return false;
276 }
277
278 if (! acceptTokenClass(EHTokAssign)) {
279 expected("=");
280 return false;
281 }
282
283 return false;
284}
285
John Kesseniche01a9bc2016-03-12 20:11:22 -0700286// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600287// : sampler_declaration_dx9 post_decls SEMICOLON
288// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600289// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600290// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600291// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700292//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600293// declarator_list
294// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600295//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600296// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600297// : identifier array_specifier post_decls
298// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600299// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600300//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600301// Parsing has to go pretty far in to know whether it's a variable, prototype, or
302// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600303// as above. (The 'identifier' in the first item in init_declarator list is the
304// same as 'identifier' for function declarations.)
305//
John Kessenichca71d942017-03-07 20:44:09 -0700306// This can generate more than one subtree, one per initializer or a function body.
307// All initializer subtrees are put in their own aggregate node, making one top-level
308// node for all the initializers. Each function created is a top-level node to grow
309// into the passed-in nodeList.
John Kessenichd016be12016-03-13 11:24:20 -0600310//
John Kessenichca71d942017-03-07 20:44:09 -0700311// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
312// each top-level node the declaration creates. Otherwise, if only one top-level
313// node in generated here, that is want is returned in nodeList.
John Kessenich02467d82017-01-19 15:41:47 -0700314//
John Kessenichca71d942017-03-07 20:44:09 -0700315bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700316{
John Kessenich54ee28f2017-03-11 14:13:00 -0700317 bool declarator_list = false; // true when processing comma separation
John Kessenichd016be12016-03-13 11:24:20 -0600318
steve-lunarg1868b142016-10-20 13:07:10 -0600319 // attributes
John Kessenich088d52b2017-03-11 17:55:28 -0700320 TFunctionDeclarator declarator;
321 acceptAttributes(declarator.attributes);
steve-lunarg1868b142016-10-20 13:07:10 -0600322
John Kessenich5e69ec62016-07-05 00:02:40 -0600323 // typedef
324 bool typedefDecl = acceptTokenClass(EHTokTypedef);
325
John Kesseniche82061d2016-09-27 14:38:57 -0600326 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600327
328 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600329 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
330 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
331 // HLSL shaders, this will have to be a master level switch
332 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700333 // For that reason, this line is commented out
John Kessenichca71d942017-03-07 20:44:09 -0700334 // if (acceptSamplerDeclarationDX9(declaredType))
335 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600336
337 // fully_specified_type
John Kessenich54ee28f2017-03-11 14:13:00 -0700338 if (! acceptFullySpecifiedType(declaredType, nodeList))
John Kessenich87142c72016-03-12 20:24:24 -0700339 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600340
John Kessenich87142c72016-03-12 20:24:24 -0700341 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600342 HlslToken idToken;
John Kessenichca71d942017-03-07 20:44:09 -0700343 TIntermAggregate* initializers = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600344 while (acceptIdentifier(idToken)) {
John Kessenich78388722017-03-08 18:53:51 -0700345 if (peekTokenClass(EHTokLeftParen)) {
346 // looks like function parameters
John Kessenich4dc835c2017-03-28 23:43:10 -0600347 const TString* fnName = idToken.string;
steve-lunargf1e0c872016-10-31 15:13:43 -0600348
John Kessenich78388722017-03-08 18:53:51 -0700349 // Potentially rename shader entry point function. No-op most of the time.
350 parseContext.renameShaderFunction(fnName);
steve-lunargf1e0c872016-10-31 15:13:43 -0600351
John Kessenich78388722017-03-08 18:53:51 -0700352 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -0700353 declarator.function = new TFunction(fnName, declaredType);
354 if (!acceptFunctionParameters(*declarator.function)) {
John Kessenich78388722017-03-08 18:53:51 -0700355 expected("function parameter list");
356 return false;
357 }
358
John Kessenich630dd7d2016-06-12 23:52:12 -0600359 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -0700360 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600361
John Kessenichd5ed0b62016-07-04 17:32:45 -0600362 // compound_statement (function body definition) or just a prototype?
John Kessenich088d52b2017-03-11 17:55:28 -0700363 declarator.loc = token.loc;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600364 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700365 if (declarator_list)
John Kessenichd5ed0b62016-07-04 17:32:45 -0600366 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600367 if (typedefDecl)
368 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenichb16f7e62017-03-11 19:32:47 -0700369 return acceptFunctionDefinition(declarator, nodeList, nullptr);
John Kessenich5e69ec62016-07-05 00:02:40 -0600370 } else {
371 if (typedefDecl)
372 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich088d52b2017-03-11 17:55:28 -0700373 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600374 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600375 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600376 // A variable declaration. Fix the storage qualifier if it's a global.
377 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
378 declaredType.getQualifier().storage = EvqUniform;
379
John Kessenichecba76f2017-01-06 00:34:48 -0700380 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600381 // the number of types can expand when arrayness is different.
382 TType variableType;
383 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600384
John Kesseniche82061d2016-09-27 14:38:57 -0600385 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600386 TArraySizes* arraySizes = nullptr;
387 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600388
John Kesseniche82061d2016-09-27 14:38:57 -0600389 // Fix arrayness in the variableType
390 if (declaredType.isImplicitlySizedArray()) {
391 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
392 // of different sizes, for this case sharing the shallow copy of arrayness
393 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
394 variableType.newArraySizes(declaredType.getArraySizes());
395 }
396 if (arraySizes || variableType.isArray()) {
397 // In the most general case, arrayness is potentially coming both from the
398 // declared type and from the variable: "int[] a[];" or just one or the other.
399 // Merge it all to the variableType, so all arrayness is part of the variableType.
400 parseContext.arrayDimMerge(variableType, arraySizes);
401 }
402
LoopDawg4886f692016-06-29 10:58:58 -0600403 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600404 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600405 if (! acceptSamplerState())
406 return false;
407 }
408
John Kessenichd5ed0b62016-07-04 17:32:45 -0600409 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600410 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600411
412 // EQUAL assignment_expression
413 TIntermTyped* expressionNode = nullptr;
414 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600415 if (typedefDecl)
416 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600417 if (! acceptAssignmentExpression(expressionNode)) {
418 expected("initializer");
419 return false;
420 }
421 }
422
John Kessenich6dbc0a72016-09-27 19:13:05 -0600423 // TODO: things scoped within an annotation need their own name space;
424 // TODO: strings are not yet handled.
425 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
426 if (typedefDecl)
427 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
428 else if (variableType.getBasicType() == EbtBlock)
steve-lunargdd8287a2017-02-23 18:04:12 -0700429 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600430 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700431 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600432 // this isn't really an individual variable, but a member of the $Global buffer
433 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
434 } else {
435 // Declare the variable and add any initializer code to the AST.
436 // The top-level node is always made into an aggregate, as that's
437 // historically how the AST has been.
John Kessenichca71d942017-03-07 20:44:09 -0700438 initializers = intermediate.growAggregate(initializers,
439 parseContext.declareVariable(idToken.loc, *idToken.string, variableType, expressionNode),
440 idToken.loc);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600441 }
442 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600443 }
John Kessenich5f934b02016-03-13 17:58:25 -0600444 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600445
446 if (acceptTokenClass(EHTokComma)) {
John Kessenich54ee28f2017-03-11 14:13:00 -0700447 declarator_list = true;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600448 continue;
449 }
450 };
451
John Kessenichca71d942017-03-07 20:44:09 -0700452 // The top-level initializer node is a sequence.
453 if (initializers != nullptr)
454 initializers->setOperator(EOpSequence);
455
456 // Add the initializers' aggregate to the nodeList we were handed.
457 if (nodeList)
458 nodeList = intermediate.growAggregate(nodeList, initializers);
459 else
460 nodeList = initializers;
John Kessenich87142c72016-03-12 20:24:24 -0700461
John Kessenich078d7f22016-03-14 10:02:11 -0600462 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600463 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700464 // This may have been a false detection of what appeared to be a declaration, but
465 // was actually an assignment such as "float = 4", where "float" is an identifier.
466 // We put the token back to let further parsing happen for cases where that may
467 // happen. This errors on the side of caution, and mostly triggers the error.
468
469 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
470 recedeToken();
471 else
472 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600473 return false;
474 }
John Kessenichecba76f2017-01-06 00:34:48 -0700475
John Kesseniche01a9bc2016-03-12 20:11:22 -0700476 return true;
477}
478
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600479// control_declaration
480// : fully_specified_type identifier EQUAL expression
481//
482bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
483{
484 node = nullptr;
485
486 // fully_specified_type
487 TType type;
488 if (! acceptFullySpecifiedType(type))
489 return false;
490
John Kessenich057df292017-03-06 18:18:37 -0700491 // filter out type casts
492 if (peekTokenClass(EHTokLeftParen)) {
493 recedeToken();
494 return false;
495 }
496
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600497 // identifier
498 HlslToken idToken;
499 if (! acceptIdentifier(idToken)) {
500 expected("identifier");
501 return false;
502 }
503
504 // EQUAL
505 TIntermTyped* expressionNode = nullptr;
506 if (! acceptTokenClass(EHTokAssign)) {
507 expected("=");
508 return false;
509 }
510
511 // expression
512 if (! acceptExpression(expressionNode)) {
513 expected("initializer");
514 return false;
515 }
516
John Kesseniche82061d2016-09-27 14:38:57 -0600517 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600518
519 return true;
520}
521
John Kessenich87142c72016-03-12 20:24:24 -0700522// fully_specified_type
523// : type_specifier
524// | type_qualifier type_specifier
525//
526bool HlslGrammar::acceptFullySpecifiedType(TType& type)
527{
John Kessenich54ee28f2017-03-11 14:13:00 -0700528 TIntermNode* nodeList = nullptr;
529 return acceptFullySpecifiedType(type, nodeList);
530}
531bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
532{
John Kessenich87142c72016-03-12 20:24:24 -0700533 // type_qualifier
534 TQualifier qualifier;
535 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600536 if (! acceptQualifier(qualifier))
537 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600538 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700539
540 // type_specifier
John Kessenich54ee28f2017-03-11 14:13:00 -0700541 if (! acceptType(type, nodeList)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -0700542 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700543 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700544 // qualifier. Back it out, if we did.
545 if (qualifier.sample)
546 recedeToken();
547
John Kessenich87142c72016-03-12 20:24:24 -0700548 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700549 }
John Kessenich3d157c52016-07-25 16:05:33 -0600550 if (type.getBasicType() == EbtBlock) {
551 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600552 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600553 // further, it can create an anonymous instance of the block
554 if (peekTokenClass(EHTokSemicolon))
555 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600556 } else {
557 // Some qualifiers are set when parsing the type. Merge those with
558 // whatever comes from acceptQualifier.
559 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700560
steve-lunargbb0183f2016-10-04 16:58:14 -0600561 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600562 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700563
steve-lunargd3947d22017-03-19 12:40:12 -0600564 // Propagate sampler readonly qualifier for buffers
565 if (type.getBasicType() == EbtSampler)
566 qualifier.readonly = type.getQualifier().readonly;
567
steve-lunarg5da1f032017-02-12 17:50:28 -0700568 if (type.getQualifier().storage == EvqVaryingOut ||
569 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700570 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700571 qualifier.readonly = type.getQualifier().readonly;
572 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700573
574 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600575 }
John Kessenich87142c72016-03-12 20:24:24 -0700576
577 return true;
578}
579
John Kessenich630dd7d2016-06-12 23:52:12 -0600580// type_qualifier
581// : qualifier qualifier ...
582//
583// Zero or more of these, so this can't return false.
584//
John Kessenichb9e39122016-08-17 10:22:08 -0600585bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700586{
John Kessenich630dd7d2016-06-12 23:52:12 -0600587 do {
588 switch (peek()) {
589 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600590 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600591 break;
592 case EHTokExtern:
593 // TODO: no meaning in glslang?
594 break;
595 case EHTokShared:
596 // TODO: hint
597 break;
598 case EHTokGroupShared:
599 qualifier.storage = EvqShared;
600 break;
601 case EHTokUniform:
602 qualifier.storage = EvqUniform;
603 break;
604 case EHTokConst:
605 qualifier.storage = EvqConst;
606 break;
607 case EHTokVolatile:
608 qualifier.volatil = true;
609 break;
610 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600611 qualifier.smooth = true;
612 break;
613 case EHTokCentroid:
614 qualifier.centroid = true;
615 break;
616 case EHTokNointerpolation:
617 qualifier.flat = true;
618 break;
619 case EHTokNoperspective:
620 qualifier.nopersp = true;
621 break;
622 case EHTokSample:
623 qualifier.sample = true;
624 break;
625 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600626 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600627 break;
628 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600629 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600630 break;
631 case EHTokPrecise:
632 qualifier.noContraction = true;
633 break;
LoopDawg9249c702016-07-12 20:44:32 -0600634 case EHTokIn:
635 qualifier.storage = EvqIn;
636 break;
637 case EHTokOut:
638 qualifier.storage = EvqOut;
639 break;
640 case EHTokInOut:
641 qualifier.storage = EvqInOut;
642 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600643 case EHTokLayout:
644 if (! acceptLayoutQualifierList(qualifier))
645 return false;
646 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700647 case EHTokGloballyCoherent:
648 qualifier.coherent = true;
649 break;
John Kessenich36b218d2017-03-15 09:05:14 -0600650 case EHTokInline:
651 // TODO: map this to SPIR-V function control
652 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700653
654 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
655 // for output variables.
656 case EHTokPoint:
657 qualifier.storage = EvqIn;
658 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
659 return false;
660 break;
661 case EHTokLine:
662 qualifier.storage = EvqIn;
663 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
664 return false;
665 break;
666 case EHTokTriangle:
667 qualifier.storage = EvqIn;
668 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
669 return false;
670 break;
671 case EHTokLineAdj:
672 qualifier.storage = EvqIn;
673 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
674 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700675 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700676 case EHTokTriangleAdj:
677 qualifier.storage = EvqIn;
678 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
679 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700680 break;
681
John Kessenich630dd7d2016-06-12 23:52:12 -0600682 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600683 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600684 }
685 advanceToken();
686 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700687}
688
John Kessenichb9e39122016-08-17 10:22:08 -0600689// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600690// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600691//
692// layout_qualifier
693// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600694// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600695//
696// Zero or more of these, so this can't return false.
697//
698bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
699{
700 if (! acceptTokenClass(EHTokLayout))
701 return false;
702
703 // LEFT_PAREN
704 if (! acceptTokenClass(EHTokLeftParen))
705 return false;
706
707 do {
708 // identifier
709 HlslToken idToken;
710 if (! acceptIdentifier(idToken))
711 break;
712
713 // EQUAL expression
714 if (acceptTokenClass(EHTokAssign)) {
715 TIntermTyped* expr;
716 if (! acceptConditionalExpression(expr)) {
717 expected("expression");
718 return false;
719 }
720 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
721 } else
722 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
723
724 // COMMA
725 if (! acceptTokenClass(EHTokComma))
726 break;
727 } while (true);
728
729 // RIGHT_PAREN
730 if (! acceptTokenClass(EHTokRightParen)) {
731 expected(")");
732 return false;
733 }
734
735 return true;
736}
737
LoopDawg6daaa4f2016-06-23 19:13:48 -0600738// template_type
739// : FLOAT
740// | DOUBLE
741// | INT
742// | DWORD
743// | UINT
744// | BOOL
745//
steve-lunargf49cdf42016-11-17 15:04:20 -0700746bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600747{
748 switch (peek()) {
749 case EHTokFloat:
750 basicType = EbtFloat;
751 break;
752 case EHTokDouble:
753 basicType = EbtDouble;
754 break;
755 case EHTokInt:
756 case EHTokDword:
757 basicType = EbtInt;
758 break;
759 case EHTokUint:
760 basicType = EbtUint;
761 break;
762 case EHTokBool:
763 basicType = EbtBool;
764 break;
765 default:
766 return false;
767 }
768
769 advanceToken();
770
771 return true;
772}
773
774// vector_template_type
775// : VECTOR
776// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
777//
778bool HlslGrammar::acceptVectorTemplateType(TType& type)
779{
780 if (! acceptTokenClass(EHTokVector))
781 return false;
782
783 if (! acceptTokenClass(EHTokLeftAngle)) {
784 // in HLSL, 'vector' alone means float4.
785 new(&type) TType(EbtFloat, EvqTemporary, 4);
786 return true;
787 }
788
789 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700790 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600791 expected("scalar type");
792 return false;
793 }
794
795 // COMMA
796 if (! acceptTokenClass(EHTokComma)) {
797 expected(",");
798 return false;
799 }
800
801 // integer
802 if (! peekTokenClass(EHTokIntConstant)) {
803 expected("literal integer");
804 return false;
805 }
806
807 TIntermTyped* vecSize;
808 if (! acceptLiteral(vecSize))
809 return false;
810
811 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
812
813 new(&type) TType(basicType, EvqTemporary, vecSizeI);
814
815 if (vecSizeI == 1)
816 type.makeVector();
817
818 if (!acceptTokenClass(EHTokRightAngle)) {
819 expected("right angle bracket");
820 return false;
821 }
822
823 return true;
824}
825
826// matrix_template_type
827// : MATRIX
828// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
829//
830bool HlslGrammar::acceptMatrixTemplateType(TType& type)
831{
832 if (! acceptTokenClass(EHTokMatrix))
833 return false;
834
835 if (! acceptTokenClass(EHTokLeftAngle)) {
836 // in HLSL, 'matrix' alone means float4x4.
837 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
838 return true;
839 }
840
841 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700842 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600843 expected("scalar type");
844 return false;
845 }
846
847 // COMMA
848 if (! acceptTokenClass(EHTokComma)) {
849 expected(",");
850 return false;
851 }
852
853 // integer rows
854 if (! peekTokenClass(EHTokIntConstant)) {
855 expected("literal integer");
856 return false;
857 }
858
859 TIntermTyped* rows;
860 if (! acceptLiteral(rows))
861 return false;
862
863 // COMMA
864 if (! acceptTokenClass(EHTokComma)) {
865 expected(",");
866 return false;
867 }
John Kessenichecba76f2017-01-06 00:34:48 -0700868
LoopDawg6daaa4f2016-06-23 19:13:48 -0600869 // integer cols
870 if (! peekTokenClass(EHTokIntConstant)) {
871 expected("literal integer");
872 return false;
873 }
874
875 TIntermTyped* cols;
876 if (! acceptLiteral(cols))
877 return false;
878
879 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600880 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
881 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600882
883 if (!acceptTokenClass(EHTokRightAngle)) {
884 expected("right angle bracket");
885 return false;
886 }
887
888 return true;
889}
890
steve-lunargf49cdf42016-11-17 15:04:20 -0700891// layout_geometry
892// : LINESTREAM
893// | POINTSTREAM
894// | TRIANGLESTREAM
895//
896bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
897{
898 // read geometry type
899 const EHlslTokenClass geometryType = peek();
900
901 switch (geometryType) {
902 case EHTokPointStream: geometry = ElgPoints; break;
903 case EHTokLineStream: geometry = ElgLineStrip; break;
904 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
905 default:
906 return false; // not a layout geometry
907 }
908
909 advanceToken(); // consume the layout keyword
910 return true;
911}
912
steve-lunarg858c9282017-01-07 08:54:10 -0700913// tessellation_decl_type
914// : INPUTPATCH
915// | OUTPUTPATCH
916//
917bool HlslGrammar::acceptTessellationDeclType()
918{
919 // read geometry type
920 const EHlslTokenClass tessType = peek();
921
922 switch (tessType) {
923 case EHTokInputPatch: break;
924 case EHTokOutputPatch: break;
925 default:
926 return false; // not a tessellation decl
927 }
928
929 advanceToken(); // consume the keyword
930 return true;
931}
932
933// tessellation_patch_template_type
934// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
935//
936bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
937{
938 if (! acceptTessellationDeclType())
939 return false;
940
941 if (! acceptTokenClass(EHTokLeftAngle))
942 return false;
943
944 if (! acceptType(type)) {
945 expected("tessellation patch type");
946 return false;
947 }
948
949 if (! acceptTokenClass(EHTokComma))
950 return false;
951
952 // integer size
953 if (! peekTokenClass(EHTokIntConstant)) {
954 expected("literal integer");
955 return false;
956 }
957
958 TIntermTyped* size;
959 if (! acceptLiteral(size))
960 return false;
961
962 TArraySizes* arraySizes = new TArraySizes;
963 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
964 type.newArraySizes(*arraySizes);
965
966 if (! acceptTokenClass(EHTokRightAngle)) {
967 expected("right angle bracket");
968 return false;
969 }
970
971 return true;
972}
973
steve-lunargf49cdf42016-11-17 15:04:20 -0700974// stream_out_template_type
975// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
976//
977bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
978{
979 geometry = ElgNone;
980
981 if (! acceptOutputPrimitiveGeometry(geometry))
982 return false;
983
984 if (! acceptTokenClass(EHTokLeftAngle))
985 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700986
steve-lunargf49cdf42016-11-17 15:04:20 -0700987 if (! acceptType(type)) {
988 expected("stream output type");
989 return false;
990 }
991
992 type.getQualifier().storage = EvqVaryingOut;
993
994 if (! acceptTokenClass(EHTokRightAngle)) {
995 expected("right angle bracket");
996 return false;
997 }
998
999 return true;
1000}
John Kessenichecba76f2017-01-06 00:34:48 -07001001
John Kessenicha1e2d492016-09-20 13:22:58 -06001002// annotations
1003// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -06001004//
John Kessenicha1e2d492016-09-20 13:22:58 -06001005bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -06001006{
John Kessenicha1e2d492016-09-20 13:22:58 -06001007 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -06001008 return false;
1009
John Kessenicha1e2d492016-09-20 13:22:58 -06001010 // note that we are nesting a name space
1011 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -06001012
1013 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1014 do {
1015 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1016 while (acceptTokenClass(EHTokSemicolon))
1017 ;
1018
1019 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -06001020 break;
John Kessenich86f71382016-09-19 20:23:18 -06001021
1022 // declaration
John Kessenichca71d942017-03-07 20:44:09 -07001023 TIntermNode* node = nullptr;
John Kessenich86f71382016-09-19 20:23:18 -06001024 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -06001025 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -06001026 return false;
1027 }
1028 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -06001029
1030 parseContext.unnestAnnotations();
1031 return true;
John Kessenich86f71382016-09-19 20:23:18 -06001032}
LoopDawg6daaa4f2016-06-23 19:13:48 -06001033
LoopDawg4886f692016-06-29 10:58:58 -06001034// sampler_type
1035// : SAMPLER
1036// | SAMPLER1D
1037// | SAMPLER2D
1038// | SAMPLER3D
1039// | SAMPLERCUBE
1040// | SAMPLERSTATE
1041// | SAMPLERCOMPARISONSTATE
1042bool HlslGrammar::acceptSamplerType(TType& type)
1043{
1044 // read sampler type
1045 const EHlslTokenClass samplerType = peek();
1046
LoopDawga78b0292016-07-19 14:28:05 -06001047 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001048 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001049
LoopDawga78b0292016-07-19 14:28:05 -06001050 bool isShadow = false;
1051
LoopDawg4886f692016-06-29 10:58:58 -06001052 switch (samplerType) {
1053 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001054 case EHTokSampler1d: /*dim = Esd1D*/; break;
1055 case EHTokSampler2d: /*dim = Esd2D*/; break;
1056 case EHTokSampler3d: /*dim = Esd3D*/; break;
1057 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001058 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001059 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001060 default:
1061 return false; // not a sampler declaration
1062 }
1063
1064 advanceToken(); // consume the sampler type keyword
1065
1066 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001067
1068 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001069 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001070
1071 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1072
1073 return true;
1074}
1075
1076// texture_type
1077// | BUFFER
1078// | TEXTURE1D
1079// | TEXTURE1DARRAY
1080// | TEXTURE2D
1081// | TEXTURE2DARRAY
1082// | TEXTURE3D
1083// | TEXTURECUBE
1084// | TEXTURECUBEARRAY
1085// | TEXTURE2DMS
1086// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001087// | RWBUFFER
1088// | RWTEXTURE1D
1089// | RWTEXTURE1DARRAY
1090// | RWTEXTURE2D
1091// | RWTEXTURE2DARRAY
1092// | RWTEXTURE3D
1093
LoopDawg4886f692016-06-29 10:58:58 -06001094bool HlslGrammar::acceptTextureType(TType& type)
1095{
1096 const EHlslTokenClass textureType = peek();
1097
1098 TSamplerDim dim = EsdNone;
1099 bool array = false;
1100 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001101 bool image = false;
steve-lunargcf2e7272017-03-17 13:19:42 -06001102 bool readonly = false;
LoopDawg4886f692016-06-29 10:58:58 -06001103
1104 switch (textureType) {
steve-lunargcf2e7272017-03-17 13:19:42 -06001105 case EHTokTexture1d: dim = Esd1D; break;
1106 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1107 case EHTokTexture2d: dim = Esd2D; break;
1108 case EHTokTexture2darray: dim = Esd2D; array = true; break;
1109 case EHTokTexture3d: dim = Esd3D; break;
1110 case EHTokTextureCube: dim = EsdCube; break;
1111 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1112 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1113 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
1114 case EHTokBuffer: dim = EsdBuffer; readonly=true; image=true; break;
1115 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1116 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1117 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1118 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1119 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1120 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001121 default:
1122 return false; // not a texture declaration
1123 }
1124
1125 advanceToken(); // consume the texture object keyword
1126
1127 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001128
LoopDawg4886f692016-06-29 10:58:58 -06001129 TIntermTyped* msCount = nullptr;
1130
steve-lunargbb0183f2016-10-04 16:58:14 -06001131 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001132 if (acceptTokenClass(EHTokLeftAngle)) {
1133 if (! acceptType(txType)) {
1134 expected("scalar or vector type");
1135 return false;
1136 }
1137
1138 const TBasicType basicRetType = txType.getBasicType() ;
1139
1140 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1141 unimplemented("basic type in texture");
1142 return false;
1143 }
1144
steve-lunargd53f7172016-07-27 15:46:48 -06001145 // Buffers can handle small mats if they fit in 4 components
1146 if (dim == EsdBuffer && txType.isMatrix()) {
1147 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1148 expected("components < 4 in matrix buffer type");
1149 return false;
1150 }
1151
1152 // TODO: except we don't handle it yet...
1153 unimplemented("matrix type in buffer");
1154 return false;
1155 }
1156
LoopDawg4886f692016-06-29 10:58:58 -06001157 if (!txType.isScalar() && !txType.isVector()) {
1158 expected("scalar or vector type");
1159 return false;
1160 }
1161
LoopDawg4886f692016-06-29 10:58:58 -06001162 if (ms && acceptTokenClass(EHTokComma)) {
1163 // read sample count for multisample types, if given
1164 if (! peekTokenClass(EHTokIntConstant)) {
1165 expected("multisample count");
1166 return false;
1167 }
1168
1169 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1170 return false;
1171 }
1172
1173 if (! acceptTokenClass(EHTokRightAngle)) {
1174 expected("right angle bracket");
1175 return false;
1176 }
1177 } else if (ms) {
1178 expected("texture type for multisample");
1179 return false;
steve-lunargcf2e7272017-03-17 13:19:42 -06001180 } else if (image && !readonly) {
steve-lunargbb0183f2016-10-04 16:58:14 -06001181 expected("type for RWTexture/RWBuffer");
1182 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001183 }
1184
1185 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001186 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001187
1188 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001189 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001190
steve-lunarg4f2da272016-10-10 15:24:57 -06001191 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1192 if (image || dim == EsdBuffer)
1193 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001194
1195 // Non-image Buffers are combined
1196 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001197 sampler.set(txType.getBasicType(), dim, array);
1198 } else {
1199 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001200 if (image) {
1201 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1202 } else {
1203 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1204 }
steve-lunargd53f7172016-07-27 15:46:48 -06001205 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001206
1207 // Remember the declared vector size.
1208 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001209
LoopDawg4886f692016-06-29 10:58:58 -06001210 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1211
LoopDawg4886f692016-06-29 10:58:58 -06001212 type.getQualifier().layoutFormat = format;
steve-lunargcf2e7272017-03-17 13:19:42 -06001213 type.getQualifier().readonly = readonly;
LoopDawg4886f692016-06-29 10:58:58 -06001214
1215 return true;
1216}
1217
John Kessenich87142c72016-03-12 20:24:24 -07001218// If token is for a type, update 'type' with the type information,
1219// and return true and advance.
1220// Otherwise, return false, and don't advance
1221bool HlslGrammar::acceptType(TType& type)
1222{
John Kessenich54ee28f2017-03-11 14:13:00 -07001223 TIntermNode* nodeList = nullptr;
1224 return acceptType(type, nodeList);
1225}
1226bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1227{
steve-lunarg3226b082016-10-26 19:18:55 -06001228 // Basic types for min* types, broken out here in case of future
1229 // changes, e.g, to use native halfs.
1230 static const TBasicType min16float_bt = EbtFloat;
1231 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001232 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001233 static const TBasicType min16int_bt = EbtInt;
1234 static const TBasicType min12int_bt = EbtInt;
1235 static const TBasicType min16uint_bt = EbtUint;
1236
John Kessenich9c86c6a2016-05-03 22:49:24 -06001237 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001238 case EHTokVector:
1239 return acceptVectorTemplateType(type);
1240 break;
1241
1242 case EHTokMatrix:
1243 return acceptMatrixTemplateType(type);
1244 break;
1245
steve-lunargf49cdf42016-11-17 15:04:20 -07001246 case EHTokPointStream: // fall through
1247 case EHTokLineStream: // ...
1248 case EHTokTriangleStream: // ...
1249 {
1250 TLayoutGeometry geometry;
1251 if (! acceptStreamOutTemplateType(type, geometry))
1252 return false;
1253
1254 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1255 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001256
steve-lunargf49cdf42016-11-17 15:04:20 -07001257 return true;
1258 }
1259
steve-lunarg858c9282017-01-07 08:54:10 -07001260 case EHTokInputPatch: // fall through
1261 case EHTokOutputPatch: // ...
1262 {
1263 if (! acceptTessellationPatchTemplateType(type))
1264 return false;
1265
1266 return true;
1267 }
1268
LoopDawg4886f692016-06-29 10:58:58 -06001269 case EHTokSampler: // fall through
1270 case EHTokSampler1d: // ...
1271 case EHTokSampler2d: // ...
1272 case EHTokSampler3d: // ...
1273 case EHTokSamplerCube: // ...
1274 case EHTokSamplerState: // ...
1275 case EHTokSamplerComparisonState: // ...
1276 return acceptSamplerType(type);
1277 break;
1278
1279 case EHTokBuffer: // fall through
1280 case EHTokTexture1d: // ...
1281 case EHTokTexture1darray: // ...
1282 case EHTokTexture2d: // ...
1283 case EHTokTexture2darray: // ...
1284 case EHTokTexture3d: // ...
1285 case EHTokTextureCube: // ...
1286 case EHTokTextureCubearray: // ...
1287 case EHTokTexture2DMS: // ...
1288 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001289 case EHTokRWTexture1d: // ...
1290 case EHTokRWTexture1darray: // ...
1291 case EHTokRWTexture2d: // ...
1292 case EHTokRWTexture2darray: // ...
1293 case EHTokRWTexture3d: // ...
1294 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001295 return acceptTextureType(type);
1296 break;
1297
steve-lunarg5da1f032017-02-12 17:50:28 -07001298 case EHTokAppendStructuredBuffer:
1299 case EHTokByteAddressBuffer:
1300 case EHTokConsumeStructuredBuffer:
1301 case EHTokRWByteAddressBuffer:
1302 case EHTokRWStructuredBuffer:
1303 case EHTokStructuredBuffer:
1304 return acceptStructBufferType(type);
1305 break;
1306
John Kessenich27ffb292017-03-03 17:01:01 -07001307 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001308 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001309 case EHTokCBuffer:
1310 case EHTokTBuffer:
John Kessenich54ee28f2017-03-11 14:13:00 -07001311 return acceptStruct(type, nodeList);
John Kesseniche6e74942016-06-11 16:43:14 -06001312
1313 case EHTokIdentifier:
1314 // An identifier could be for a user-defined type.
1315 // Note we cache the symbol table lookup, to save for a later rule
1316 // when this is not a type.
John Kessenichf4ba25e2017-03-21 18:35:04 -06001317 if (parseContext.lookupUserType(*token.string, type) != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001318 advanceToken();
1319 return true;
1320 } else
1321 return false;
1322
John Kessenich71351de2016-06-08 12:50:56 -06001323 case EHTokVoid:
1324 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001325 break;
John Kessenich71351de2016-06-08 12:50:56 -06001326
John Kessenicha1e2d492016-09-20 13:22:58 -06001327 case EHTokString:
1328 new(&type) TType(EbtString);
1329 break;
1330
John Kessenich87142c72016-03-12 20:24:24 -07001331 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001332 new(&type) TType(EbtFloat);
1333 break;
John Kessenich87142c72016-03-12 20:24:24 -07001334 case EHTokFloat1:
1335 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001336 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001337 break;
John Kessenich87142c72016-03-12 20:24:24 -07001338 case EHTokFloat2:
1339 new(&type) TType(EbtFloat, EvqTemporary, 2);
1340 break;
1341 case EHTokFloat3:
1342 new(&type) TType(EbtFloat, EvqTemporary, 3);
1343 break;
1344 case EHTokFloat4:
1345 new(&type) TType(EbtFloat, EvqTemporary, 4);
1346 break;
1347
John Kessenich71351de2016-06-08 12:50:56 -06001348 case EHTokDouble:
1349 new(&type) TType(EbtDouble);
1350 break;
1351 case EHTokDouble1:
1352 new(&type) TType(EbtDouble);
1353 type.makeVector();
1354 break;
1355 case EHTokDouble2:
1356 new(&type) TType(EbtDouble, EvqTemporary, 2);
1357 break;
1358 case EHTokDouble3:
1359 new(&type) TType(EbtDouble, EvqTemporary, 3);
1360 break;
1361 case EHTokDouble4:
1362 new(&type) TType(EbtDouble, EvqTemporary, 4);
1363 break;
1364
1365 case EHTokInt:
1366 case EHTokDword:
1367 new(&type) TType(EbtInt);
1368 break;
1369 case EHTokInt1:
1370 new(&type) TType(EbtInt);
1371 type.makeVector();
1372 break;
John Kessenich87142c72016-03-12 20:24:24 -07001373 case EHTokInt2:
1374 new(&type) TType(EbtInt, EvqTemporary, 2);
1375 break;
1376 case EHTokInt3:
1377 new(&type) TType(EbtInt, EvqTemporary, 3);
1378 break;
1379 case EHTokInt4:
1380 new(&type) TType(EbtInt, EvqTemporary, 4);
1381 break;
1382
John Kessenich71351de2016-06-08 12:50:56 -06001383 case EHTokUint:
1384 new(&type) TType(EbtUint);
1385 break;
1386 case EHTokUint1:
1387 new(&type) TType(EbtUint);
1388 type.makeVector();
1389 break;
1390 case EHTokUint2:
1391 new(&type) TType(EbtUint, EvqTemporary, 2);
1392 break;
1393 case EHTokUint3:
1394 new(&type) TType(EbtUint, EvqTemporary, 3);
1395 break;
1396 case EHTokUint4:
1397 new(&type) TType(EbtUint, EvqTemporary, 4);
1398 break;
1399
1400 case EHTokBool:
1401 new(&type) TType(EbtBool);
1402 break;
1403 case EHTokBool1:
1404 new(&type) TType(EbtBool);
1405 type.makeVector();
1406 break;
John Kessenich87142c72016-03-12 20:24:24 -07001407 case EHTokBool2:
1408 new(&type) TType(EbtBool, EvqTemporary, 2);
1409 break;
1410 case EHTokBool3:
1411 new(&type) TType(EbtBool, EvqTemporary, 3);
1412 break;
1413 case EHTokBool4:
1414 new(&type) TType(EbtBool, EvqTemporary, 4);
1415 break;
1416
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001417 case EHTokHalf:
1418 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1419 break;
1420 case EHTokHalf1:
1421 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1422 type.makeVector();
1423 break;
1424 case EHTokHalf2:
1425 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1426 break;
1427 case EHTokHalf3:
1428 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1429 break;
1430 case EHTokHalf4:
1431 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1432 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001433
steve-lunarg3226b082016-10-26 19:18:55 -06001434 case EHTokMin16float:
1435 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1436 break;
1437 case EHTokMin16float1:
1438 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1439 type.makeVector();
1440 break;
1441 case EHTokMin16float2:
1442 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1443 break;
1444 case EHTokMin16float3:
1445 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1446 break;
1447 case EHTokMin16float4:
1448 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1449 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001450
steve-lunarg3226b082016-10-26 19:18:55 -06001451 case EHTokMin10float:
1452 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1453 break;
1454 case EHTokMin10float1:
1455 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1456 type.makeVector();
1457 break;
1458 case EHTokMin10float2:
1459 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1460 break;
1461 case EHTokMin10float3:
1462 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1463 break;
1464 case EHTokMin10float4:
1465 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1466 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001467
steve-lunarg3226b082016-10-26 19:18:55 -06001468 case EHTokMin16int:
1469 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1470 break;
1471 case EHTokMin16int1:
1472 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1473 type.makeVector();
1474 break;
1475 case EHTokMin16int2:
1476 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1477 break;
1478 case EHTokMin16int3:
1479 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1480 break;
1481 case EHTokMin16int4:
1482 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1483 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001484
steve-lunarg3226b082016-10-26 19:18:55 -06001485 case EHTokMin12int:
1486 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1487 break;
1488 case EHTokMin12int1:
1489 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1490 type.makeVector();
1491 break;
1492 case EHTokMin12int2:
1493 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1494 break;
1495 case EHTokMin12int3:
1496 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1497 break;
1498 case EHTokMin12int4:
1499 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1500 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001501
steve-lunarg3226b082016-10-26 19:18:55 -06001502 case EHTokMin16uint:
1503 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1504 break;
1505 case EHTokMin16uint1:
1506 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1507 type.makeVector();
1508 break;
1509 case EHTokMin16uint2:
1510 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1511 break;
1512 case EHTokMin16uint3:
1513 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1514 break;
1515 case EHTokMin16uint4:
1516 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1517 break;
1518
John Kessenich0133c122016-05-20 12:17:26 -06001519 case EHTokInt1x1:
1520 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1521 break;
1522 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001523 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001524 break;
1525 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001526 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001527 break;
1528 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001529 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001530 break;
1531 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001532 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001533 break;
1534 case EHTokInt2x2:
1535 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1536 break;
1537 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001538 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001539 break;
1540 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001541 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001542 break;
1543 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001544 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001545 break;
1546 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001547 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001548 break;
1549 case EHTokInt3x3:
1550 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1551 break;
1552 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001553 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001554 break;
1555 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001556 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001557 break;
1558 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001559 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001560 break;
1561 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001562 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001563 break;
1564 case EHTokInt4x4:
1565 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1566 break;
1567
John Kessenich71351de2016-06-08 12:50:56 -06001568 case EHTokUint1x1:
1569 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1570 break;
1571 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001572 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001573 break;
1574 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001575 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001576 break;
1577 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001578 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001579 break;
1580 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001581 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001582 break;
1583 case EHTokUint2x2:
1584 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1585 break;
1586 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001587 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001588 break;
1589 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001590 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001591 break;
1592 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001593 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001594 break;
1595 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001596 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001597 break;
1598 case EHTokUint3x3:
1599 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1600 break;
1601 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001602 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001603 break;
1604 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001605 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001606 break;
1607 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001608 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001609 break;
1610 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001611 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001612 break;
1613 case EHTokUint4x4:
1614 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1615 break;
1616
1617 case EHTokBool1x1:
1618 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1619 break;
1620 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001621 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001622 break;
1623 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001624 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001625 break;
1626 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001627 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001628 break;
1629 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001630 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001631 break;
1632 case EHTokBool2x2:
1633 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1634 break;
1635 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001636 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001637 break;
1638 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001639 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001640 break;
1641 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001642 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001643 break;
1644 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001645 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001646 break;
1647 case EHTokBool3x3:
1648 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1649 break;
1650 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001651 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001652 break;
1653 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001654 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001655 break;
1656 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001657 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001658 break;
1659 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001660 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001661 break;
1662 case EHTokBool4x4:
1663 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1664 break;
1665
John Kessenich0133c122016-05-20 12:17:26 -06001666 case EHTokFloat1x1:
1667 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1668 break;
1669 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001670 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001671 break;
1672 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001673 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001674 break;
1675 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001676 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001677 break;
1678 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001679 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001680 break;
John Kessenich87142c72016-03-12 20:24:24 -07001681 case EHTokFloat2x2:
1682 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1683 break;
1684 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001685 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001686 break;
1687 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001688 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001689 break;
John Kessenich0133c122016-05-20 12:17:26 -06001690 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001691 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001692 break;
John Kessenich87142c72016-03-12 20:24:24 -07001693 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001694 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001695 break;
1696 case EHTokFloat3x3:
1697 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1698 break;
1699 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001700 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001701 break;
John Kessenich0133c122016-05-20 12:17:26 -06001702 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001703 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001704 break;
John Kessenich87142c72016-03-12 20:24:24 -07001705 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001706 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001707 break;
1708 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001709 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001710 break;
1711 case EHTokFloat4x4:
1712 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1713 break;
1714
John Kessenich0133c122016-05-20 12:17:26 -06001715 case EHTokDouble1x1:
1716 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1717 break;
1718 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001719 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001720 break;
1721 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001722 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001723 break;
1724 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001725 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001726 break;
1727 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001728 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001729 break;
1730 case EHTokDouble2x2:
1731 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1732 break;
1733 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001734 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001735 break;
1736 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001737 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001738 break;
1739 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001740 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001741 break;
1742 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001743 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001744 break;
1745 case EHTokDouble3x3:
1746 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1747 break;
1748 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001749 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001750 break;
1751 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001752 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001753 break;
1754 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001755 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001756 break;
1757 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001758 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001759 break;
1760 case EHTokDouble4x4:
1761 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1762 break;
1763
John Kessenich87142c72016-03-12 20:24:24 -07001764 default:
1765 return false;
1766 }
1767
1768 advanceToken();
1769
1770 return true;
1771}
1772
John Kesseniche6e74942016-06-11 16:43:14 -06001773// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001774// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1775// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07001776// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06001777//
1778// struct_type
1779// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001780// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06001781// | CBUFFER
1782// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001783//
John Kessenich54ee28f2017-03-11 14:13:00 -07001784bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
John Kesseniche6e74942016-06-11 16:43:14 -06001785{
John Kessenichb804de62016-09-05 12:19:18 -06001786 // This storage qualifier will tell us whether it's an AST
1787 // block type or just a generic structure type.
1788 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001789
1790 // CBUFFER
1791 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001792 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001793 // TBUFFER
1794 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001795 storageQualifier = EvqBuffer;
John Kessenich27ffb292017-03-03 17:01:01 -07001796 // CLASS
John Kesseniche6e74942016-06-11 16:43:14 -06001797 // STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001798 else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001799 return false;
1800
1801 // IDENTIFIER
1802 TString structName = "";
1803 if (peekTokenClass(EHTokIdentifier)) {
1804 structName = *token.string;
1805 advanceToken();
1806 }
1807
John Kessenich3d157c52016-07-25 16:05:33 -06001808 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001809 TQualifier postDeclQualifier;
1810 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07001811 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001812
John Kessenichf3d88bd2017-03-19 12:24:29 -06001813 // LEFT_BRACE, or
John Kessenich854fe242017-03-02 14:30:59 -07001814 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06001815 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07001816 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
1817 // struct_type IDENTIFIER
1818 return true;
1819 } else {
1820 expected("{");
1821 return false;
1822 }
John Kesseniche6e74942016-06-11 16:43:14 -06001823 }
1824
John Kessenichf3d88bd2017-03-19 12:24:29 -06001825
John Kesseniche6e74942016-06-11 16:43:14 -06001826 // struct_declaration_list
1827 TTypeList* typeList;
John Kessenichf3d88bd2017-03-19 12:24:29 -06001828 // Save each member function so they can be processed after we have a fully formed 'this'.
1829 TVector<TFunctionDeclarator> functionDeclarators;
1830
1831 parseContext.pushNamespace(structName);
John Kessenichaa3c64c2017-03-28 09:52:38 -06001832 bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
John Kessenichf3d88bd2017-03-19 12:24:29 -06001833 parseContext.popNamespace();
1834
1835 if (! acceptedList) {
John Kesseniche6e74942016-06-11 16:43:14 -06001836 expected("struct member declarations");
1837 return false;
1838 }
1839
1840 // RIGHT_BRACE
1841 if (! acceptTokenClass(EHTokRightBrace)) {
1842 expected("}");
1843 return false;
1844 }
1845
1846 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001847 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001848 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001849 else {
John Kessenich7735b942016-09-05 12:40:06 -06001850 postDeclQualifier.storage = storageQualifier;
1851 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001852 }
John Kesseniche6e74942016-06-11 16:43:14 -06001853
John Kessenich727b3742017-02-03 17:57:55 -07001854 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001855
John Kessenich4960baa2017-03-19 18:09:59 -06001856 // For member functions: now that we know the type of 'this', go back and
1857 // - add their implicit argument with 'this' (not to the mangling, just the argument list)
1858 // - parse the functions, their tokens were saved for deferred parsing (now)
1859 for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
1860 // update signature
1861 if (functionDeclarators[b].function->hasImplicitThis())
John Kessenich37789792017-03-21 23:56:40 -06001862 functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
John Kessenich4960baa2017-03-19 18:09:59 -06001863 }
1864
John Kessenichf3d88bd2017-03-19 12:24:29 -06001865 // All member functions get parsed inside the class/struct namespace and with the
1866 // class/struct members in a symbol-table level.
1867 parseContext.pushNamespace(structName);
John Kessenich37789792017-03-21 23:56:40 -06001868 parseContext.pushThisScope(type);
John Kessenichf3d88bd2017-03-19 12:24:29 -06001869 bool deferredSuccess = true;
1870 for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
1871 // parse body
1872 pushTokenStream(functionDeclarators[b].body);
1873 if (! acceptFunctionBody(functionDeclarators[b], nodeList))
1874 deferredSuccess = false;
1875 popTokenStream();
1876 }
John Kessenich37789792017-03-21 23:56:40 -06001877 parseContext.popThisScope();
John Kessenichf3d88bd2017-03-19 12:24:29 -06001878 parseContext.popNamespace();
1879
1880 return deferredSuccess;
John Kesseniche6e74942016-06-11 16:43:14 -06001881}
1882
steve-lunarg5da1f032017-02-12 17:50:28 -07001883// struct_buffer
1884// : APPENDSTRUCTUREDBUFFER
1885// | BYTEADDRESSBUFFER
1886// | CONSUMESTRUCTUREDBUFFER
1887// | RWBYTEADDRESSBUFFER
1888// | RWSTRUCTUREDBUFFER
1889// | STRUCTUREDBUFFER
1890bool HlslGrammar::acceptStructBufferType(TType& type)
1891{
1892 const EHlslTokenClass structBuffType = peek();
1893
1894 // TODO: globallycoherent
1895 bool hasTemplateType = true;
1896 bool readonly = false;
1897
1898 TStorageQualifier storage = EvqBuffer;
1899
1900 switch (structBuffType) {
1901 case EHTokAppendStructuredBuffer:
1902 unimplemented("AppendStructuredBuffer");
1903 return false;
1904 case EHTokByteAddressBuffer:
1905 hasTemplateType = false;
1906 readonly = true;
1907 break;
1908 case EHTokConsumeStructuredBuffer:
1909 unimplemented("ConsumeStructuredBuffer");
1910 return false;
1911 case EHTokRWByteAddressBuffer:
1912 hasTemplateType = false;
1913 break;
1914 case EHTokRWStructuredBuffer:
1915 break;
1916 case EHTokStructuredBuffer:
1917 readonly = true;
1918 break;
1919 default:
1920 return false; // not a structure buffer type
1921 }
1922
1923 advanceToken(); // consume the structure keyword
1924
1925 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
1926 TType* templateType = new TType;
1927
1928 if (hasTemplateType) {
1929 if (! acceptTokenClass(EHTokLeftAngle)) {
1930 expected("left angle bracket");
1931 return false;
1932 }
1933
1934 if (! acceptType(*templateType)) {
1935 expected("type");
1936 return false;
1937 }
1938 if (! acceptTokenClass(EHTokRightAngle)) {
1939 expected("right angle bracket");
1940 return false;
1941 }
1942 } else {
1943 // byte address buffers have no explicit type.
1944 TType uintType(EbtUint, storage);
1945 templateType->shallowCopy(uintType);
1946 }
1947
1948 // Create an unsized array out of that type.
1949 // TODO: does this work if it's already an array type?
1950 TArraySizes unsizedArray;
1951 unsizedArray.addInnerSize(UnsizedArraySize);
1952 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07001953 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07001954
1955 // field name is canonical for all structbuffers
1956 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07001957
1958 // Create block type. TODO: hidden internal uint member when needed
steve-lunargdd8287a2017-02-23 18:04:12 -07001959
steve-lunarg5da1f032017-02-12 17:50:28 -07001960 TTypeList* blockStruct = new TTypeList;
1961 TTypeLoc member = { templateType, token.loc };
1962 blockStruct->push_back(member);
1963
steve-lunargdd8287a2017-02-23 18:04:12 -07001964 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07001965 TType blockType(blockStruct, "", templateType->getQualifier());
1966
steve-lunargdd8287a2017-02-23 18:04:12 -07001967 blockType.getQualifier().storage = storage;
1968 blockType.getQualifier().readonly = readonly;
1969
1970 // We may have created an equivalent type before, in which case we should use its
1971 // deep structure.
1972 parseContext.shareStructBufferType(blockType);
1973
steve-lunarg5da1f032017-02-12 17:50:28 -07001974 type.shallowCopy(blockType);
1975
1976 return true;
1977}
1978
John Kesseniche6e74942016-06-11 16:43:14 -06001979// struct_declaration_list
1980// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1981//
1982// struct_declaration
1983// : fully_specified_type struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07001984// | fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
John Kesseniche6e74942016-06-11 16:43:14 -06001985//
1986// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001987// : IDENTIFIER post_decls
1988// | IDENTIFIER array_specifier post_decls
John Kessenich54ee28f2017-03-11 14:13:00 -07001989// | IDENTIFIER function_parameters post_decls // member-function prototype
John Kesseniche6e74942016-06-11 16:43:14 -06001990//
John Kessenichaa3c64c2017-03-28 09:52:38 -06001991bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
John Kessenichf3d88bd2017-03-19 12:24:29 -06001992 TVector<TFunctionDeclarator>& declarators)
John Kesseniche6e74942016-06-11 16:43:14 -06001993{
1994 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001995 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001996
1997 do {
1998 // success on seeing the RIGHT_BRACE coming up
1999 if (peekTokenClass(EHTokRightBrace))
John Kessenichb16f7e62017-03-11 19:32:47 -07002000 break;
John Kesseniche6e74942016-06-11 16:43:14 -06002001
2002 // struct_declaration
John Kessenich54ee28f2017-03-11 14:13:00 -07002003
2004 bool declarator_list = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002005
2006 // fully_specified_type
2007 TType memberType;
John Kessenich54ee28f2017-03-11 14:13:00 -07002008 if (! acceptFullySpecifiedType(memberType, nodeList)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002009 expected("member type");
2010 return false;
2011 }
2012
2013 // struct_declarator COMMA struct_declarator ...
John Kessenich54ee28f2017-03-11 14:13:00 -07002014 bool functionDefinitionAccepted = false;
John Kesseniche6e74942016-06-11 16:43:14 -06002015 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002016 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002017 expected("member name");
2018 return false;
2019 }
2020
John Kessenich54ee28f2017-03-11 14:13:00 -07002021 if (peekTokenClass(EHTokLeftParen)) {
2022 // function_parameters
2023 if (!declarator_list) {
John Kessenichb16f7e62017-03-11 19:32:47 -07002024 declarators.resize(declarators.size() + 1);
2025 // request a token stream for deferred processing
John Kessenichf3d88bd2017-03-19 12:24:29 -06002026 functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2027 declarators.back());
John Kessenich54ee28f2017-03-11 14:13:00 -07002028 if (functionDefinitionAccepted)
2029 break;
2030 }
2031 expected("member-function definition");
2032 return false;
2033 } else {
2034 // add it to the list of members
2035 TTypeLoc member = { new TType(EbtVoid), token.loc };
2036 member.type->shallowCopy(memberType);
2037 member.type->setFieldName(*idToken.string);
2038 typeList->push_back(member);
John Kesseniche6e74942016-06-11 16:43:14 -06002039
John Kessenich54ee28f2017-03-11 14:13:00 -07002040 // array_specifier
2041 TArraySizes* arraySizes = nullptr;
2042 acceptArraySpecifier(arraySizes);
2043 if (arraySizes)
2044 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06002045
John Kessenich54ee28f2017-03-11 14:13:00 -07002046 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06002047
John Kessenich54ee28f2017-03-11 14:13:00 -07002048 // EQUAL assignment_expression
2049 if (acceptTokenClass(EHTokAssign)) {
2050 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2051 TIntermTyped* expressionNode = nullptr;
2052 if (! acceptAssignmentExpression(expressionNode)) {
2053 expected("initializer");
2054 return false;
2055 }
John Kessenich18adbdb2017-02-02 15:16:20 -07002056 }
2057 }
John Kesseniche6e74942016-06-11 16:43:14 -06002058 // success on seeing the SEMICOLON coming up
2059 if (peekTokenClass(EHTokSemicolon))
2060 break;
2061
2062 // COMMA
John Kessenich54ee28f2017-03-11 14:13:00 -07002063 if (acceptTokenClass(EHTokComma))
2064 declarator_list = true;
2065 else {
John Kesseniche6e74942016-06-11 16:43:14 -06002066 expected(",");
2067 return false;
2068 }
2069
2070 } while (true);
2071
2072 // SEMI_COLON
John Kessenich54ee28f2017-03-11 14:13:00 -07002073 if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002074 expected(";");
2075 return false;
2076 }
2077
2078 } while (true);
John Kessenichb16f7e62017-03-11 19:32:47 -07002079
John Kessenichb16f7e62017-03-11 19:32:47 -07002080 return true;
John Kesseniche6e74942016-06-11 16:43:14 -06002081}
2082
John Kessenich54ee28f2017-03-11 14:13:00 -07002083// member_function_definition
2084// | function_parameters post_decls compound_statement
2085//
2086// Expects type to have EvqGlobal for a static member and
2087// EvqTemporary for non-static member.
John Kessenichf3d88bd2017-03-19 12:24:29 -06002088bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, const TString& memberName,
2089 TFunctionDeclarator& declarator)
John Kessenich54ee28f2017-03-11 14:13:00 -07002090{
John Kessenich54ee28f2017-03-11 14:13:00 -07002091 bool accepted = false;
2092
John Kessenich4dc835c2017-03-28 23:43:10 -06002093 const TString* functionName = &memberName;
2094 parseContext.getFullNamespaceName(functionName);
John Kessenich088d52b2017-03-11 17:55:28 -07002095 declarator.function = new TFunction(functionName, type);
John Kessenich4960baa2017-03-19 18:09:59 -06002096 if (type.getQualifier().storage == EvqTemporary)
2097 declarator.function->setImplicitThis();
John Kessenich37789792017-03-21 23:56:40 -06002098 else
2099 declarator.function->setIllegalImplicitThis();
John Kessenich54ee28f2017-03-11 14:13:00 -07002100
2101 // function_parameters
John Kessenich088d52b2017-03-11 17:55:28 -07002102 if (acceptFunctionParameters(*declarator.function)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002103 // post_decls
John Kessenich088d52b2017-03-11 17:55:28 -07002104 acceptPostDecls(declarator.function->getWritableType().getQualifier());
John Kessenich54ee28f2017-03-11 14:13:00 -07002105
2106 // compound_statement (function body definition)
2107 if (peekTokenClass(EHTokLeftBrace)) {
John Kessenich088d52b2017-03-11 17:55:28 -07002108 declarator.loc = token.loc;
John Kessenichf3d88bd2017-03-19 12:24:29 -06002109 declarator.body = new TVector<HlslToken>;
2110 accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
John Kessenich54ee28f2017-03-11 14:13:00 -07002111 }
2112 } else
2113 expected("function parameter list");
2114
John Kessenich54ee28f2017-03-11 14:13:00 -07002115 return accepted;
2116}
2117
John Kessenich5f934b02016-03-13 17:58:25 -06002118// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06002119// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06002120// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002121//
2122bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2123{
John Kessenich078d7f22016-03-14 10:02:11 -06002124 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002125 if (! acceptTokenClass(EHTokLeftParen))
2126 return false;
2127
John Kessenich71351de2016-06-08 12:50:56 -06002128 // VOID RIGHT_PAREN
2129 if (! acceptTokenClass(EHTokVoid)) {
2130 do {
2131 // parameter_declaration
2132 if (! acceptParameterDeclaration(function))
2133 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002134
John Kessenich71351de2016-06-08 12:50:56 -06002135 // COMMA
2136 if (! acceptTokenClass(EHTokComma))
2137 break;
2138 } while (true);
2139 }
John Kessenich5f934b02016-03-13 17:58:25 -06002140
John Kessenich078d7f22016-03-14 10:02:11 -06002141 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002142 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002143 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002144 return false;
2145 }
2146
2147 return true;
2148}
2149
steve-lunarg26d31452016-12-23 18:56:57 -07002150// default_parameter_declaration
2151// : EQUAL conditional_expression
2152// : EQUAL initializer
2153bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2154{
2155 node = nullptr;
2156
2157 // Valid not to have a default_parameter_declaration
2158 if (!acceptTokenClass(EHTokAssign))
2159 return true;
2160
2161 if (!acceptConditionalExpression(node)) {
2162 if (!acceptInitializer(node))
2163 return false;
2164
2165 // For initializer lists, we have to const-fold into a constructor for the type, so build
2166 // that.
2167 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
2168 if (constructor == nullptr) // cannot construct
2169 return false;
2170
2171 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002172 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002173 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002174
steve-lunarg26d31452016-12-23 18:56:57 -07002175 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2176 }
2177
2178 // If this is simply a constant, we can use it directly.
2179 if (node->getAsConstantUnion())
2180 return true;
2181
2182 // Otherwise, it has to be const-foldable.
2183 TIntermTyped* origNode = node;
2184
2185 node = intermediate.fold(node->getAsAggregate());
2186
2187 if (node != nullptr && origNode != node)
2188 return true;
2189
2190 parseContext.error(token.loc, "invalid default parameter value", "", "");
2191
2192 return false;
2193}
2194
John Kessenich5f934b02016-03-13 17:58:25 -06002195// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002196// : fully_specified_type post_decls [ = default_parameter_declaration ]
2197// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002198//
2199bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2200{
2201 // fully_specified_type
2202 TType* type = new TType;
2203 if (! acceptFullySpecifiedType(*type))
2204 return false;
2205
2206 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002207 HlslToken idToken;
2208 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002209
John Kessenich19b92ff2016-06-19 11:50:34 -06002210 // array_specifier
2211 TArraySizes* arraySizes = nullptr;
2212 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002213 if (arraySizes) {
2214 if (arraySizes->isImplicit()) {
2215 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2216 return false;
2217 }
2218
John Kessenich19b92ff2016-06-19 11:50:34 -06002219 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002220 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002221
2222 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002223 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002224
steve-lunarg26d31452016-12-23 18:56:57 -07002225 TIntermTyped* defaultValue;
2226 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2227 return false;
2228
John Kessenich5aa59e22016-06-17 15:50:47 -06002229 parseContext.paramFix(*type);
2230
steve-lunarg26d31452016-12-23 18:56:57 -07002231 // If any prior parameters have default values, all the parameters after that must as well.
2232 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2233 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2234 return false;
2235 }
2236
2237 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002238 function.addParameter(param);
2239
2240 return true;
2241}
2242
2243// Do the work to create the function definition in addition to
2244// parsing the body (compound_statement).
John Kessenichb16f7e62017-03-11 19:32:47 -07002245//
2246// If 'deferredTokens' are passed in, just get the token stream,
2247// don't process.
2248//
2249bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2250 TVector<HlslToken>* deferredTokens)
John Kessenich5f934b02016-03-13 17:58:25 -06002251{
John Kessenich088d52b2017-03-11 17:55:28 -07002252 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
John Kessenich5f934b02016-03-13 17:58:25 -06002253
John Kessenichb16f7e62017-03-11 19:32:47 -07002254 if (deferredTokens)
2255 return captureBlockTokens(*deferredTokens);
2256 else
John Kessenich4960baa2017-03-19 18:09:59 -06002257 return acceptFunctionBody(declarator, nodeList);
John Kessenich088d52b2017-03-11 17:55:28 -07002258}
2259
2260bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2261{
2262 // we might get back an entry-point
John Kessenichca71d942017-03-07 20:44:09 -07002263 TIntermNode* entryPointNode = nullptr;
2264
John Kessenich077e0522016-06-09 02:02:17 -06002265 // This does a pushScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002266 TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2267 declarator.attributes, entryPointNode);
John Kessenich5f934b02016-03-13 17:58:25 -06002268
2269 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002270 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002271 if (! acceptCompoundStatement(functionBody))
2272 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002273
John Kessenich54ee28f2017-03-11 14:13:00 -07002274 // this does a popScope()
John Kessenich088d52b2017-03-11 17:55:28 -07002275 parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
John Kessenichca71d942017-03-07 20:44:09 -07002276
2277 // Hook up the 1 or 2 function definitions.
2278 nodeList = intermediate.growAggregate(nodeList, functionNode);
2279 nodeList = intermediate.growAggregate(nodeList, entryPointNode);
John Kessenich02467d82017-01-19 15:41:47 -07002280
2281 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002282}
2283
John Kessenich0d2b6de2016-06-05 11:23:11 -06002284// Accept an expression with parenthesis around it, where
2285// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002286// syntactically required ones like in "if ( expression )".
2287//
2288// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002289//
2290// Note this one is not set up to be speculative; as it gives
2291// errors if not found.
2292//
2293bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2294{
2295 // LEFT_PAREN
2296 if (! acceptTokenClass(EHTokLeftParen))
2297 expected("(");
2298
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002299 bool decl = false;
2300 TIntermNode* declNode = nullptr;
2301 decl = acceptControlDeclaration(declNode);
2302 if (decl) {
2303 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2304 expected("initialized declaration");
2305 return false;
2306 } else
2307 expression = declNode->getAsTyped();
2308 } else {
2309 // no declaration
2310 if (! acceptExpression(expression)) {
2311 expected("expression");
2312 return false;
2313 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002314 }
2315
2316 // RIGHT_PAREN
2317 if (! acceptTokenClass(EHTokRightParen))
2318 expected(")");
2319
2320 return true;
2321}
2322
John Kessenich34fb0362016-05-03 23:17:20 -06002323// The top-level full expression recognizer.
2324//
John Kessenich87142c72016-03-12 20:24:24 -07002325// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002326// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002327//
2328bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2329{
LoopDawgef764a22016-06-03 09:17:51 -06002330 node = nullptr;
2331
John Kessenich34fb0362016-05-03 23:17:20 -06002332 // assignment_expression
2333 if (! acceptAssignmentExpression(node))
2334 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002335
John Kessenich34fb0362016-05-03 23:17:20 -06002336 if (! peekTokenClass(EHTokComma))
2337 return true;
2338
2339 do {
2340 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002341 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002342 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002343
John Kessenich34fb0362016-05-03 23:17:20 -06002344 // ... assignment_expression
2345 TIntermTyped* rightNode = nullptr;
2346 if (! acceptAssignmentExpression(rightNode)) {
2347 expected("assignment expression");
2348 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002349 }
2350
John Kessenich34fb0362016-05-03 23:17:20 -06002351 node = intermediate.addComma(node, rightNode, loc);
2352
2353 if (! peekTokenClass(EHTokComma))
2354 return true;
2355 } while (true);
2356}
2357
John Kessenich07354242016-07-01 19:58:06 -06002358// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002359// : LEFT_BRACE RIGHT_BRACE
2360// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002361//
2362// initializer_list
2363// : assignment_expression COMMA assignment_expression COMMA ...
2364//
2365bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2366{
2367 // LEFT_BRACE
2368 if (! acceptTokenClass(EHTokLeftBrace))
2369 return false;
2370
John Kessenich98ad4852016-11-27 17:39:07 -07002371 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002372 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002373 if (acceptTokenClass(EHTokRightBrace)) {
2374 // a zero-length initializer list
2375 node = intermediate.makeAggregate(loc);
2376 return true;
2377 }
2378
2379 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002380 node = nullptr;
2381 do {
2382 // assignment_expression
2383 TIntermTyped* expr;
2384 if (! acceptAssignmentExpression(expr)) {
2385 expected("assignment expression in initializer list");
2386 return false;
2387 }
2388 node = intermediate.growAggregate(node, expr, loc);
2389
2390 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002391 if (acceptTokenClass(EHTokComma)) {
2392 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2393 return true;
John Kessenich07354242016-07-01 19:58:06 -06002394 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002395 }
John Kessenich07354242016-07-01 19:58:06 -06002396
2397 // RIGHT_BRACE
2398 if (acceptTokenClass(EHTokRightBrace))
2399 return true;
2400
2401 expected(", or }");
2402 return false;
2403 } while (true);
2404}
2405
John Kessenich34fb0362016-05-03 23:17:20 -06002406// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002407// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002408//
2409// a op (b op (c op d))
2410//
2411// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002412// : initializer
2413// | conditional_expression
2414// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002415//
2416bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2417{
John Kessenich07354242016-07-01 19:58:06 -06002418 // initializer
2419 if (peekTokenClass(EHTokLeftBrace)) {
2420 if (acceptInitializer(node))
2421 return true;
2422
2423 expected("initializer");
2424 return false;
2425 }
2426
John Kessenich00957f82016-07-27 10:39:57 -06002427 // conditional_expression
2428 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002429 return false;
2430
John Kessenich07354242016-07-01 19:58:06 -06002431 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002432 TOperator assignOp = HlslOpMap::assignment(peek());
2433 if (assignOp == EOpNull)
2434 return true;
2435
John Kessenich00957f82016-07-27 10:39:57 -06002436 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002437 TSourceLoc loc = token.loc;
2438 advanceToken();
2439
John Kessenich00957f82016-07-27 10:39:57 -06002440 // conditional_expression assign_op conditional_expression ...
2441 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002442 // gets the right-to-left associativity.
2443 TIntermTyped* rightNode = nullptr;
2444 if (! acceptAssignmentExpression(rightNode)) {
2445 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002446 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002447 }
2448
John Kessenichd21baed2016-09-16 03:05:12 -06002449 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002450 node = parseContext.handleLvalue(loc, "assign", node);
2451
John Kessenichfea226b2016-07-28 17:53:56 -06002452 if (node == nullptr) {
2453 parseContext.error(loc, "could not create assignment", "", "");
2454 return false;
2455 }
John Kessenich34fb0362016-05-03 23:17:20 -06002456
2457 if (! peekTokenClass(EHTokComma))
2458 return true;
2459
2460 return true;
2461}
2462
John Kessenich00957f82016-07-27 10:39:57 -06002463// Accept a conditional expression, which associates right-to-left,
2464// accomplished by the "true" expression calling down to lower
2465// precedence levels than this level.
2466//
2467// conditional_expression
2468// : binary_expression
2469// | binary_expression QUESTION expression COLON assignment_expression
2470//
2471bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2472{
2473 // binary_expression
2474 if (! acceptBinaryExpression(node, PlLogicalOr))
2475 return false;
2476
2477 if (! acceptTokenClass(EHTokQuestion))
2478 return true;
2479
2480 TIntermTyped* trueNode = nullptr;
2481 if (! acceptExpression(trueNode)) {
2482 expected("expression after ?");
2483 return false;
2484 }
2485 TSourceLoc loc = token.loc;
2486
2487 if (! acceptTokenClass(EHTokColon)) {
2488 expected(":");
2489 return false;
2490 }
2491
2492 TIntermTyped* falseNode = nullptr;
2493 if (! acceptAssignmentExpression(falseNode)) {
2494 expected("expression after :");
2495 return false;
2496 }
2497
2498 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2499
2500 return true;
2501}
2502
John Kessenich34fb0362016-05-03 23:17:20 -06002503// Accept a binary expression, for binary operations that
2504// associate left-to-right. This is, it is implicit, for example
2505//
2506// ((a op b) op c) op d
2507//
2508// binary_expression
2509// : expression op expression op expression ...
2510//
2511// where 'expression' is the next higher level in precedence.
2512//
2513bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2514{
2515 if (precedenceLevel > PlMul)
2516 return acceptUnaryExpression(node);
2517
2518 // assignment_expression
2519 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2520 return false;
2521
John Kessenich34fb0362016-05-03 23:17:20 -06002522 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002523 TOperator op = HlslOpMap::binary(peek());
2524 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2525 if (tokenLevel < precedenceLevel)
2526 return true;
2527
John Kessenich34fb0362016-05-03 23:17:20 -06002528 // ... op
2529 TSourceLoc loc = token.loc;
2530 advanceToken();
2531
2532 // ... expression
2533 TIntermTyped* rightNode = nullptr;
2534 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2535 expected("expression");
2536 return false;
2537 }
2538
2539 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002540 if (node == nullptr) {
2541 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2542 return false;
2543 }
John Kessenich34fb0362016-05-03 23:17:20 -06002544 } while (true);
2545}
2546
2547// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002548// : (type) unary_expression
2549// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002550// | - unary_expression
2551// | ! unary_expression
2552// | ~ unary_expression
2553// | ++ unary_expression
2554// | -- unary_expression
2555// | postfix_expression
2556//
2557bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2558{
John Kessenich1cc1a282016-06-03 16:55:49 -06002559 // (type) unary_expression
2560 // Have to look two steps ahead, because this could be, e.g., a
2561 // postfix_expression instead, since that also starts with at "(".
2562 if (acceptTokenClass(EHTokLeftParen)) {
2563 TType castType;
2564 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002565 if (acceptTokenClass(EHTokRightParen)) {
2566 // We've matched "(type)" now, get the expression to cast
2567 TSourceLoc loc = token.loc;
2568 if (! acceptUnaryExpression(node))
2569 return false;
2570
2571 // Hook it up like a constructor
2572 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2573 if (constructorFunction == nullptr) {
2574 expected("type that can be constructed");
2575 return false;
2576 }
2577 TIntermTyped* arguments = nullptr;
2578 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2579 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2580
2581 return true;
2582 } else {
2583 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2584 // the '(int' part. We must back up twice.
2585 recedeToken();
2586 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002587 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002588 } else {
2589 // This isn't a type cast, but it still started "(", so if it is a
2590 // unary expression, it can only be a postfix_expression, so try that.
2591 // Back it up first.
2592 recedeToken();
2593 return acceptPostfixExpression(node);
2594 }
2595 }
2596
2597 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002598 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002599
John Kessenich1cc1a282016-06-03 16:55:49 -06002600 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002601 if (unaryOp == EOpNull)
2602 return acceptPostfixExpression(node);
2603
2604 // op unary_expression
2605 TSourceLoc loc = token.loc;
2606 advanceToken();
2607 if (! acceptUnaryExpression(node))
2608 return false;
2609
2610 // + is a no-op
2611 if (unaryOp == EOpAdd)
2612 return true;
2613
2614 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002615
2616 // These unary ops require lvalues
2617 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2618 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002619
2620 return node != nullptr;
2621}
2622
2623// postfix_expression
2624// : LEFT_PAREN expression RIGHT_PAREN
2625// | literal
2626// | constructor
2627// | identifier
2628// | function_call
2629// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2630// | postfix_expression DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002631// | postfix_expression DOT IDENTIFIER arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07002632// | postfix_expression COLONCOLON IDENTIFIER arguments
John Kessenich34fb0362016-05-03 23:17:20 -06002633// | postfix_expression INC_OP
2634// | postfix_expression DEC_OP
2635//
2636bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2637{
2638 // Not implemented as self-recursive:
John Kessenich54ee28f2017-03-11 14:13:00 -07002639 // The logical "right recursion" is done with a loop at the end
John Kessenich34fb0362016-05-03 23:17:20 -06002640
2641 // idToken will pick up either a variable or a function name in a function call
2642 HlslToken idToken;
2643
John Kessenich54ee28f2017-03-11 14:13:00 -07002644 // scopeBase will pick up the type symbol on the left of '::'
John Kessenich4960baa2017-03-19 18:09:59 -06002645 TSymbol* scope = nullptr;
John Kessenich54ee28f2017-03-11 14:13:00 -07002646
John Kessenich21472ae2016-06-04 11:46:33 -06002647 // Find something before the postfix operations, as they can't operate
2648 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002649 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002650 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002651 if (! acceptExpression(node)) {
2652 expected("expression");
2653 return false;
2654 }
2655 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002656 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002657 return false;
2658 }
John Kessenich34fb0362016-05-03 23:17:20 -06002659 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002660 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002661 } else if (acceptConstructor(node)) {
2662 // constructor (nothing else to do yet)
2663 } else if (acceptIdentifier(idToken)) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002664 // user-type, identifier, or function name
2665 if (peekTokenClass(EHTokColonColon)) {
2666 TType type;
John Kessenich4960baa2017-03-19 18:09:59 -06002667 scope = parseContext.lookupUserType(*idToken.string, type);
2668 if (scope == nullptr) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002669 expected("type left of ::");
2670 return false;
2671 }
2672 } else if (! peekTokenClass(EHTokLeftParen)) {
John Kessenichf4ba25e2017-03-21 18:35:04 -06002673 node = parseContext.handleVariable(idToken.loc, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002674 } else if (acceptFunctionCall(idToken, node)) {
2675 // function_call (nothing else to do yet)
2676 } else {
2677 expected("function call arguments");
2678 return false;
2679 }
John Kessenich21472ae2016-06-04 11:46:33 -06002680 } else {
2681 // nothing found, can't post operate
2682 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002683 }
2684
steve-lunarga2b01a02016-11-28 17:09:54 -07002685 // This is to guarantee we do this no matter how we get out of the stack frame.
2686 // This way there's no bug if an early return forgets to do it.
2687 struct tFinalize {
2688 tFinalize(HlslParseContext& p) : parseContext(p) { }
2689 ~tFinalize() { parseContext.finalizeFlattening(); }
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002690 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002691 private:
John Kessenichca71d942017-03-07 20:44:09 -07002692 const tFinalize& operator=(const tFinalize&) { return *this; }
John Kessenichefeefd92017-03-01 13:12:26 -07002693 tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
steve-lunarga2b01a02016-11-28 17:09:54 -07002694 } finalize(parseContext);
2695
2696 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2697 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2698 // level: hence the init and finalize. Even though in practice these must be
2699 // constants, they are parsed no matter what.
2700 parseContext.initFlattening();
2701
John Kessenich21472ae2016-06-04 11:46:33 -06002702 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002703 do {
2704 TSourceLoc loc = token.loc;
2705 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002706
John Kessenich34fb0362016-05-03 23:17:20 -06002707 // Consume only a valid post-unary operator, otherwise we are done.
2708 switch (postOp) {
2709 case EOpIndexDirectStruct:
2710 case EOpIndexIndirect:
2711 case EOpPostIncrement:
2712 case EOpPostDecrement:
John Kessenich54ee28f2017-03-11 14:13:00 -07002713 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002714 advanceToken();
2715 break;
2716 default:
2717 return true;
2718 }
John Kessenich87142c72016-03-12 20:24:24 -07002719
John Kessenich34fb0362016-05-03 23:17:20 -06002720 // We have a valid post-unary operator, process it.
2721 switch (postOp) {
John Kessenich54ee28f2017-03-11 14:13:00 -07002722 case EOpScoping:
John Kessenich34fb0362016-05-03 23:17:20 -06002723 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002724 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002725 // DOT IDENTIFIER
John Kessenich516d92d2017-03-08 20:09:03 -07002726 // includes swizzles, member variables, and member functions
John Kessenich93a162a2016-06-17 17:16:27 -06002727 HlslToken field;
2728 if (! acceptIdentifier(field)) {
2729 expected("swizzle or member");
2730 return false;
2731 }
LoopDawg4886f692016-06-29 10:58:58 -06002732
John Kessenich516d92d2017-03-08 20:09:03 -07002733 if (peekTokenClass(EHTokLeftParen)) {
2734 // member function
2735 TIntermTyped* thisNode = node;
LoopDawg4886f692016-06-29 10:58:58 -06002736
John Kessenich516d92d2017-03-08 20:09:03 -07002737 // arguments
John Kessenich4960baa2017-03-19 18:09:59 -06002738 if (! acceptFunctionCall(field, node, thisNode, scope)) {
LoopDawg4886f692016-06-29 10:58:58 -06002739 expected("function parameters");
2740 return false;
2741 }
John Kessenich516d92d2017-03-08 20:09:03 -07002742 } else
2743 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002744
John Kessenich34fb0362016-05-03 23:17:20 -06002745 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002746 }
John Kessenich34fb0362016-05-03 23:17:20 -06002747 case EOpIndexIndirect:
2748 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002749 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002750 TIntermTyped* indexNode = nullptr;
2751 if (! acceptExpression(indexNode) ||
2752 ! peekTokenClass(EHTokRightBracket)) {
2753 expected("expression followed by ']'");
2754 return false;
2755 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002756 advanceToken();
2757 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2758 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002759 }
2760 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002761 // INC_OP
2762 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002763 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002764 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002765 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002766 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002767 break;
2768 default:
2769 assert(0);
2770 break;
2771 }
2772 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002773}
2774
John Kessenichd016be12016-03-13 11:24:20 -06002775// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002776// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002777//
2778bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2779{
2780 // type
2781 TType type;
2782 if (acceptType(type)) {
2783 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2784 if (constructorFunction == nullptr)
2785 return false;
2786
2787 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002788 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002789 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002790 // It's possible this is a type keyword used as an identifier. Put the token back
2791 // for later use.
2792 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002793 return false;
2794 }
2795
2796 // hook it up
2797 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2798
2799 return true;
2800 }
2801
2802 return false;
2803}
2804
John Kessenich34fb0362016-05-03 23:17:20 -06002805// The function_call identifier was already recognized, and passed in as idToken.
2806//
2807// function_call
2808// : [idToken] arguments
2809//
John Kessenich54ee28f2017-03-11 14:13:00 -07002810bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, TIntermTyped* baseObject,
John Kessenich4960baa2017-03-19 18:09:59 -06002811 const TSymbol* scope)
John Kessenich34fb0362016-05-03 23:17:20 -06002812{
John Kessenich54ee28f2017-03-11 14:13:00 -07002813 // name
2814 TString* functionName = nullptr;
steve-lunarge7d07522017-03-19 18:12:37 -06002815 if ((baseObject == nullptr && scope == nullptr)) {
2816 functionName = callToken.string;
2817 } else if (parseContext.isBuiltInMethod(callToken.loc, baseObject, *callToken.string)) {
John Kessenich4960baa2017-03-19 18:09:59 -06002818 // Built-in methods are not in the symbol table as methods, but as global functions
2819 // taking an explicit 'this' as the first argument.
steve-lunarge7d07522017-03-19 18:12:37 -06002820 functionName = NewPoolTString(BUILTIN_PREFIX);
2821 functionName->append(*callToken.string);
John Kessenich4960baa2017-03-19 18:09:59 -06002822 } else {
John Kessenich54ee28f2017-03-11 14:13:00 -07002823 functionName = NewPoolTString("");
John Kessenich4960baa2017-03-19 18:09:59 -06002824 if (baseObject != nullptr)
2825 functionName->append(baseObject->getType().getTypeName());
2826 else if (scope != nullptr)
2827 functionName->append(scope->getType().getTypeName());
John Kessenichf3d88bd2017-03-19 12:24:29 -06002828 parseContext.addScopeMangler(*functionName);
John Kessenich54ee28f2017-03-11 14:13:00 -07002829 functionName->append(*callToken.string);
John Kessenich5f12d2f2017-03-11 09:39:55 -07002830 }
LoopDawg4886f692016-06-29 10:58:58 -06002831
John Kessenich54ee28f2017-03-11 14:13:00 -07002832 // function
2833 TFunction* function = new TFunction(functionName, TType(EbtVoid));
2834
2835 // arguments
John Kessenich54ee28f2017-03-11 14:13:00 -07002836 TIntermTyped* arguments = nullptr;
John Kessenichdfbdd9e2017-03-19 13:10:28 -06002837 if (baseObject != nullptr) {
2838 // Non-static member functions have an implicit first argument of the base object.
John Kessenich54ee28f2017-03-11 14:13:00 -07002839 parseContext.handleFunctionArgument(function, arguments, baseObject);
John Kessenichdfbdd9e2017-03-19 13:10:28 -06002840 }
John Kessenich4678ca92016-05-13 09:33:42 -06002841 if (! acceptArguments(function, arguments))
2842 return false;
2843
John Kessenich54ee28f2017-03-11 14:13:00 -07002844 // call
John Kessenich5f12d2f2017-03-11 09:39:55 -07002845 node = parseContext.handleFunctionCall(callToken.loc, function, arguments);
John Kessenich4678ca92016-05-13 09:33:42 -06002846
2847 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002848}
2849
John Kessenich87142c72016-03-12 20:24:24 -07002850// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002851// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002852//
John Kessenichd016be12016-03-13 11:24:20 -06002853// The arguments are pushed onto the 'function' argument list and
2854// onto the 'arguments' aggregate.
2855//
John Kessenich4678ca92016-05-13 09:33:42 -06002856bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002857{
John Kessenich078d7f22016-03-14 10:02:11 -06002858 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002859 if (! acceptTokenClass(EHTokLeftParen))
2860 return false;
2861
2862 do {
John Kessenichd016be12016-03-13 11:24:20 -06002863 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002864 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002865 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002866 break;
John Kessenichd016be12016-03-13 11:24:20 -06002867
2868 // hook it up
2869 parseContext.handleFunctionArgument(function, arguments, arg);
2870
John Kessenich078d7f22016-03-14 10:02:11 -06002871 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002872 if (! acceptTokenClass(EHTokComma))
2873 break;
2874 } while (true);
2875
John Kessenich078d7f22016-03-14 10:02:11 -06002876 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002877 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002878 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002879 return false;
2880 }
2881
2882 return true;
2883}
2884
2885bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2886{
2887 switch (token.tokenClass) {
2888 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002889 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002890 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002891 case EHTokUintConstant:
2892 node = intermediate.addConstantUnion(token.u, token.loc, true);
2893 break;
John Kessenich87142c72016-03-12 20:24:24 -07002894 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002895 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002896 break;
2897 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002898 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002899 break;
2900 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002901 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002902 break;
John Kessenich86f71382016-09-19 20:23:18 -06002903 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07002904 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06002905 break;
John Kessenich87142c72016-03-12 20:24:24 -07002906
2907 default:
2908 return false;
2909 }
2910
2911 advanceToken();
2912
2913 return true;
2914}
2915
John Kessenich5f934b02016-03-13 17:58:25 -06002916// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002917// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002918//
John Kessenich21472ae2016-06-04 11:46:33 -06002919bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002920{
John Kessenich21472ae2016-06-04 11:46:33 -06002921 TIntermAggregate* compoundStatement = nullptr;
2922
John Kessenich34fb0362016-05-03 23:17:20 -06002923 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002924 if (! acceptTokenClass(EHTokLeftBrace))
2925 return false;
2926
2927 // statement statement ...
2928 TIntermNode* statement = nullptr;
2929 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002930 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2931 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2932 branch->getFlowOp() == EOpDefault)) {
2933 // hook up individual subsequences within a switch statement
2934 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2935 compoundStatement = nullptr;
2936 } else {
2937 // hook it up to the growing compound statement
2938 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2939 }
John Kessenich5f934b02016-03-13 17:58:25 -06002940 }
John Kessenich34fb0362016-05-03 23:17:20 -06002941 if (compoundStatement)
2942 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002943
John Kessenich21472ae2016-06-04 11:46:33 -06002944 retStatement = compoundStatement;
2945
John Kessenich34fb0362016-05-03 23:17:20 -06002946 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002947 return acceptTokenClass(EHTokRightBrace);
2948}
2949
John Kessenich0d2b6de2016-06-05 11:23:11 -06002950bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2951{
2952 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002953 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002954 parseContext.popScope();
2955
2956 return result;
2957}
2958
John Kessenich077e0522016-06-09 02:02:17 -06002959bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002960{
John Kessenich077e0522016-06-09 02:02:17 -06002961 parseContext.pushScope();
2962 bool result = acceptCompoundStatement(statement);
2963 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002964
2965 return result;
2966}
2967
John Kessenich5f934b02016-03-13 17:58:25 -06002968// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002969// : attributes attributed_statement
2970//
2971// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002972// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002973// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002974// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002975// | declaration_statement
2976// | selection_statement
2977// | switch_statement
2978// | case_label
2979// | iteration_statement
2980// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002981//
2982bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2983{
John Kessenich21472ae2016-06-04 11:46:33 -06002984 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002985
John Kessenich21472ae2016-06-04 11:46:33 -06002986 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002987 TAttributeMap attributes;
2988 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002989
John Kessenich21472ae2016-06-04 11:46:33 -06002990 // attributed_statement
2991 switch (peek()) {
2992 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002993 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002994
John Kessenich21472ae2016-06-04 11:46:33 -06002995 case EHTokIf:
2996 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002997
John Kessenich21472ae2016-06-04 11:46:33 -06002998 case EHTokSwitch:
2999 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06003000
John Kessenich21472ae2016-06-04 11:46:33 -06003001 case EHTokFor:
3002 case EHTokDo:
3003 case EHTokWhile:
3004 return acceptIterationStatement(statement);
3005
3006 case EHTokContinue:
3007 case EHTokBreak:
3008 case EHTokDiscard:
3009 case EHTokReturn:
3010 return acceptJumpStatement(statement);
3011
3012 case EHTokCase:
3013 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06003014 case EHTokDefault:
3015 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06003016
3017 case EHTokSemicolon:
3018 return acceptTokenClass(EHTokSemicolon);
3019
3020 case EHTokRightBrace:
3021 // Performance: not strictly necessary, but stops a bunch of hunting early,
3022 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06003023 return false;
3024
John Kessenich21472ae2016-06-04 11:46:33 -06003025 default:
3026 {
3027 // declaration
3028 if (acceptDeclaration(statement))
3029 return true;
3030
3031 // expression
3032 TIntermTyped* node;
3033 if (acceptExpression(node))
3034 statement = node;
3035 else
3036 return false;
3037
3038 // SEMICOLON (following an expression)
3039 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06003040 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06003041 return false;
3042 }
3043 }
3044 }
3045
John Kessenich5f934b02016-03-13 17:58:25 -06003046 return true;
John Kessenich87142c72016-03-12 20:24:24 -07003047}
3048
John Kessenich21472ae2016-06-04 11:46:33 -06003049// attributes
3050// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
3051//
3052// attribute:
3053// : UNROLL
3054// | UNROLL LEFT_PAREN literal RIGHT_PAREN
3055// | FASTOPT
3056// | ALLOW_UAV_CONDITION
3057// | BRANCH
3058// | FLATTEN
3059// | FORCECASE
3060// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06003061// | DOMAIN
3062// | EARLYDEPTHSTENCIL
3063// | INSTANCE
3064// | MAXTESSFACTOR
3065// | OUTPUTCONTROLPOINTS
3066// | OUTPUTTOPOLOGY
3067// | PARTITIONING
3068// | PATCHCONSTANTFUNC
3069// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06003070//
steve-lunarg1868b142016-10-20 13:07:10 -06003071void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06003072{
steve-lunarg1868b142016-10-20 13:07:10 -06003073 // For now, accept the [ XXX(X) ] syntax, but drop all but
3074 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06003075 // TODO: subset to correct set? Pass on?
3076 do {
steve-lunarg1868b142016-10-20 13:07:10 -06003077 HlslToken idToken;
3078
John Kessenich0d2b6de2016-06-05 11:23:11 -06003079 // LEFT_BRACKET?
3080 if (! acceptTokenClass(EHTokLeftBracket))
3081 return;
3082
3083 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06003084 if (acceptIdentifier(idToken)) {
3085 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06003086 } else if (! peekTokenClass(EHTokRightBracket)) {
3087 expected("identifier");
3088 advanceToken();
3089 }
3090
steve-lunarga22f7db2016-11-11 08:17:44 -07003091 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06003092
3093 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06003094 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07003095 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06003096
John Kessenich0d2b6de2016-06-05 11:23:11 -06003097 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07003098 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07003099
steve-lunarga22f7db2016-11-11 08:17:44 -07003100 while (acceptAssignmentExpression(node)) {
3101 expectingExpression = false;
3102 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06003103 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07003104 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06003105 }
3106
steve-lunarga22f7db2016-11-11 08:17:44 -07003107 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06003108 if (! acceptTokenClass(EHTokRightParen))
3109 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07003110
3111 // Error for partial or missing expression
3112 if (expectingExpression || expressions->getSequence().empty())
3113 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06003114 }
3115
3116 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06003117 if (!acceptTokenClass(EHTokRightBracket)) {
3118 expected("]");
3119 return;
3120 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06003121
steve-lunarg1868b142016-10-20 13:07:10 -06003122 // Add any values we found into the attribute map. This accepts
3123 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07003124 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06003125 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06003126}
3127
John Kessenich0d2b6de2016-06-05 11:23:11 -06003128// selection_statement
3129// : IF LEFT_PAREN expression RIGHT_PAREN statement
3130// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3131//
John Kessenich21472ae2016-06-04 11:46:33 -06003132bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
3133{
John Kessenich0d2b6de2016-06-05 11:23:11 -06003134 TSourceLoc loc = token.loc;
3135
3136 // IF
3137 if (! acceptTokenClass(EHTokIf))
3138 return false;
3139
3140 // so that something declared in the condition is scoped to the lifetimes
3141 // of the then-else statements
3142 parseContext.pushScope();
3143
3144 // LEFT_PAREN expression RIGHT_PAREN
3145 TIntermTyped* condition;
3146 if (! acceptParenExpression(condition))
3147 return false;
3148
3149 // create the child statements
3150 TIntermNodePair thenElse = { nullptr, nullptr };
3151
3152 // then statement
3153 if (! acceptScopedStatement(thenElse.node1)) {
3154 expected("then statement");
3155 return false;
3156 }
3157
3158 // ELSE
3159 if (acceptTokenClass(EHTokElse)) {
3160 // else statement
3161 if (! acceptScopedStatement(thenElse.node2)) {
3162 expected("else statement");
3163 return false;
3164 }
3165 }
3166
3167 // Put the pieces together
3168 statement = intermediate.addSelection(condition, thenElse, loc);
3169 parseContext.popScope();
3170
3171 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003172}
3173
John Kessenichd02dc5d2016-07-01 00:04:11 -06003174// switch_statement
3175// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3176//
John Kessenich21472ae2016-06-04 11:46:33 -06003177bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
3178{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003179 // SWITCH
3180 TSourceLoc loc = token.loc;
3181 if (! acceptTokenClass(EHTokSwitch))
3182 return false;
3183
3184 // LEFT_PAREN expression RIGHT_PAREN
3185 parseContext.pushScope();
3186 TIntermTyped* switchExpression;
3187 if (! acceptParenExpression(switchExpression)) {
3188 parseContext.popScope();
3189 return false;
3190 }
3191
3192 // compound_statement
3193 parseContext.pushSwitchSequence(new TIntermSequence);
3194 bool statementOkay = acceptCompoundStatement(statement);
3195 if (statementOkay)
3196 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
3197
3198 parseContext.popSwitchSequence();
3199 parseContext.popScope();
3200
3201 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003202}
3203
John Kessenich119f8f62016-06-05 15:44:07 -06003204// iteration_statement
3205// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3206// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3207// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3208//
3209// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06003210bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
3211{
John Kessenich119f8f62016-06-05 15:44:07 -06003212 TSourceLoc loc = token.loc;
3213 TIntermTyped* condition = nullptr;
3214
3215 EHlslTokenClass loop = peek();
3216 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3217
3218 // WHILE or DO or FOR
3219 advanceToken();
3220
3221 switch (loop) {
3222 case EHTokWhile:
3223 // so that something declared in the condition is scoped to the lifetime
3224 // of the while sub-statement
3225 parseContext.pushScope();
3226 parseContext.nestLooping();
3227
3228 // LEFT_PAREN condition RIGHT_PAREN
3229 if (! acceptParenExpression(condition))
3230 return false;
3231
3232 // statement
3233 if (! acceptScopedStatement(statement)) {
3234 expected("while sub-statement");
3235 return false;
3236 }
3237
3238 parseContext.unnestLooping();
3239 parseContext.popScope();
3240
3241 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
3242
3243 return true;
3244
3245 case EHTokDo:
3246 parseContext.nestLooping();
3247
3248 if (! acceptTokenClass(EHTokLeftBrace))
3249 expected("{");
3250
3251 // statement
3252 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
3253 expected("do sub-statement");
3254 return false;
3255 }
3256
3257 if (! acceptTokenClass(EHTokRightBrace))
3258 expected("}");
3259
3260 // WHILE
3261 if (! acceptTokenClass(EHTokWhile)) {
3262 expected("while");
3263 return false;
3264 }
3265
3266 // LEFT_PAREN condition RIGHT_PAREN
3267 TIntermTyped* condition;
3268 if (! acceptParenExpression(condition))
3269 return false;
3270
3271 if (! acceptTokenClass(EHTokSemicolon))
3272 expected(";");
3273
3274 parseContext.unnestLooping();
3275
3276 statement = intermediate.addLoop(statement, condition, 0, false, loc);
3277
3278 return true;
3279
3280 case EHTokFor:
3281 {
3282 // LEFT_PAREN
3283 if (! acceptTokenClass(EHTokLeftParen))
3284 expected("(");
3285
3286 // so that something declared in the condition is scoped to the lifetime
3287 // of the for sub-statement
3288 parseContext.pushScope();
3289
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003290 // initializer
3291 TIntermNode* initNode = nullptr;
3292 if (! acceptControlDeclaration(initNode)) {
3293 TIntermTyped* initExpr = nullptr;
3294 acceptExpression(initExpr);
3295 initNode = initExpr;
3296 }
3297 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06003298 if (! acceptTokenClass(EHTokSemicolon))
3299 expected(";");
3300
3301 parseContext.nestLooping();
3302
3303 // condition SEMI_COLON
3304 acceptExpression(condition);
3305 if (! acceptTokenClass(EHTokSemicolon))
3306 expected(";");
3307
3308 // iterator SEMI_COLON
3309 TIntermTyped* iterator = nullptr;
3310 acceptExpression(iterator);
3311 if (! acceptTokenClass(EHTokRightParen))
3312 expected(")");
3313
3314 // statement
3315 if (! acceptScopedStatement(statement)) {
3316 expected("for sub-statement");
3317 return false;
3318 }
3319
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003320 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06003321
3322 parseContext.popScope();
3323 parseContext.unnestLooping();
3324
3325 return true;
3326 }
3327
3328 default:
3329 return false;
3330 }
John Kessenich21472ae2016-06-04 11:46:33 -06003331}
3332
3333// jump_statement
3334// : CONTINUE SEMICOLON
3335// | BREAK SEMICOLON
3336// | DISCARD SEMICOLON
3337// | RETURN SEMICOLON
3338// | RETURN expression SEMICOLON
3339//
3340bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3341{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003342 EHlslTokenClass jump = peek();
3343 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003344 case EHTokContinue:
3345 case EHTokBreak:
3346 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003347 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003348 advanceToken();
3349 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003350 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003351 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003352 return false;
3353 }
John Kessenich21472ae2016-06-04 11:46:33 -06003354
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003355 switch (jump) {
3356 case EHTokContinue:
3357 statement = intermediate.addBranch(EOpContinue, token.loc);
3358 break;
3359 case EHTokBreak:
3360 statement = intermediate.addBranch(EOpBreak, token.loc);
3361 break;
3362 case EHTokDiscard:
3363 statement = intermediate.addBranch(EOpKill, token.loc);
3364 break;
3365
3366 case EHTokReturn:
3367 {
3368 // expression
3369 TIntermTyped* node;
3370 if (acceptExpression(node)) {
3371 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003372 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003373 } else
3374 statement = intermediate.addBranch(EOpReturn, token.loc);
3375 break;
3376 }
3377
3378 default:
3379 assert(0);
3380 return false;
3381 }
3382
3383 // SEMICOLON
3384 if (! acceptTokenClass(EHTokSemicolon))
3385 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003386
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003387 return true;
3388}
John Kessenich21472ae2016-06-04 11:46:33 -06003389
John Kessenichd02dc5d2016-07-01 00:04:11 -06003390// case_label
3391// : CASE expression COLON
3392//
John Kessenich21472ae2016-06-04 11:46:33 -06003393bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3394{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003395 TSourceLoc loc = token.loc;
3396 if (! acceptTokenClass(EHTokCase))
3397 return false;
3398
3399 TIntermTyped* expression;
3400 if (! acceptExpression(expression)) {
3401 expected("case expression");
3402 return false;
3403 }
3404
3405 if (! acceptTokenClass(EHTokColon)) {
3406 expected(":");
3407 return false;
3408 }
3409
3410 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3411
3412 return true;
3413}
3414
3415// default_label
3416// : DEFAULT COLON
3417//
3418bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3419{
3420 TSourceLoc loc = token.loc;
3421 if (! acceptTokenClass(EHTokDefault))
3422 return false;
3423
3424 if (! acceptTokenClass(EHTokColon)) {
3425 expected(":");
3426 return false;
3427 }
3428
3429 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3430
3431 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003432}
3433
John Kessenich19b92ff2016-06-19 11:50:34 -06003434// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003435// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3436// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003437//
3438void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3439{
3440 arraySizes = nullptr;
3441
steve-lunarg7b211a32016-10-13 12:26:18 -06003442 // Early-out if there aren't any array dimensions
3443 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003444 return;
3445
steve-lunarg7b211a32016-10-13 12:26:18 -06003446 // 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 -06003447 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003448
3449 // Collect each array dimension.
3450 while (acceptTokenClass(EHTokLeftBracket)) {
3451 TSourceLoc loc = token.loc;
3452 TIntermTyped* sizeExpr = nullptr;
3453
John Kessenich057df292017-03-06 18:18:37 -07003454 // Array sizing expression is optional. If omitted, array will be later sized by initializer list.
steve-lunarg7b211a32016-10-13 12:26:18 -06003455 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3456
3457 if (! acceptTokenClass(EHTokRightBracket)) {
3458 expected("]");
3459 return;
3460 }
3461
3462 if (hasArraySize) {
3463 TArraySize arraySize;
3464 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3465 arraySizes->addInnerSize(arraySize);
3466 } else {
3467 arraySizes->addInnerSize(0); // sized by initializers.
3468 }
steve-lunarg265c0612016-09-27 10:57:35 -06003469 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003470}
3471
John Kessenich630dd7d2016-06-12 23:52:12 -06003472// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003473// : COLON semantic // optional
3474// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3475// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003476// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003477// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003478//
John Kessenich854fe242017-03-02 14:30:59 -07003479// Return true if any tokens were accepted. That is,
3480// false can be returned on successfully recognizing nothing,
3481// not necessarily meaning bad syntax.
3482//
3483bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003484{
John Kessenich854fe242017-03-02 14:30:59 -07003485 bool found = false;
3486
John Kessenich630dd7d2016-06-12 23:52:12 -06003487 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003488 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003489 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003490 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003491 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003492 if (peekTokenClass(EHTokLayout))
3493 acceptLayoutQualifierList(qualifier);
3494 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003495 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003496 if (! acceptTokenClass(EHTokLeftParen)) {
3497 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003498 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003499 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003500 HlslToken locationToken;
3501 if (! acceptIdentifier(locationToken)) {
3502 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003503 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003504 }
3505 HlslToken componentToken;
3506 if (acceptTokenClass(EHTokDot)) {
3507 if (! acceptIdentifier(componentToken)) {
3508 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003509 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003510 }
3511 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003512 if (! acceptTokenClass(EHTokRightParen)) {
3513 expected(")");
3514 break;
3515 }
John Kessenich7735b942016-09-05 12:40:06 -06003516 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003517 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003518 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003519 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003520 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003521 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3522 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003523 if (! acceptTokenClass(EHTokLeftParen)) {
3524 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003525 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003526 }
John Kessenichb38f0712016-07-30 10:29:54 -06003527 HlslToken registerDesc; // for Type#
3528 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003529 if (! acceptIdentifier(registerDesc)) {
3530 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003531 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003532 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003533 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3534 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003535 // Then we didn't really see the registerDesc yet, it was
3536 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003537 profile = registerDesc;
3538 if (! acceptIdentifier(registerDesc)) {
3539 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003540 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003541 }
3542 }
John Kessenichb38f0712016-07-30 10:29:54 -06003543 int subComponent = 0;
3544 if (acceptTokenClass(EHTokLeftBracket)) {
3545 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3546 if (! peekTokenClass(EHTokIntConstant)) {
3547 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003548 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003549 }
3550 subComponent = token.i;
3551 advanceToken();
3552 if (! acceptTokenClass(EHTokRightBracket)) {
3553 expected("]");
3554 break;
3555 }
3556 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003557 // (COMMA SPACEN)opt
3558 HlslToken spaceDesc;
3559 if (acceptTokenClass(EHTokComma)) {
3560 if (! acceptIdentifier(spaceDesc)) {
3561 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003562 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003563 }
3564 }
3565 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003566 if (! acceptTokenClass(EHTokRightParen)) {
3567 expected(")");
3568 break;
3569 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003570 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003571 } else {
3572 // semantic, in idToken.string
John Kessenich2dd643f2017-03-14 21:50:06 -06003573 TString semanticUpperCase = *idToken.string;
3574 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
3575 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
John Kessenich630dd7d2016-06-12 23:52:12 -06003576 }
John Kessenich854fe242017-03-02 14:30:59 -07003577 } else if (peekTokenClass(EHTokLeftAngle)) {
3578 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06003579 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07003580 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06003581 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003582
John Kessenich630dd7d2016-06-12 23:52:12 -06003583 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07003584
3585 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06003586}
3587
John Kessenichb16f7e62017-03-11 19:32:47 -07003588//
3589// Get the stream of tokens from the scanner, but skip all syntactic/semantic
3590// processing.
3591//
3592bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
3593{
3594 if (! peekTokenClass(EHTokLeftBrace))
3595 return false;
3596
3597 int braceCount = 0;
3598
3599 do {
3600 switch (peek()) {
3601 case EHTokLeftBrace:
3602 ++braceCount;
3603 break;
3604 case EHTokRightBrace:
3605 --braceCount;
3606 break;
3607 case EHTokNone:
3608 // End of input before balance { } is bad...
3609 return false;
3610 default:
3611 break;
3612 }
3613
3614 tokens.push_back(token);
3615 advanceToken();
3616 } while (braceCount > 0);
3617
3618 return true;
3619}
3620
John Kesseniche01a9bc2016-03-12 20:11:22 -07003621} // end namespace glslang