blob: ea2ae5559a0bd388e5805a5cafd74b3fa4160875 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
John Kessenich927608b2017-01-06 12:34:14 -07002// Copyright (C) 2016 Google, Inc.
3// Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
John Kessenich927608b2017-01-06 12:34:14 -07005// All rights reserved.
John Kesseniche01a9bc2016-03-12 20:11:22 -07006//
John Kessenich927608b2017-01-06 12:34:14 -07007// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
John Kesseniche01a9bc2016-03-12 20:11:22 -070010//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
John Kessenich927608b2017-01-06 12:34:14 -070023// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34// POSSIBILITY OF SUCH DAMAGE.
John Kesseniche01a9bc2016-03-12 20:11:22 -070035//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenichaecd4972016-03-14 10:46:34 -060078// Only process the next token if it is an identifier.
79// Return true if it was an identifier.
80bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
81{
82 if (peekTokenClass(EHTokIdentifier)) {
83 idToken = token;
84 advanceToken();
85 return true;
86 }
87
steve-lunarg5ca85ad2016-12-26 18:45:52 -070088 // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
89 // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a
90 // valid identifier, nor is "linear". This code special cases the known instances of this, so
91 // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed.
John Kessenichecba76f2017-01-06 00:34:48 -070092
steve-lunarg5ca85ad2016-12-26 18:45:52 -070093 TString* idString = nullptr;
94 switch (peek()) {
95 case EHTokSample: idString = NewPoolTString("sample"); break;
96 case EHTokHalf: idString = NewPoolTString("half"); break;
97 case EHTokBool: idString = NewPoolTString("bool"); break;
98 case EHTokFloat: idString = NewPoolTString("float"); break;
99 case EHTokDouble: idString = NewPoolTString("double"); break;
100 case EHTokInt: idString = NewPoolTString("int"); break;
101 case EHTokUint: idString = NewPoolTString("uint"); break;
102 case EHTokMin16float: idString = NewPoolTString("min16float"); break;
103 case EHTokMin10float: idString = NewPoolTString("min10float"); break;
104 case EHTokMin16int: idString = NewPoolTString("min16int"); break;
105 case EHTokMin12int: idString = NewPoolTString("min12int"); break;
106 default:
107 return false;
steve-lunarg75fd2232016-11-16 13:22:11 -0700108 }
109
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700110 token.string = idString;
111 token.tokenClass = EHTokIdentifier;
112 token.symbol = nullptr;
113 idToken = token;
114
115 advanceToken();
116
117 return true;
John Kessenichaecd4972016-03-14 10:46:34 -0600118}
119
John Kesseniche01a9bc2016-03-12 20:11:22 -0700120// compilationUnit
121// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600122// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700123//
124bool HlslGrammar::acceptCompilationUnit()
125{
John Kessenichd016be12016-03-13 11:24:20 -0600126 TIntermNode* unitNode = nullptr;
127
John Kessenich9c86c6a2016-05-03 22:49:24 -0600128 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600129 // HLSL allows semicolons between global declarations, e.g, between functions.
130 if (acceptTokenClass(EHTokSemicolon))
131 continue;
132
John Kessenichd016be12016-03-13 11:24:20 -0600133 // externalDeclaration
John Kessenich02467d82017-01-19 15:41:47 -0700134 TIntermNode* declarationNode1;
135 TIntermNode* declarationNode2 = nullptr; // sometimes the grammar for a single declaration creates two
136 if (! acceptDeclaration(declarationNode1, declarationNode2))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700137 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600138
139 // hook it up
John Kessenich02467d82017-01-19 15:41:47 -0700140 unitNode = intermediate.growAggregate(unitNode, declarationNode1);
141 if (declarationNode2 != nullptr)
142 unitNode = intermediate.growAggregate(unitNode, declarationNode2);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700143 }
144
John Kessenichd016be12016-03-13 11:24:20 -0600145 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600146 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600147
John Kesseniche01a9bc2016-03-12 20:11:22 -0700148 return true;
149}
150
LoopDawg4886f692016-06-29 10:58:58 -0600151// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700152// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600153//
154// sampler_state_assignment
155// : sampler_state_identifier EQUAL value SEMICOLON
156//
157// sampler_state_identifier
158// : ADDRESSU
159// | ADDRESSV
160// | ADDRESSW
161// | BORDERCOLOR
162// | FILTER
163// | MAXANISOTROPY
164// | MAXLOD
165// | MINLOD
166// | MIPLODBIAS
167//
168bool HlslGrammar::acceptSamplerState()
169{
170 // TODO: this should be genericized to accept a list of valid tokens and
171 // return token/value pairs. Presently it is specific to texture values.
172
173 if (! acceptTokenClass(EHTokLeftBrace))
174 return true;
175
176 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700177
LoopDawg4886f692016-06-29 10:58:58 -0600178 do {
179 // read state name
180 HlslToken state;
181 if (! acceptIdentifier(state))
182 break; // end of list
183
184 // FXC accepts any case
185 TString stateName = *state.string;
186 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
187
188 if (! acceptTokenClass(EHTokAssign)) {
189 expected("assign");
190 return false;
191 }
192
193 if (stateName == "minlod" || stateName == "maxlod") {
194 if (! peekTokenClass(EHTokIntConstant)) {
195 expected("integer");
196 return false;
197 }
198
199 TIntermTyped* lod = nullptr;
200 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
201 return false;
202 } else if (stateName == "maxanisotropy") {
203 if (! peekTokenClass(EHTokIntConstant)) {
204 expected("integer");
205 return false;
206 }
207
208 TIntermTyped* maxAnisotropy = nullptr;
209 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
210 return false;
211 } else if (stateName == "filter") {
212 HlslToken filterMode;
213 if (! acceptIdentifier(filterMode)) {
214 expected("filter mode");
215 return false;
216 }
217 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
218 HlslToken addrMode;
219 if (! acceptIdentifier(addrMode)) {
220 expected("texture address mode");
221 return false;
222 }
223 } else if (stateName == "miplodbias") {
224 TIntermTyped* lodBias = nullptr;
225 if (! acceptLiteral(lodBias)) {
226 expected("lod bias");
227 return false;
228 }
229 } else if (stateName == "bordercolor") {
230 return false;
231 } else {
232 expected("texture state");
233 return false;
234 }
235
236 // SEMICOLON
237 if (! acceptTokenClass(EHTokSemicolon)) {
238 expected("semicolon");
239 return false;
240 }
241 } while (true);
242
243 if (! acceptTokenClass(EHTokRightBrace))
244 return false;
245
246 return true;
247}
248
249// sampler_declaration_dx9
250// : SAMPLER identifier EQUAL sampler_type sampler_state
251//
John Kesseniche4821e42016-07-16 10:19:43 -0600252bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600253{
254 if (! acceptTokenClass(EHTokSampler))
255 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700256
LoopDawg4886f692016-06-29 10:58:58 -0600257 // TODO: remove this when DX9 style declarations are implemented.
258 unimplemented("Direct3D 9 sampler declaration");
259
260 // read sampler name
261 HlslToken name;
262 if (! acceptIdentifier(name)) {
263 expected("sampler name");
264 return false;
265 }
266
267 if (! acceptTokenClass(EHTokAssign)) {
268 expected("=");
269 return false;
270 }
271
272 return false;
273}
274
John Kesseniche01a9bc2016-03-12 20:11:22 -0700275// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600276// : sampler_declaration_dx9 post_decls SEMICOLON
277// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600278// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600279// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600280// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700281//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600282// declarator_list
283// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600284//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600285// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600286// : identifier array_specifier post_decls
287// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600288// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600289//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600290// Parsing has to go pretty far in to know whether it's a variable, prototype, or
291// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600292// as above. (The 'identifier' in the first item in init_declarator list is the
293// same as 'identifier' for function declarations.)
294//
295// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600296// or a function body.
297//
John Kessenich02467d82017-01-19 15:41:47 -0700298// 'node2' could get populated with a second decoration tree if a single source declaration
299// leads to two subtrees that need to be peers higher up.
300//
John Kessenichd016be12016-03-13 11:24:20 -0600301bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700302{
John Kessenich02467d82017-01-19 15:41:47 -0700303 TIntermNode* node2;
304 return acceptDeclaration(node, node2);
305}
306bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
307{
John Kessenichd016be12016-03-13 11:24:20 -0600308 node = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -0700309 node2 = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600310 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600311
steve-lunarg1868b142016-10-20 13:07:10 -0600312 // attributes
313 TAttributeMap attributes;
314 acceptAttributes(attributes);
315
John Kessenich5e69ec62016-07-05 00:02:40 -0600316 // typedef
317 bool typedefDecl = acceptTokenClass(EHTokTypedef);
318
John Kesseniche82061d2016-09-27 14:38:57 -0600319 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600320
321 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600322 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
323 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
324 // HLSL shaders, this will have to be a master level switch
325 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700326 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400327
John Kesseniche82061d2016-09-27 14:38:57 -0600328 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400329 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600330
331 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600332 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700333 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600334
John Kessenich87142c72016-03-12 20:24:24 -0700335 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600336 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600337 while (acceptIdentifier(idToken)) {
steve-lunargf1e0c872016-10-31 15:13:43 -0600338 TString* fnName = idToken.string;
339
340 // Potentially rename shader entry point function. No-op most of the time.
341 parseContext.renameShaderFunction(fnName);
342
John Kessenich5f934b02016-03-13 17:58:25 -0600343 // function_parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600344 TFunction& function = *new TFunction(fnName, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600345 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600346 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600347 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600348
John Kessenichd5ed0b62016-07-04 17:32:45 -0600349 // compound_statement (function body definition) or just a prototype?
350 if (peekTokenClass(EHTokLeftBrace)) {
351 if (list)
352 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600353 if (typedefDecl)
354 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich02467d82017-01-19 15:41:47 -0700355 return acceptFunctionDefinition(function, node, node2, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600356 } else {
357 if (typedefDecl)
358 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600359 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600360 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600361 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600362 // A variable declaration. Fix the storage qualifier if it's a global.
363 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
364 declaredType.getQualifier().storage = EvqUniform;
365
John Kessenichecba76f2017-01-06 00:34:48 -0700366 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600367 // the number of types can expand when arrayness is different.
368 TType variableType;
369 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600370
John Kesseniche82061d2016-09-27 14:38:57 -0600371 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600372 TArraySizes* arraySizes = nullptr;
373 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600374
John Kesseniche82061d2016-09-27 14:38:57 -0600375 // Fix arrayness in the variableType
376 if (declaredType.isImplicitlySizedArray()) {
377 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
378 // of different sizes, for this case sharing the shallow copy of arrayness
379 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
380 variableType.newArraySizes(declaredType.getArraySizes());
381 }
382 if (arraySizes || variableType.isArray()) {
383 // In the most general case, arrayness is potentially coming both from the
384 // declared type and from the variable: "int[] a[];" or just one or the other.
385 // Merge it all to the variableType, so all arrayness is part of the variableType.
386 parseContext.arrayDimMerge(variableType, arraySizes);
387 }
388
LoopDawg4886f692016-06-29 10:58:58 -0600389 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600390 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600391 if (! acceptSamplerState())
392 return false;
393 }
394
John Kessenichd5ed0b62016-07-04 17:32:45 -0600395 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600396 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600397
398 // EQUAL assignment_expression
399 TIntermTyped* expressionNode = nullptr;
400 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600401 if (typedefDecl)
402 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600403 if (! acceptAssignmentExpression(expressionNode)) {
404 expected("initializer");
405 return false;
406 }
407 }
408
John Kessenich6dbc0a72016-09-27 19:13:05 -0600409 // Hand off the actual declaration
410
411 // TODO: things scoped within an annotation need their own name space;
412 // TODO: strings are not yet handled.
413 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
414 if (typedefDecl)
415 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
416 else if (variableType.getBasicType() == EbtBlock)
417 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
418 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700419 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600420 // this isn't really an individual variable, but a member of the $Global buffer
421 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
422 } else {
423 // Declare the variable and add any initializer code to the AST.
424 // The top-level node is always made into an aggregate, as that's
425 // historically how the AST has been.
426 node = intermediate.growAggregate(node,
427 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
428 expressionNode),
429 idToken.loc);
430 }
431 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600432 }
John Kessenich5f934b02016-03-13 17:58:25 -0600433 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600434
435 if (acceptTokenClass(EHTokComma)) {
436 list = true;
437 continue;
438 }
439 };
440
441 // The top-level node is a sequence.
442 if (node != nullptr)
443 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700444
John Kessenich078d7f22016-03-14 10:02:11 -0600445 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600446 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700447 // This may have been a false detection of what appeared to be a declaration, but
448 // was actually an assignment such as "float = 4", where "float" is an identifier.
449 // We put the token back to let further parsing happen for cases where that may
450 // happen. This errors on the side of caution, and mostly triggers the error.
451
452 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
453 recedeToken();
454 else
455 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600456 return false;
457 }
John Kessenichecba76f2017-01-06 00:34:48 -0700458
John Kesseniche01a9bc2016-03-12 20:11:22 -0700459 return true;
460}
461
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600462// control_declaration
463// : fully_specified_type identifier EQUAL expression
464//
465bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
466{
467 node = nullptr;
468
469 // fully_specified_type
470 TType type;
471 if (! acceptFullySpecifiedType(type))
472 return false;
473
474 // identifier
475 HlslToken idToken;
476 if (! acceptIdentifier(idToken)) {
477 expected("identifier");
478 return false;
479 }
480
481 // EQUAL
482 TIntermTyped* expressionNode = nullptr;
483 if (! acceptTokenClass(EHTokAssign)) {
484 expected("=");
485 return false;
486 }
487
488 // expression
489 if (! acceptExpression(expressionNode)) {
490 expected("initializer");
491 return false;
492 }
493
John Kesseniche82061d2016-09-27 14:38:57 -0600494 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600495
496 return true;
497}
498
John Kessenich87142c72016-03-12 20:24:24 -0700499// fully_specified_type
500// : type_specifier
501// | type_qualifier type_specifier
502//
503bool HlslGrammar::acceptFullySpecifiedType(TType& type)
504{
505 // type_qualifier
506 TQualifier qualifier;
507 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600508 if (! acceptQualifier(qualifier))
509 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600510 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700511
512 // type_specifier
steve-lunarga64ed3e2016-12-18 17:51:14 -0700513 if (! acceptType(type)) {
514 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700515 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700516 // qualifier. Back it out, if we did.
517 if (qualifier.sample)
518 recedeToken();
519
John Kessenich87142c72016-03-12 20:24:24 -0700520 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700521 }
John Kessenich3d157c52016-07-25 16:05:33 -0600522 if (type.getBasicType() == EbtBlock) {
523 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600524 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600525 // further, it can create an anonymous instance of the block
526 if (peekTokenClass(EHTokSemicolon))
527 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600528 } else {
529 // Some qualifiers are set when parsing the type. Merge those with
530 // whatever comes from acceptQualifier.
531 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700532
steve-lunargbb0183f2016-10-04 16:58:14 -0600533 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600534 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700535
536 if (type.getQualifier().storage == EvqVaryingOut)
537 qualifier.storage = type.getQualifier().storage;
538
539 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600540 }
John Kessenich87142c72016-03-12 20:24:24 -0700541
542 return true;
543}
544
John Kessenich630dd7d2016-06-12 23:52:12 -0600545// type_qualifier
546// : qualifier qualifier ...
547//
548// Zero or more of these, so this can't return false.
549//
John Kessenichb9e39122016-08-17 10:22:08 -0600550bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700551{
John Kessenich630dd7d2016-06-12 23:52:12 -0600552 do {
553 switch (peek()) {
554 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600555 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600556 break;
557 case EHTokExtern:
558 // TODO: no meaning in glslang?
559 break;
560 case EHTokShared:
561 // TODO: hint
562 break;
563 case EHTokGroupShared:
564 qualifier.storage = EvqShared;
565 break;
566 case EHTokUniform:
567 qualifier.storage = EvqUniform;
568 break;
569 case EHTokConst:
570 qualifier.storage = EvqConst;
571 break;
572 case EHTokVolatile:
573 qualifier.volatil = true;
574 break;
575 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600576 qualifier.smooth = true;
577 break;
578 case EHTokCentroid:
579 qualifier.centroid = true;
580 break;
581 case EHTokNointerpolation:
582 qualifier.flat = true;
583 break;
584 case EHTokNoperspective:
585 qualifier.nopersp = true;
586 break;
587 case EHTokSample:
588 qualifier.sample = true;
589 break;
590 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600591 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600592 break;
593 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600594 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600595 break;
596 case EHTokPrecise:
597 qualifier.noContraction = true;
598 break;
LoopDawg9249c702016-07-12 20:44:32 -0600599 case EHTokIn:
600 qualifier.storage = EvqIn;
601 break;
602 case EHTokOut:
603 qualifier.storage = EvqOut;
604 break;
605 case EHTokInOut:
606 qualifier.storage = EvqInOut;
607 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600608 case EHTokLayout:
609 if (! acceptLayoutQualifierList(qualifier))
610 return false;
611 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700612
613 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
614 // for output variables.
615 case EHTokPoint:
616 qualifier.storage = EvqIn;
617 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
618 return false;
619 break;
620 case EHTokLine:
621 qualifier.storage = EvqIn;
622 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
623 return false;
624 break;
625 case EHTokTriangle:
626 qualifier.storage = EvqIn;
627 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
628 return false;
629 break;
630 case EHTokLineAdj:
631 qualifier.storage = EvqIn;
632 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
633 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700634 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700635 case EHTokTriangleAdj:
636 qualifier.storage = EvqIn;
637 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
638 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700639 break;
640
John Kessenich630dd7d2016-06-12 23:52:12 -0600641 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600642 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600643 }
644 advanceToken();
645 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700646}
647
John Kessenichb9e39122016-08-17 10:22:08 -0600648// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600649// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600650//
651// layout_qualifier
652// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600653// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600654//
655// Zero or more of these, so this can't return false.
656//
657bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
658{
659 if (! acceptTokenClass(EHTokLayout))
660 return false;
661
662 // LEFT_PAREN
663 if (! acceptTokenClass(EHTokLeftParen))
664 return false;
665
666 do {
667 // identifier
668 HlslToken idToken;
669 if (! acceptIdentifier(idToken))
670 break;
671
672 // EQUAL expression
673 if (acceptTokenClass(EHTokAssign)) {
674 TIntermTyped* expr;
675 if (! acceptConditionalExpression(expr)) {
676 expected("expression");
677 return false;
678 }
679 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
680 } else
681 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
682
683 // COMMA
684 if (! acceptTokenClass(EHTokComma))
685 break;
686 } while (true);
687
688 // RIGHT_PAREN
689 if (! acceptTokenClass(EHTokRightParen)) {
690 expected(")");
691 return false;
692 }
693
694 return true;
695}
696
LoopDawg6daaa4f2016-06-23 19:13:48 -0600697// template_type
698// : FLOAT
699// | DOUBLE
700// | INT
701// | DWORD
702// | UINT
703// | BOOL
704//
steve-lunargf49cdf42016-11-17 15:04:20 -0700705bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600706{
707 switch (peek()) {
708 case EHTokFloat:
709 basicType = EbtFloat;
710 break;
711 case EHTokDouble:
712 basicType = EbtDouble;
713 break;
714 case EHTokInt:
715 case EHTokDword:
716 basicType = EbtInt;
717 break;
718 case EHTokUint:
719 basicType = EbtUint;
720 break;
721 case EHTokBool:
722 basicType = EbtBool;
723 break;
724 default:
725 return false;
726 }
727
728 advanceToken();
729
730 return true;
731}
732
733// vector_template_type
734// : VECTOR
735// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
736//
737bool HlslGrammar::acceptVectorTemplateType(TType& type)
738{
739 if (! acceptTokenClass(EHTokVector))
740 return false;
741
742 if (! acceptTokenClass(EHTokLeftAngle)) {
743 // in HLSL, 'vector' alone means float4.
744 new(&type) TType(EbtFloat, EvqTemporary, 4);
745 return true;
746 }
747
748 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700749 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600750 expected("scalar type");
751 return false;
752 }
753
754 // COMMA
755 if (! acceptTokenClass(EHTokComma)) {
756 expected(",");
757 return false;
758 }
759
760 // integer
761 if (! peekTokenClass(EHTokIntConstant)) {
762 expected("literal integer");
763 return false;
764 }
765
766 TIntermTyped* vecSize;
767 if (! acceptLiteral(vecSize))
768 return false;
769
770 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
771
772 new(&type) TType(basicType, EvqTemporary, vecSizeI);
773
774 if (vecSizeI == 1)
775 type.makeVector();
776
777 if (!acceptTokenClass(EHTokRightAngle)) {
778 expected("right angle bracket");
779 return false;
780 }
781
782 return true;
783}
784
785// matrix_template_type
786// : MATRIX
787// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
788//
789bool HlslGrammar::acceptMatrixTemplateType(TType& type)
790{
791 if (! acceptTokenClass(EHTokMatrix))
792 return false;
793
794 if (! acceptTokenClass(EHTokLeftAngle)) {
795 // in HLSL, 'matrix' alone means float4x4.
796 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
797 return true;
798 }
799
800 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700801 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600802 expected("scalar type");
803 return false;
804 }
805
806 // COMMA
807 if (! acceptTokenClass(EHTokComma)) {
808 expected(",");
809 return false;
810 }
811
812 // integer rows
813 if (! peekTokenClass(EHTokIntConstant)) {
814 expected("literal integer");
815 return false;
816 }
817
818 TIntermTyped* rows;
819 if (! acceptLiteral(rows))
820 return false;
821
822 // COMMA
823 if (! acceptTokenClass(EHTokComma)) {
824 expected(",");
825 return false;
826 }
John Kessenichecba76f2017-01-06 00:34:48 -0700827
LoopDawg6daaa4f2016-06-23 19:13:48 -0600828 // integer cols
829 if (! peekTokenClass(EHTokIntConstant)) {
830 expected("literal integer");
831 return false;
832 }
833
834 TIntermTyped* cols;
835 if (! acceptLiteral(cols))
836 return false;
837
838 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600839 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
840 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600841
842 if (!acceptTokenClass(EHTokRightAngle)) {
843 expected("right angle bracket");
844 return false;
845 }
846
847 return true;
848}
849
steve-lunargf49cdf42016-11-17 15:04:20 -0700850// layout_geometry
851// : LINESTREAM
852// | POINTSTREAM
853// | TRIANGLESTREAM
854//
855bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
856{
857 // read geometry type
858 const EHlslTokenClass geometryType = peek();
859
860 switch (geometryType) {
861 case EHTokPointStream: geometry = ElgPoints; break;
862 case EHTokLineStream: geometry = ElgLineStrip; break;
863 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
864 default:
865 return false; // not a layout geometry
866 }
867
868 advanceToken(); // consume the layout keyword
869 return true;
870}
871
steve-lunarg858c9282017-01-07 08:54:10 -0700872// tessellation_decl_type
873// : INPUTPATCH
874// | OUTPUTPATCH
875//
876bool HlslGrammar::acceptTessellationDeclType()
877{
878 // read geometry type
879 const EHlslTokenClass tessType = peek();
880
881 switch (tessType) {
882 case EHTokInputPatch: break;
883 case EHTokOutputPatch: break;
884 default:
885 return false; // not a tessellation decl
886 }
887
888 advanceToken(); // consume the keyword
889 return true;
890}
891
892// tessellation_patch_template_type
893// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
894//
895bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
896{
897 if (! acceptTessellationDeclType())
898 return false;
899
900 if (! acceptTokenClass(EHTokLeftAngle))
901 return false;
902
903 if (! acceptType(type)) {
904 expected("tessellation patch type");
905 return false;
906 }
907
908 if (! acceptTokenClass(EHTokComma))
909 return false;
910
911 // integer size
912 if (! peekTokenClass(EHTokIntConstant)) {
913 expected("literal integer");
914 return false;
915 }
916
917 TIntermTyped* size;
918 if (! acceptLiteral(size))
919 return false;
920
921 TArraySizes* arraySizes = new TArraySizes;
922 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
923 type.newArraySizes(*arraySizes);
924
925 if (! acceptTokenClass(EHTokRightAngle)) {
926 expected("right angle bracket");
927 return false;
928 }
929
930 return true;
931}
932
steve-lunargf49cdf42016-11-17 15:04:20 -0700933// stream_out_template_type
934// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
935//
936bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
937{
938 geometry = ElgNone;
939
940 if (! acceptOutputPrimitiveGeometry(geometry))
941 return false;
942
943 if (! acceptTokenClass(EHTokLeftAngle))
944 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700945
steve-lunargf49cdf42016-11-17 15:04:20 -0700946 if (! acceptType(type)) {
947 expected("stream output type");
948 return false;
949 }
950
951 type.getQualifier().storage = EvqVaryingOut;
952
953 if (! acceptTokenClass(EHTokRightAngle)) {
954 expected("right angle bracket");
955 return false;
956 }
957
958 return true;
959}
John Kessenichecba76f2017-01-06 00:34:48 -0700960
John Kessenicha1e2d492016-09-20 13:22:58 -0600961// annotations
962// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600963//
John Kessenicha1e2d492016-09-20 13:22:58 -0600964bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600965{
John Kessenicha1e2d492016-09-20 13:22:58 -0600966 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600967 return false;
968
John Kessenicha1e2d492016-09-20 13:22:58 -0600969 // note that we are nesting a name space
970 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600971
972 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
973 do {
974 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
975 while (acceptTokenClass(EHTokSemicolon))
976 ;
977
978 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600979 break;
John Kessenich86f71382016-09-19 20:23:18 -0600980
981 // declaration
982 TIntermNode* node;
983 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600984 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600985 return false;
986 }
987 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600988
989 parseContext.unnestAnnotations();
990 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600991}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600992
LoopDawg4886f692016-06-29 10:58:58 -0600993// sampler_type
994// : SAMPLER
995// | SAMPLER1D
996// | SAMPLER2D
997// | SAMPLER3D
998// | SAMPLERCUBE
999// | SAMPLERSTATE
1000// | SAMPLERCOMPARISONSTATE
1001bool HlslGrammar::acceptSamplerType(TType& type)
1002{
1003 // read sampler type
1004 const EHlslTokenClass samplerType = peek();
1005
LoopDawga78b0292016-07-19 14:28:05 -06001006 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001007 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001008
LoopDawga78b0292016-07-19 14:28:05 -06001009 bool isShadow = false;
1010
LoopDawg4886f692016-06-29 10:58:58 -06001011 switch (samplerType) {
1012 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001013 case EHTokSampler1d: /*dim = Esd1D*/; break;
1014 case EHTokSampler2d: /*dim = Esd2D*/; break;
1015 case EHTokSampler3d: /*dim = Esd3D*/; break;
1016 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001017 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001018 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001019 default:
1020 return false; // not a sampler declaration
1021 }
1022
1023 advanceToken(); // consume the sampler type keyword
1024
1025 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001026
1027 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001028 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001029
1030 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1031
1032 return true;
1033}
1034
1035// texture_type
1036// | BUFFER
1037// | TEXTURE1D
1038// | TEXTURE1DARRAY
1039// | TEXTURE2D
1040// | TEXTURE2DARRAY
1041// | TEXTURE3D
1042// | TEXTURECUBE
1043// | TEXTURECUBEARRAY
1044// | TEXTURE2DMS
1045// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001046// | RWBUFFER
1047// | RWTEXTURE1D
1048// | RWTEXTURE1DARRAY
1049// | RWTEXTURE2D
1050// | RWTEXTURE2DARRAY
1051// | RWTEXTURE3D
1052
LoopDawg4886f692016-06-29 10:58:58 -06001053bool HlslGrammar::acceptTextureType(TType& type)
1054{
1055 const EHlslTokenClass textureType = peek();
1056
1057 TSamplerDim dim = EsdNone;
1058 bool array = false;
1059 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001060 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -06001061
1062 switch (textureType) {
1063 case EHTokBuffer: dim = EsdBuffer; break;
1064 case EHTokTexture1d: dim = Esd1D; break;
1065 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1066 case EHTokTexture2d: dim = Esd2D; break;
1067 case EHTokTexture2darray: dim = Esd2D; array = true; break;
John Kessenichecba76f2017-01-06 00:34:48 -07001068 case EHTokTexture3d: dim = Esd3D; break;
LoopDawg4886f692016-06-29 10:58:58 -06001069 case EHTokTextureCube: dim = EsdCube; break;
1070 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1071 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1072 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -06001073 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1074 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1075 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1076 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1077 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1078 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001079 default:
1080 return false; // not a texture declaration
1081 }
1082
1083 advanceToken(); // consume the texture object keyword
1084
1085 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001086
LoopDawg4886f692016-06-29 10:58:58 -06001087 TIntermTyped* msCount = nullptr;
1088
steve-lunargbb0183f2016-10-04 16:58:14 -06001089 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001090 if (acceptTokenClass(EHTokLeftAngle)) {
1091 if (! acceptType(txType)) {
1092 expected("scalar or vector type");
1093 return false;
1094 }
1095
1096 const TBasicType basicRetType = txType.getBasicType() ;
1097
1098 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1099 unimplemented("basic type in texture");
1100 return false;
1101 }
1102
steve-lunargd53f7172016-07-27 15:46:48 -06001103 // Buffers can handle small mats if they fit in 4 components
1104 if (dim == EsdBuffer && txType.isMatrix()) {
1105 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1106 expected("components < 4 in matrix buffer type");
1107 return false;
1108 }
1109
1110 // TODO: except we don't handle it yet...
1111 unimplemented("matrix type in buffer");
1112 return false;
1113 }
1114
LoopDawg4886f692016-06-29 10:58:58 -06001115 if (!txType.isScalar() && !txType.isVector()) {
1116 expected("scalar or vector type");
1117 return false;
1118 }
1119
LoopDawg4886f692016-06-29 10:58:58 -06001120 if (ms && acceptTokenClass(EHTokComma)) {
1121 // read sample count for multisample types, if given
1122 if (! peekTokenClass(EHTokIntConstant)) {
1123 expected("multisample count");
1124 return false;
1125 }
1126
1127 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1128 return false;
1129 }
1130
1131 if (! acceptTokenClass(EHTokRightAngle)) {
1132 expected("right angle bracket");
1133 return false;
1134 }
1135 } else if (ms) {
1136 expected("texture type for multisample");
1137 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001138 } else if (image) {
1139 expected("type for RWTexture/RWBuffer");
1140 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001141 }
1142
1143 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001144 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001145
1146 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001147 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001148
steve-lunarg4f2da272016-10-10 15:24:57 -06001149 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1150 if (image || dim == EsdBuffer)
1151 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001152
1153 // Non-image Buffers are combined
1154 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001155 sampler.set(txType.getBasicType(), dim, array);
1156 } else {
1157 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001158 if (image) {
1159 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1160 } else {
1161 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1162 }
steve-lunargd53f7172016-07-27 15:46:48 -06001163 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001164
1165 // Remember the declared vector size.
1166 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001167
LoopDawg4886f692016-06-29 10:58:58 -06001168 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001169 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001170
1171 return true;
1172}
1173
John Kessenich87142c72016-03-12 20:24:24 -07001174// If token is for a type, update 'type' with the type information,
1175// and return true and advance.
1176// Otherwise, return false, and don't advance
1177bool HlslGrammar::acceptType(TType& type)
1178{
steve-lunarg3226b082016-10-26 19:18:55 -06001179 // Basic types for min* types, broken out here in case of future
1180 // changes, e.g, to use native halfs.
1181 static const TBasicType min16float_bt = EbtFloat;
1182 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001183 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001184 static const TBasicType min16int_bt = EbtInt;
1185 static const TBasicType min12int_bt = EbtInt;
1186 static const TBasicType min16uint_bt = EbtUint;
1187
John Kessenich9c86c6a2016-05-03 22:49:24 -06001188 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001189 case EHTokVector:
1190 return acceptVectorTemplateType(type);
1191 break;
1192
1193 case EHTokMatrix:
1194 return acceptMatrixTemplateType(type);
1195 break;
1196
steve-lunargf49cdf42016-11-17 15:04:20 -07001197 case EHTokPointStream: // fall through
1198 case EHTokLineStream: // ...
1199 case EHTokTriangleStream: // ...
1200 {
1201 TLayoutGeometry geometry;
1202 if (! acceptStreamOutTemplateType(type, geometry))
1203 return false;
1204
1205 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1206 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001207
steve-lunargf49cdf42016-11-17 15:04:20 -07001208 return true;
1209 }
1210
steve-lunarg858c9282017-01-07 08:54:10 -07001211 case EHTokInputPatch: // fall through
1212 case EHTokOutputPatch: // ...
1213 {
1214 if (! acceptTessellationPatchTemplateType(type))
1215 return false;
1216
1217 return true;
1218 }
1219
LoopDawg4886f692016-06-29 10:58:58 -06001220 case EHTokSampler: // fall through
1221 case EHTokSampler1d: // ...
1222 case EHTokSampler2d: // ...
1223 case EHTokSampler3d: // ...
1224 case EHTokSamplerCube: // ...
1225 case EHTokSamplerState: // ...
1226 case EHTokSamplerComparisonState: // ...
1227 return acceptSamplerType(type);
1228 break;
1229
1230 case EHTokBuffer: // fall through
1231 case EHTokTexture1d: // ...
1232 case EHTokTexture1darray: // ...
1233 case EHTokTexture2d: // ...
1234 case EHTokTexture2darray: // ...
1235 case EHTokTexture3d: // ...
1236 case EHTokTextureCube: // ...
1237 case EHTokTextureCubearray: // ...
1238 case EHTokTexture2DMS: // ...
1239 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001240 case EHTokRWTexture1d: // ...
1241 case EHTokRWTexture1darray: // ...
1242 case EHTokRWTexture2d: // ...
1243 case EHTokRWTexture2darray: // ...
1244 case EHTokRWTexture3d: // ...
1245 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001246 return acceptTextureType(type);
1247 break;
1248
John Kesseniche6e74942016-06-11 16:43:14 -06001249 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001250 case EHTokCBuffer:
1251 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001252 return acceptStruct(type);
1253 break;
1254
1255 case EHTokIdentifier:
1256 // An identifier could be for a user-defined type.
1257 // Note we cache the symbol table lookup, to save for a later rule
1258 // when this is not a type.
1259 token.symbol = parseContext.symbolTable.find(*token.string);
1260 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1261 type.shallowCopy(token.symbol->getType());
1262 advanceToken();
1263 return true;
1264 } else
1265 return false;
1266
John Kessenich71351de2016-06-08 12:50:56 -06001267 case EHTokVoid:
1268 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001269 break;
John Kessenich71351de2016-06-08 12:50:56 -06001270
John Kessenicha1e2d492016-09-20 13:22:58 -06001271 case EHTokString:
1272 new(&type) TType(EbtString);
1273 break;
1274
John Kessenich87142c72016-03-12 20:24:24 -07001275 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001276 new(&type) TType(EbtFloat);
1277 break;
John Kessenich87142c72016-03-12 20:24:24 -07001278 case EHTokFloat1:
1279 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001280 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001281 break;
John Kessenich87142c72016-03-12 20:24:24 -07001282 case EHTokFloat2:
1283 new(&type) TType(EbtFloat, EvqTemporary, 2);
1284 break;
1285 case EHTokFloat3:
1286 new(&type) TType(EbtFloat, EvqTemporary, 3);
1287 break;
1288 case EHTokFloat4:
1289 new(&type) TType(EbtFloat, EvqTemporary, 4);
1290 break;
1291
John Kessenich71351de2016-06-08 12:50:56 -06001292 case EHTokDouble:
1293 new(&type) TType(EbtDouble);
1294 break;
1295 case EHTokDouble1:
1296 new(&type) TType(EbtDouble);
1297 type.makeVector();
1298 break;
1299 case EHTokDouble2:
1300 new(&type) TType(EbtDouble, EvqTemporary, 2);
1301 break;
1302 case EHTokDouble3:
1303 new(&type) TType(EbtDouble, EvqTemporary, 3);
1304 break;
1305 case EHTokDouble4:
1306 new(&type) TType(EbtDouble, EvqTemporary, 4);
1307 break;
1308
1309 case EHTokInt:
1310 case EHTokDword:
1311 new(&type) TType(EbtInt);
1312 break;
1313 case EHTokInt1:
1314 new(&type) TType(EbtInt);
1315 type.makeVector();
1316 break;
John Kessenich87142c72016-03-12 20:24:24 -07001317 case EHTokInt2:
1318 new(&type) TType(EbtInt, EvqTemporary, 2);
1319 break;
1320 case EHTokInt3:
1321 new(&type) TType(EbtInt, EvqTemporary, 3);
1322 break;
1323 case EHTokInt4:
1324 new(&type) TType(EbtInt, EvqTemporary, 4);
1325 break;
1326
John Kessenich71351de2016-06-08 12:50:56 -06001327 case EHTokUint:
1328 new(&type) TType(EbtUint);
1329 break;
1330 case EHTokUint1:
1331 new(&type) TType(EbtUint);
1332 type.makeVector();
1333 break;
1334 case EHTokUint2:
1335 new(&type) TType(EbtUint, EvqTemporary, 2);
1336 break;
1337 case EHTokUint3:
1338 new(&type) TType(EbtUint, EvqTemporary, 3);
1339 break;
1340 case EHTokUint4:
1341 new(&type) TType(EbtUint, EvqTemporary, 4);
1342 break;
1343
1344 case EHTokBool:
1345 new(&type) TType(EbtBool);
1346 break;
1347 case EHTokBool1:
1348 new(&type) TType(EbtBool);
1349 type.makeVector();
1350 break;
John Kessenich87142c72016-03-12 20:24:24 -07001351 case EHTokBool2:
1352 new(&type) TType(EbtBool, EvqTemporary, 2);
1353 break;
1354 case EHTokBool3:
1355 new(&type) TType(EbtBool, EvqTemporary, 3);
1356 break;
1357 case EHTokBool4:
1358 new(&type) TType(EbtBool, EvqTemporary, 4);
1359 break;
1360
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001361 case EHTokHalf:
1362 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1363 break;
1364 case EHTokHalf1:
1365 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1366 type.makeVector();
1367 break;
1368 case EHTokHalf2:
1369 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1370 break;
1371 case EHTokHalf3:
1372 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1373 break;
1374 case EHTokHalf4:
1375 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1376 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001377
steve-lunarg3226b082016-10-26 19:18:55 -06001378 case EHTokMin16float:
1379 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1380 break;
1381 case EHTokMin16float1:
1382 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1383 type.makeVector();
1384 break;
1385 case EHTokMin16float2:
1386 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1387 break;
1388 case EHTokMin16float3:
1389 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1390 break;
1391 case EHTokMin16float4:
1392 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1393 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001394
steve-lunarg3226b082016-10-26 19:18:55 -06001395 case EHTokMin10float:
1396 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1397 break;
1398 case EHTokMin10float1:
1399 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1400 type.makeVector();
1401 break;
1402 case EHTokMin10float2:
1403 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1404 break;
1405 case EHTokMin10float3:
1406 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1407 break;
1408 case EHTokMin10float4:
1409 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1410 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001411
steve-lunarg3226b082016-10-26 19:18:55 -06001412 case EHTokMin16int:
1413 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1414 break;
1415 case EHTokMin16int1:
1416 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1417 type.makeVector();
1418 break;
1419 case EHTokMin16int2:
1420 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1421 break;
1422 case EHTokMin16int3:
1423 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1424 break;
1425 case EHTokMin16int4:
1426 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1427 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001428
steve-lunarg3226b082016-10-26 19:18:55 -06001429 case EHTokMin12int:
1430 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1431 break;
1432 case EHTokMin12int1:
1433 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1434 type.makeVector();
1435 break;
1436 case EHTokMin12int2:
1437 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1438 break;
1439 case EHTokMin12int3:
1440 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1441 break;
1442 case EHTokMin12int4:
1443 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1444 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001445
steve-lunarg3226b082016-10-26 19:18:55 -06001446 case EHTokMin16uint:
1447 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1448 break;
1449 case EHTokMin16uint1:
1450 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1451 type.makeVector();
1452 break;
1453 case EHTokMin16uint2:
1454 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1455 break;
1456 case EHTokMin16uint3:
1457 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1458 break;
1459 case EHTokMin16uint4:
1460 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1461 break;
1462
John Kessenich0133c122016-05-20 12:17:26 -06001463 case EHTokInt1x1:
1464 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1465 break;
1466 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001467 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001468 break;
1469 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001470 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001471 break;
1472 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001473 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001474 break;
1475 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001476 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001477 break;
1478 case EHTokInt2x2:
1479 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1480 break;
1481 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001482 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001483 break;
1484 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001485 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001486 break;
1487 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001488 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001489 break;
1490 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001491 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001492 break;
1493 case EHTokInt3x3:
1494 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1495 break;
1496 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001497 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001498 break;
1499 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001500 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001501 break;
1502 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001503 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001504 break;
1505 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001506 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001507 break;
1508 case EHTokInt4x4:
1509 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1510 break;
1511
John Kessenich71351de2016-06-08 12:50:56 -06001512 case EHTokUint1x1:
1513 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1514 break;
1515 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001516 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001517 break;
1518 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001519 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001520 break;
1521 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001522 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001523 break;
1524 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001525 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001526 break;
1527 case EHTokUint2x2:
1528 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1529 break;
1530 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001531 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001532 break;
1533 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001534 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001535 break;
1536 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001537 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001538 break;
1539 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001540 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001541 break;
1542 case EHTokUint3x3:
1543 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1544 break;
1545 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001546 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001547 break;
1548 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001549 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001550 break;
1551 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001552 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001553 break;
1554 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001555 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001556 break;
1557 case EHTokUint4x4:
1558 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1559 break;
1560
1561 case EHTokBool1x1:
1562 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1563 break;
1564 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001565 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001566 break;
1567 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001568 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001569 break;
1570 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001571 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001572 break;
1573 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001574 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001575 break;
1576 case EHTokBool2x2:
1577 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1578 break;
1579 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001580 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001581 break;
1582 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001583 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001584 break;
1585 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001586 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001587 break;
1588 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001589 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001590 break;
1591 case EHTokBool3x3:
1592 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1593 break;
1594 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001595 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001596 break;
1597 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001598 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001599 break;
1600 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001601 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001602 break;
1603 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001604 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001605 break;
1606 case EHTokBool4x4:
1607 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1608 break;
1609
John Kessenich0133c122016-05-20 12:17:26 -06001610 case EHTokFloat1x1:
1611 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1612 break;
1613 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001614 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001615 break;
1616 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001617 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001618 break;
1619 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001620 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001621 break;
1622 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001623 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001624 break;
John Kessenich87142c72016-03-12 20:24:24 -07001625 case EHTokFloat2x2:
1626 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1627 break;
1628 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001629 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001630 break;
1631 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001632 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001633 break;
John Kessenich0133c122016-05-20 12:17:26 -06001634 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001635 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001636 break;
John Kessenich87142c72016-03-12 20:24:24 -07001637 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001638 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001639 break;
1640 case EHTokFloat3x3:
1641 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1642 break;
1643 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001644 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001645 break;
John Kessenich0133c122016-05-20 12:17:26 -06001646 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001647 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001648 break;
John Kessenich87142c72016-03-12 20:24:24 -07001649 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001650 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001651 break;
1652 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001653 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001654 break;
1655 case EHTokFloat4x4:
1656 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1657 break;
1658
John Kessenich0133c122016-05-20 12:17:26 -06001659 case EHTokDouble1x1:
1660 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1661 break;
1662 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001663 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001664 break;
1665 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001666 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001667 break;
1668 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001669 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001670 break;
1671 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001672 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001673 break;
1674 case EHTokDouble2x2:
1675 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1676 break;
1677 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001678 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001679 break;
1680 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001681 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001682 break;
1683 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001684 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001685 break;
1686 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001687 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001688 break;
1689 case EHTokDouble3x3:
1690 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1691 break;
1692 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001693 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001694 break;
1695 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001696 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001697 break;
1698 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001699 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001700 break;
1701 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001702 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001703 break;
1704 case EHTokDouble4x4:
1705 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1706 break;
1707
John Kessenich87142c72016-03-12 20:24:24 -07001708 default:
1709 return false;
1710 }
1711
1712 advanceToken();
1713
1714 return true;
1715}
1716
John Kesseniche6e74942016-06-11 16:43:14 -06001717// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001718// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1719// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1720//
1721// struct_type
1722// : STRUCT
1723// | CBUFFER
1724// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001725//
1726bool HlslGrammar::acceptStruct(TType& type)
1727{
John Kessenichb804de62016-09-05 12:19:18 -06001728 // This storage qualifier will tell us whether it's an AST
1729 // block type or just a generic structure type.
1730 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001731
1732 // CBUFFER
1733 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001734 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001735 // TBUFFER
1736 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001737 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001738 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001739 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001740 return false;
1741
1742 // IDENTIFIER
1743 TString structName = "";
1744 if (peekTokenClass(EHTokIdentifier)) {
1745 structName = *token.string;
1746 advanceToken();
1747 }
1748
John Kessenich3d157c52016-07-25 16:05:33 -06001749 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001750 TQualifier postDeclQualifier;
1751 postDeclQualifier.clear();
1752 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001753
John Kesseniche6e74942016-06-11 16:43:14 -06001754 // LEFT_BRACE
1755 if (! acceptTokenClass(EHTokLeftBrace)) {
1756 expected("{");
1757 return false;
1758 }
1759
1760 // struct_declaration_list
1761 TTypeList* typeList;
1762 if (! acceptStructDeclarationList(typeList)) {
1763 expected("struct member declarations");
1764 return false;
1765 }
1766
1767 // RIGHT_BRACE
1768 if (! acceptTokenClass(EHTokRightBrace)) {
1769 expected("}");
1770 return false;
1771 }
1772
1773 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001774 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001775 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001776 else {
John Kessenich7735b942016-09-05 12:40:06 -06001777 postDeclQualifier.storage = storageQualifier;
1778 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001779 }
John Kesseniche6e74942016-06-11 16:43:14 -06001780
John Kessenich727b3742017-02-03 17:57:55 -07001781 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001782
1783 return true;
1784}
1785
1786// struct_declaration_list
1787// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1788//
1789// struct_declaration
1790// : fully_specified_type struct_declarator COMMA struct_declarator ...
1791//
1792// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001793// : IDENTIFIER post_decls
1794// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001795//
1796bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1797{
1798 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001799 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001800
1801 do {
1802 // success on seeing the RIGHT_BRACE coming up
1803 if (peekTokenClass(EHTokRightBrace))
1804 return true;
1805
1806 // struct_declaration
1807
1808 // fully_specified_type
1809 TType memberType;
1810 if (! acceptFullySpecifiedType(memberType)) {
1811 expected("member type");
1812 return false;
1813 }
1814
1815 // struct_declarator COMMA struct_declarator ...
1816 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001817 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001818 expected("member name");
1819 return false;
1820 }
1821
1822 // add it to the list of members
1823 TTypeLoc member = { new TType(EbtVoid), token.loc };
1824 member.type->shallowCopy(memberType);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001825 member.type->setFieldName(*idToken.string);
John Kesseniche6e74942016-06-11 16:43:14 -06001826 typeList->push_back(member);
1827
John Kesseniche6e74942016-06-11 16:43:14 -06001828 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001829 TArraySizes* arraySizes = nullptr;
1830 acceptArraySpecifier(arraySizes);
1831 if (arraySizes)
1832 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001833
John Kessenich7735b942016-09-05 12:40:06 -06001834 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001835
John Kessenich18adbdb2017-02-02 15:16:20 -07001836 // EQUAL assignment_expression
1837 if (acceptTokenClass(EHTokAssign)) {
1838 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
1839 TIntermTyped* expressionNode = nullptr;
1840 if (! acceptAssignmentExpression(expressionNode)) {
1841 expected("initializer");
1842 return false;
1843 }
1844 }
1845
John Kesseniche6e74942016-06-11 16:43:14 -06001846 // success on seeing the SEMICOLON coming up
1847 if (peekTokenClass(EHTokSemicolon))
1848 break;
1849
1850 // COMMA
1851 if (! acceptTokenClass(EHTokComma)) {
1852 expected(",");
1853 return false;
1854 }
1855
1856 } while (true);
1857
1858 // SEMI_COLON
1859 if (! acceptTokenClass(EHTokSemicolon)) {
1860 expected(";");
1861 return false;
1862 }
1863
1864 } while (true);
1865}
1866
John Kessenich5f934b02016-03-13 17:58:25 -06001867// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001868// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001869// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001870//
1871bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1872{
John Kessenich078d7f22016-03-14 10:02:11 -06001873 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001874 if (! acceptTokenClass(EHTokLeftParen))
1875 return false;
1876
John Kessenich71351de2016-06-08 12:50:56 -06001877 // VOID RIGHT_PAREN
1878 if (! acceptTokenClass(EHTokVoid)) {
1879 do {
1880 // parameter_declaration
1881 if (! acceptParameterDeclaration(function))
1882 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001883
John Kessenich71351de2016-06-08 12:50:56 -06001884 // COMMA
1885 if (! acceptTokenClass(EHTokComma))
1886 break;
1887 } while (true);
1888 }
John Kessenich5f934b02016-03-13 17:58:25 -06001889
John Kessenich078d7f22016-03-14 10:02:11 -06001890 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001891 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001892 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001893 return false;
1894 }
1895
1896 return true;
1897}
1898
steve-lunarg26d31452016-12-23 18:56:57 -07001899// default_parameter_declaration
1900// : EQUAL conditional_expression
1901// : EQUAL initializer
1902bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
1903{
1904 node = nullptr;
1905
1906 // Valid not to have a default_parameter_declaration
1907 if (!acceptTokenClass(EHTokAssign))
1908 return true;
1909
1910 if (!acceptConditionalExpression(node)) {
1911 if (!acceptInitializer(node))
1912 return false;
1913
1914 // For initializer lists, we have to const-fold into a constructor for the type, so build
1915 // that.
1916 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
1917 if (constructor == nullptr) // cannot construct
1918 return false;
1919
1920 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07001921 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07001922 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07001923
steve-lunarg26d31452016-12-23 18:56:57 -07001924 node = parseContext.handleFunctionCall(token.loc, constructor, node);
1925 }
1926
1927 // If this is simply a constant, we can use it directly.
1928 if (node->getAsConstantUnion())
1929 return true;
1930
1931 // Otherwise, it has to be const-foldable.
1932 TIntermTyped* origNode = node;
1933
1934 node = intermediate.fold(node->getAsAggregate());
1935
1936 if (node != nullptr && origNode != node)
1937 return true;
1938
1939 parseContext.error(token.loc, "invalid default parameter value", "", "");
1940
1941 return false;
1942}
1943
John Kessenich5f934b02016-03-13 17:58:25 -06001944// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07001945// : fully_specified_type post_decls [ = default_parameter_declaration ]
1946// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06001947//
1948bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1949{
1950 // fully_specified_type
1951 TType* type = new TType;
1952 if (! acceptFullySpecifiedType(*type))
1953 return false;
1954
1955 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001956 HlslToken idToken;
1957 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001958
John Kessenich19b92ff2016-06-19 11:50:34 -06001959 // array_specifier
1960 TArraySizes* arraySizes = nullptr;
1961 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001962 if (arraySizes) {
1963 if (arraySizes->isImplicit()) {
1964 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1965 return false;
1966 }
1967
John Kessenich19b92ff2016-06-19 11:50:34 -06001968 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001969 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001970
1971 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001972 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001973
steve-lunarg26d31452016-12-23 18:56:57 -07001974 TIntermTyped* defaultValue;
1975 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
1976 return false;
1977
John Kessenich5aa59e22016-06-17 15:50:47 -06001978 parseContext.paramFix(*type);
1979
steve-lunarg26d31452016-12-23 18:56:57 -07001980 // If any prior parameters have default values, all the parameters after that must as well.
1981 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
1982 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
1983 return false;
1984 }
1985
1986 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06001987 function.addParameter(param);
1988
1989 return true;
1990}
1991
1992// Do the work to create the function definition in addition to
1993// parsing the body (compound_statement).
John Kessenich02467d82017-01-19 15:41:47 -07001994bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, TIntermNode*& node2, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001995{
John Kessenicha3051662016-09-02 19:13:36 -06001996 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001997 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001998
John Kessenich077e0522016-06-09 02:02:17 -06001999 // This does a pushScope()
John Kessenich02467d82017-01-19 15:41:47 -07002000 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
John Kessenich5f934b02016-03-13 17:58:25 -06002001
2002 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002003 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002004 if (! acceptCompoundStatement(functionBody))
2005 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002006
John Kessenich02467d82017-01-19 15:41:47 -07002007 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
2008
2009 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002010}
2011
John Kessenich0d2b6de2016-06-05 11:23:11 -06002012// Accept an expression with parenthesis around it, where
2013// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002014// syntactically required ones like in "if ( expression )".
2015//
2016// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002017//
2018// Note this one is not set up to be speculative; as it gives
2019// errors if not found.
2020//
2021bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2022{
2023 // LEFT_PAREN
2024 if (! acceptTokenClass(EHTokLeftParen))
2025 expected("(");
2026
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002027 bool decl = false;
2028 TIntermNode* declNode = nullptr;
2029 decl = acceptControlDeclaration(declNode);
2030 if (decl) {
2031 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2032 expected("initialized declaration");
2033 return false;
2034 } else
2035 expression = declNode->getAsTyped();
2036 } else {
2037 // no declaration
2038 if (! acceptExpression(expression)) {
2039 expected("expression");
2040 return false;
2041 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002042 }
2043
2044 // RIGHT_PAREN
2045 if (! acceptTokenClass(EHTokRightParen))
2046 expected(")");
2047
2048 return true;
2049}
2050
John Kessenich34fb0362016-05-03 23:17:20 -06002051// The top-level full expression recognizer.
2052//
John Kessenich87142c72016-03-12 20:24:24 -07002053// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002054// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002055//
2056bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2057{
LoopDawgef764a22016-06-03 09:17:51 -06002058 node = nullptr;
2059
John Kessenich34fb0362016-05-03 23:17:20 -06002060 // assignment_expression
2061 if (! acceptAssignmentExpression(node))
2062 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002063
John Kessenich34fb0362016-05-03 23:17:20 -06002064 if (! peekTokenClass(EHTokComma))
2065 return true;
2066
2067 do {
2068 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002069 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002070 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002071
John Kessenich34fb0362016-05-03 23:17:20 -06002072 // ... assignment_expression
2073 TIntermTyped* rightNode = nullptr;
2074 if (! acceptAssignmentExpression(rightNode)) {
2075 expected("assignment expression");
2076 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002077 }
2078
John Kessenich34fb0362016-05-03 23:17:20 -06002079 node = intermediate.addComma(node, rightNode, loc);
2080
2081 if (! peekTokenClass(EHTokComma))
2082 return true;
2083 } while (true);
2084}
2085
John Kessenich07354242016-07-01 19:58:06 -06002086// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002087// : LEFT_BRACE RIGHT_BRACE
2088// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002089//
2090// initializer_list
2091// : assignment_expression COMMA assignment_expression COMMA ...
2092//
2093bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2094{
2095 // LEFT_BRACE
2096 if (! acceptTokenClass(EHTokLeftBrace))
2097 return false;
2098
John Kessenich98ad4852016-11-27 17:39:07 -07002099 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002100 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002101 if (acceptTokenClass(EHTokRightBrace)) {
2102 // a zero-length initializer list
2103 node = intermediate.makeAggregate(loc);
2104 return true;
2105 }
2106
2107 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002108 node = nullptr;
2109 do {
2110 // assignment_expression
2111 TIntermTyped* expr;
2112 if (! acceptAssignmentExpression(expr)) {
2113 expected("assignment expression in initializer list");
2114 return false;
2115 }
2116 node = intermediate.growAggregate(node, expr, loc);
2117
2118 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002119 if (acceptTokenClass(EHTokComma)) {
2120 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2121 return true;
John Kessenich07354242016-07-01 19:58:06 -06002122 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002123 }
John Kessenich07354242016-07-01 19:58:06 -06002124
2125 // RIGHT_BRACE
2126 if (acceptTokenClass(EHTokRightBrace))
2127 return true;
2128
2129 expected(", or }");
2130 return false;
2131 } while (true);
2132}
2133
John Kessenich34fb0362016-05-03 23:17:20 -06002134// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002135// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002136//
2137// a op (b op (c op d))
2138//
2139// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002140// : initializer
2141// | conditional_expression
2142// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002143//
2144bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2145{
John Kessenich07354242016-07-01 19:58:06 -06002146 // initializer
2147 if (peekTokenClass(EHTokLeftBrace)) {
2148 if (acceptInitializer(node))
2149 return true;
2150
2151 expected("initializer");
2152 return false;
2153 }
2154
John Kessenich00957f82016-07-27 10:39:57 -06002155 // conditional_expression
2156 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002157 return false;
2158
John Kessenich07354242016-07-01 19:58:06 -06002159 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002160 TOperator assignOp = HlslOpMap::assignment(peek());
2161 if (assignOp == EOpNull)
2162 return true;
2163
John Kessenich00957f82016-07-27 10:39:57 -06002164 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002165 TSourceLoc loc = token.loc;
2166 advanceToken();
2167
John Kessenich00957f82016-07-27 10:39:57 -06002168 // conditional_expression assign_op conditional_expression ...
2169 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002170 // gets the right-to-left associativity.
2171 TIntermTyped* rightNode = nullptr;
2172 if (! acceptAssignmentExpression(rightNode)) {
2173 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002174 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002175 }
2176
John Kessenichd21baed2016-09-16 03:05:12 -06002177 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002178 node = parseContext.handleLvalue(loc, "assign", node);
2179
John Kessenichfea226b2016-07-28 17:53:56 -06002180 if (node == nullptr) {
2181 parseContext.error(loc, "could not create assignment", "", "");
2182 return false;
2183 }
John Kessenich34fb0362016-05-03 23:17:20 -06002184
2185 if (! peekTokenClass(EHTokComma))
2186 return true;
2187
2188 return true;
2189}
2190
John Kessenich00957f82016-07-27 10:39:57 -06002191// Accept a conditional expression, which associates right-to-left,
2192// accomplished by the "true" expression calling down to lower
2193// precedence levels than this level.
2194//
2195// conditional_expression
2196// : binary_expression
2197// | binary_expression QUESTION expression COLON assignment_expression
2198//
2199bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2200{
2201 // binary_expression
2202 if (! acceptBinaryExpression(node, PlLogicalOr))
2203 return false;
2204
2205 if (! acceptTokenClass(EHTokQuestion))
2206 return true;
2207
2208 TIntermTyped* trueNode = nullptr;
2209 if (! acceptExpression(trueNode)) {
2210 expected("expression after ?");
2211 return false;
2212 }
2213 TSourceLoc loc = token.loc;
2214
2215 if (! acceptTokenClass(EHTokColon)) {
2216 expected(":");
2217 return false;
2218 }
2219
2220 TIntermTyped* falseNode = nullptr;
2221 if (! acceptAssignmentExpression(falseNode)) {
2222 expected("expression after :");
2223 return false;
2224 }
2225
2226 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2227
2228 return true;
2229}
2230
John Kessenich34fb0362016-05-03 23:17:20 -06002231// Accept a binary expression, for binary operations that
2232// associate left-to-right. This is, it is implicit, for example
2233//
2234// ((a op b) op c) op d
2235//
2236// binary_expression
2237// : expression op expression op expression ...
2238//
2239// where 'expression' is the next higher level in precedence.
2240//
2241bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2242{
2243 if (precedenceLevel > PlMul)
2244 return acceptUnaryExpression(node);
2245
2246 // assignment_expression
2247 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2248 return false;
2249
John Kessenich34fb0362016-05-03 23:17:20 -06002250 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002251 TOperator op = HlslOpMap::binary(peek());
2252 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2253 if (tokenLevel < precedenceLevel)
2254 return true;
2255
John Kessenich34fb0362016-05-03 23:17:20 -06002256 // ... op
2257 TSourceLoc loc = token.loc;
2258 advanceToken();
2259
2260 // ... expression
2261 TIntermTyped* rightNode = nullptr;
2262 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2263 expected("expression");
2264 return false;
2265 }
2266
2267 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002268 if (node == nullptr) {
2269 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2270 return false;
2271 }
John Kessenich34fb0362016-05-03 23:17:20 -06002272 } while (true);
2273}
2274
2275// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002276// : (type) unary_expression
2277// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002278// | - unary_expression
2279// | ! unary_expression
2280// | ~ unary_expression
2281// | ++ unary_expression
2282// | -- unary_expression
2283// | postfix_expression
2284//
2285bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2286{
John Kessenich1cc1a282016-06-03 16:55:49 -06002287 // (type) unary_expression
2288 // Have to look two steps ahead, because this could be, e.g., a
2289 // postfix_expression instead, since that also starts with at "(".
2290 if (acceptTokenClass(EHTokLeftParen)) {
2291 TType castType;
2292 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002293 if (acceptTokenClass(EHTokRightParen)) {
2294 // We've matched "(type)" now, get the expression to cast
2295 TSourceLoc loc = token.loc;
2296 if (! acceptUnaryExpression(node))
2297 return false;
2298
2299 // Hook it up like a constructor
2300 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2301 if (constructorFunction == nullptr) {
2302 expected("type that can be constructed");
2303 return false;
2304 }
2305 TIntermTyped* arguments = nullptr;
2306 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2307 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2308
2309 return true;
2310 } else {
2311 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2312 // the '(int' part. We must back up twice.
2313 recedeToken();
2314 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002315 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002316 } else {
2317 // This isn't a type cast, but it still started "(", so if it is a
2318 // unary expression, it can only be a postfix_expression, so try that.
2319 // Back it up first.
2320 recedeToken();
2321 return acceptPostfixExpression(node);
2322 }
2323 }
2324
2325 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002326 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002327
John Kessenich1cc1a282016-06-03 16:55:49 -06002328 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002329 if (unaryOp == EOpNull)
2330 return acceptPostfixExpression(node);
2331
2332 // op unary_expression
2333 TSourceLoc loc = token.loc;
2334 advanceToken();
2335 if (! acceptUnaryExpression(node))
2336 return false;
2337
2338 // + is a no-op
2339 if (unaryOp == EOpAdd)
2340 return true;
2341
2342 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002343
2344 // These unary ops require lvalues
2345 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2346 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002347
2348 return node != nullptr;
2349}
2350
2351// postfix_expression
2352// : LEFT_PAREN expression RIGHT_PAREN
2353// | literal
2354// | constructor
2355// | identifier
2356// | function_call
2357// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2358// | postfix_expression DOT IDENTIFIER
2359// | postfix_expression INC_OP
2360// | postfix_expression DEC_OP
2361//
2362bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2363{
2364 // Not implemented as self-recursive:
2365 // The logical "right recursion" is done with an loop at the end
2366
2367 // idToken will pick up either a variable or a function name in a function call
2368 HlslToken idToken;
2369
John Kessenich21472ae2016-06-04 11:46:33 -06002370 // Find something before the postfix operations, as they can't operate
2371 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002372 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002373 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002374 if (! acceptExpression(node)) {
2375 expected("expression");
2376 return false;
2377 }
2378 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002379 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002380 return false;
2381 }
John Kessenich34fb0362016-05-03 23:17:20 -06002382 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002383 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002384 } else if (acceptConstructor(node)) {
2385 // constructor (nothing else to do yet)
2386 } else if (acceptIdentifier(idToken)) {
2387 // identifier or function_call name
2388 if (! peekTokenClass(EHTokLeftParen)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -07002389 node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002390 } else if (acceptFunctionCall(idToken, node)) {
2391 // function_call (nothing else to do yet)
2392 } else {
2393 expected("function call arguments");
2394 return false;
2395 }
John Kessenich21472ae2016-06-04 11:46:33 -06002396 } else {
2397 // nothing found, can't post operate
2398 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002399 }
2400
steve-lunarga2b01a02016-11-28 17:09:54 -07002401 // This is to guarantee we do this no matter how we get out of the stack frame.
2402 // This way there's no bug if an early return forgets to do it.
2403 struct tFinalize {
2404 tFinalize(HlslParseContext& p) : parseContext(p) { }
2405 ~tFinalize() { parseContext.finalizeFlattening(); }
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002406 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002407 private:
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002408 const tFinalize& operator=(const tFinalize& f);
2409 tFinalize(const tFinalize& f);
steve-lunarga2b01a02016-11-28 17:09:54 -07002410 } finalize(parseContext);
2411
2412 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2413 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2414 // level: hence the init and finalize. Even though in practice these must be
2415 // constants, they are parsed no matter what.
2416 parseContext.initFlattening();
2417
John Kessenich21472ae2016-06-04 11:46:33 -06002418 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002419 do {
2420 TSourceLoc loc = token.loc;
2421 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002422
John Kessenich34fb0362016-05-03 23:17:20 -06002423 // Consume only a valid post-unary operator, otherwise we are done.
2424 switch (postOp) {
2425 case EOpIndexDirectStruct:
2426 case EOpIndexIndirect:
2427 case EOpPostIncrement:
2428 case EOpPostDecrement:
2429 advanceToken();
2430 break;
2431 default:
2432 return true;
2433 }
John Kessenich87142c72016-03-12 20:24:24 -07002434
John Kessenich34fb0362016-05-03 23:17:20 -06002435 // We have a valid post-unary operator, process it.
2436 switch (postOp) {
2437 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002438 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002439 // DOT IDENTIFIER
2440 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002441 HlslToken field;
2442 if (! acceptIdentifier(field)) {
2443 expected("swizzle or member");
2444 return false;
2445 }
LoopDawg4886f692016-06-29 10:58:58 -06002446
2447 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002448 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002449
2450 // In the event of a method node, we look for an open paren and accept the function call.
steve-lunarga2b01a02016-11-28 17:09:54 -07002451 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002452 if (! acceptFunctionCall(field, node, base)) {
2453 expected("function parameters");
2454 return false;
2455 }
2456 }
2457
John Kessenich34fb0362016-05-03 23:17:20 -06002458 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002459 }
John Kessenich34fb0362016-05-03 23:17:20 -06002460 case EOpIndexIndirect:
2461 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002462 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002463 TIntermTyped* indexNode = nullptr;
2464 if (! acceptExpression(indexNode) ||
2465 ! peekTokenClass(EHTokRightBracket)) {
2466 expected("expression followed by ']'");
2467 return false;
2468 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002469 advanceToken();
2470 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2471 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002472 }
2473 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002474 // INC_OP
2475 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002476 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002477 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002478 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002479 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002480 break;
2481 default:
2482 assert(0);
2483 break;
2484 }
2485 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002486}
2487
John Kessenichd016be12016-03-13 11:24:20 -06002488// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002489// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002490//
2491bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2492{
2493 // type
2494 TType type;
2495 if (acceptType(type)) {
2496 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2497 if (constructorFunction == nullptr)
2498 return false;
2499
2500 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002501 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002502 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002503 // It's possible this is a type keyword used as an identifier. Put the token back
2504 // for later use.
2505 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002506 return false;
2507 }
2508
2509 // hook it up
2510 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2511
2512 return true;
2513 }
2514
2515 return false;
2516}
2517
John Kessenich34fb0362016-05-03 23:17:20 -06002518// The function_call identifier was already recognized, and passed in as idToken.
2519//
2520// function_call
2521// : [idToken] arguments
2522//
LoopDawg4886f692016-06-29 10:58:58 -06002523bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002524{
John Kessenich4678ca92016-05-13 09:33:42 -06002525 // arguments
2526 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2527 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002528
2529 // methods have an implicit first argument of the calling object.
2530 if (base != nullptr)
2531 parseContext.handleFunctionArgument(function, arguments, base);
2532
John Kessenich4678ca92016-05-13 09:33:42 -06002533 if (! acceptArguments(function, arguments))
2534 return false;
2535
2536 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2537
2538 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002539}
2540
John Kessenich87142c72016-03-12 20:24:24 -07002541// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002542// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002543//
John Kessenichd016be12016-03-13 11:24:20 -06002544// The arguments are pushed onto the 'function' argument list and
2545// onto the 'arguments' aggregate.
2546//
John Kessenich4678ca92016-05-13 09:33:42 -06002547bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002548{
John Kessenich078d7f22016-03-14 10:02:11 -06002549 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002550 if (! acceptTokenClass(EHTokLeftParen))
2551 return false;
2552
2553 do {
John Kessenichd016be12016-03-13 11:24:20 -06002554 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002555 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002556 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002557 break;
John Kessenichd016be12016-03-13 11:24:20 -06002558
2559 // hook it up
2560 parseContext.handleFunctionArgument(function, arguments, arg);
2561
John Kessenich078d7f22016-03-14 10:02:11 -06002562 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002563 if (! acceptTokenClass(EHTokComma))
2564 break;
2565 } while (true);
2566
John Kessenich078d7f22016-03-14 10:02:11 -06002567 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002568 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002569 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002570 return false;
2571 }
2572
2573 return true;
2574}
2575
2576bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2577{
2578 switch (token.tokenClass) {
2579 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002580 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002581 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002582 case EHTokUintConstant:
2583 node = intermediate.addConstantUnion(token.u, token.loc, true);
2584 break;
John Kessenich87142c72016-03-12 20:24:24 -07002585 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002586 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002587 break;
2588 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002589 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002590 break;
2591 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002592 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002593 break;
John Kessenich86f71382016-09-19 20:23:18 -06002594 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07002595 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06002596 break;
John Kessenich87142c72016-03-12 20:24:24 -07002597
2598 default:
2599 return false;
2600 }
2601
2602 advanceToken();
2603
2604 return true;
2605}
2606
John Kessenich5f934b02016-03-13 17:58:25 -06002607// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002608// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002609//
John Kessenich21472ae2016-06-04 11:46:33 -06002610bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002611{
John Kessenich21472ae2016-06-04 11:46:33 -06002612 TIntermAggregate* compoundStatement = nullptr;
2613
John Kessenich34fb0362016-05-03 23:17:20 -06002614 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002615 if (! acceptTokenClass(EHTokLeftBrace))
2616 return false;
2617
2618 // statement statement ...
2619 TIntermNode* statement = nullptr;
2620 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002621 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2622 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2623 branch->getFlowOp() == EOpDefault)) {
2624 // hook up individual subsequences within a switch statement
2625 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2626 compoundStatement = nullptr;
2627 } else {
2628 // hook it up to the growing compound statement
2629 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2630 }
John Kessenich5f934b02016-03-13 17:58:25 -06002631 }
John Kessenich34fb0362016-05-03 23:17:20 -06002632 if (compoundStatement)
2633 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002634
John Kessenich21472ae2016-06-04 11:46:33 -06002635 retStatement = compoundStatement;
2636
John Kessenich34fb0362016-05-03 23:17:20 -06002637 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002638 return acceptTokenClass(EHTokRightBrace);
2639}
2640
John Kessenich0d2b6de2016-06-05 11:23:11 -06002641bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2642{
2643 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002644 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002645 parseContext.popScope();
2646
2647 return result;
2648}
2649
John Kessenich077e0522016-06-09 02:02:17 -06002650bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002651{
John Kessenich077e0522016-06-09 02:02:17 -06002652 parseContext.pushScope();
2653 bool result = acceptCompoundStatement(statement);
2654 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002655
2656 return result;
2657}
2658
John Kessenich5f934b02016-03-13 17:58:25 -06002659// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002660// : attributes attributed_statement
2661//
2662// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002663// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002664// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002665// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002666// | declaration_statement
2667// | selection_statement
2668// | switch_statement
2669// | case_label
2670// | iteration_statement
2671// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002672//
2673bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2674{
John Kessenich21472ae2016-06-04 11:46:33 -06002675 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002676
John Kessenich21472ae2016-06-04 11:46:33 -06002677 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002678 TAttributeMap attributes;
2679 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002680
John Kessenich21472ae2016-06-04 11:46:33 -06002681 // attributed_statement
2682 switch (peek()) {
2683 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002684 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002685
John Kessenich21472ae2016-06-04 11:46:33 -06002686 case EHTokIf:
2687 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002688
John Kessenich21472ae2016-06-04 11:46:33 -06002689 case EHTokSwitch:
2690 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002691
John Kessenich21472ae2016-06-04 11:46:33 -06002692 case EHTokFor:
2693 case EHTokDo:
2694 case EHTokWhile:
2695 return acceptIterationStatement(statement);
2696
2697 case EHTokContinue:
2698 case EHTokBreak:
2699 case EHTokDiscard:
2700 case EHTokReturn:
2701 return acceptJumpStatement(statement);
2702
2703 case EHTokCase:
2704 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002705 case EHTokDefault:
2706 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002707
2708 case EHTokSemicolon:
2709 return acceptTokenClass(EHTokSemicolon);
2710
2711 case EHTokRightBrace:
2712 // Performance: not strictly necessary, but stops a bunch of hunting early,
2713 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002714 return false;
2715
John Kessenich21472ae2016-06-04 11:46:33 -06002716 default:
2717 {
2718 // declaration
2719 if (acceptDeclaration(statement))
2720 return true;
2721
2722 // expression
2723 TIntermTyped* node;
2724 if (acceptExpression(node))
2725 statement = node;
2726 else
2727 return false;
2728
2729 // SEMICOLON (following an expression)
2730 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002731 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002732 return false;
2733 }
2734 }
2735 }
2736
John Kessenich5f934b02016-03-13 17:58:25 -06002737 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002738}
2739
John Kessenich21472ae2016-06-04 11:46:33 -06002740// attributes
2741// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2742//
2743// attribute:
2744// : UNROLL
2745// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2746// | FASTOPT
2747// | ALLOW_UAV_CONDITION
2748// | BRANCH
2749// | FLATTEN
2750// | FORCECASE
2751// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002752// | DOMAIN
2753// | EARLYDEPTHSTENCIL
2754// | INSTANCE
2755// | MAXTESSFACTOR
2756// | OUTPUTCONTROLPOINTS
2757// | OUTPUTTOPOLOGY
2758// | PARTITIONING
2759// | PATCHCONSTANTFUNC
2760// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002761//
steve-lunarg1868b142016-10-20 13:07:10 -06002762void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002763{
steve-lunarg1868b142016-10-20 13:07:10 -06002764 // For now, accept the [ XXX(X) ] syntax, but drop all but
2765 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002766 // TODO: subset to correct set? Pass on?
2767 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002768 HlslToken idToken;
2769
John Kessenich0d2b6de2016-06-05 11:23:11 -06002770 // LEFT_BRACKET?
2771 if (! acceptTokenClass(EHTokLeftBracket))
2772 return;
2773
2774 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002775 if (acceptIdentifier(idToken)) {
2776 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002777 } else if (! peekTokenClass(EHTokRightBracket)) {
2778 expected("identifier");
2779 advanceToken();
2780 }
2781
steve-lunarga22f7db2016-11-11 08:17:44 -07002782 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002783
2784 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002785 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002786 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002787
John Kessenich0d2b6de2016-06-05 11:23:11 -06002788 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002789 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07002790
steve-lunarga22f7db2016-11-11 08:17:44 -07002791 while (acceptAssignmentExpression(node)) {
2792 expectingExpression = false;
2793 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002794 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002795 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002796 }
2797
steve-lunarga22f7db2016-11-11 08:17:44 -07002798 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002799 if (! acceptTokenClass(EHTokRightParen))
2800 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002801
2802 // Error for partial or missing expression
2803 if (expectingExpression || expressions->getSequence().empty())
2804 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002805 }
2806
2807 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002808 if (!acceptTokenClass(EHTokRightBracket)) {
2809 expected("]");
2810 return;
2811 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002812
steve-lunarg1868b142016-10-20 13:07:10 -06002813 // Add any values we found into the attribute map. This accepts
2814 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002815 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002816 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002817}
2818
John Kessenich0d2b6de2016-06-05 11:23:11 -06002819// selection_statement
2820// : IF LEFT_PAREN expression RIGHT_PAREN statement
2821// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2822//
John Kessenich21472ae2016-06-04 11:46:33 -06002823bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2824{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002825 TSourceLoc loc = token.loc;
2826
2827 // IF
2828 if (! acceptTokenClass(EHTokIf))
2829 return false;
2830
2831 // so that something declared in the condition is scoped to the lifetimes
2832 // of the then-else statements
2833 parseContext.pushScope();
2834
2835 // LEFT_PAREN expression RIGHT_PAREN
2836 TIntermTyped* condition;
2837 if (! acceptParenExpression(condition))
2838 return false;
2839
2840 // create the child statements
2841 TIntermNodePair thenElse = { nullptr, nullptr };
2842
2843 // then statement
2844 if (! acceptScopedStatement(thenElse.node1)) {
2845 expected("then statement");
2846 return false;
2847 }
2848
2849 // ELSE
2850 if (acceptTokenClass(EHTokElse)) {
2851 // else statement
2852 if (! acceptScopedStatement(thenElse.node2)) {
2853 expected("else statement");
2854 return false;
2855 }
2856 }
2857
2858 // Put the pieces together
2859 statement = intermediate.addSelection(condition, thenElse, loc);
2860 parseContext.popScope();
2861
2862 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002863}
2864
John Kessenichd02dc5d2016-07-01 00:04:11 -06002865// switch_statement
2866// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2867//
John Kessenich21472ae2016-06-04 11:46:33 -06002868bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2869{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002870 // SWITCH
2871 TSourceLoc loc = token.loc;
2872 if (! acceptTokenClass(EHTokSwitch))
2873 return false;
2874
2875 // LEFT_PAREN expression RIGHT_PAREN
2876 parseContext.pushScope();
2877 TIntermTyped* switchExpression;
2878 if (! acceptParenExpression(switchExpression)) {
2879 parseContext.popScope();
2880 return false;
2881 }
2882
2883 // compound_statement
2884 parseContext.pushSwitchSequence(new TIntermSequence);
2885 bool statementOkay = acceptCompoundStatement(statement);
2886 if (statementOkay)
2887 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2888
2889 parseContext.popSwitchSequence();
2890 parseContext.popScope();
2891
2892 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002893}
2894
John Kessenich119f8f62016-06-05 15:44:07 -06002895// iteration_statement
2896// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2897// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2898// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2899//
2900// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002901bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2902{
John Kessenich119f8f62016-06-05 15:44:07 -06002903 TSourceLoc loc = token.loc;
2904 TIntermTyped* condition = nullptr;
2905
2906 EHlslTokenClass loop = peek();
2907 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2908
2909 // WHILE or DO or FOR
2910 advanceToken();
2911
2912 switch (loop) {
2913 case EHTokWhile:
2914 // so that something declared in the condition is scoped to the lifetime
2915 // of the while sub-statement
2916 parseContext.pushScope();
2917 parseContext.nestLooping();
2918
2919 // LEFT_PAREN condition RIGHT_PAREN
2920 if (! acceptParenExpression(condition))
2921 return false;
2922
2923 // statement
2924 if (! acceptScopedStatement(statement)) {
2925 expected("while sub-statement");
2926 return false;
2927 }
2928
2929 parseContext.unnestLooping();
2930 parseContext.popScope();
2931
2932 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2933
2934 return true;
2935
2936 case EHTokDo:
2937 parseContext.nestLooping();
2938
2939 if (! acceptTokenClass(EHTokLeftBrace))
2940 expected("{");
2941
2942 // statement
2943 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2944 expected("do sub-statement");
2945 return false;
2946 }
2947
2948 if (! acceptTokenClass(EHTokRightBrace))
2949 expected("}");
2950
2951 // WHILE
2952 if (! acceptTokenClass(EHTokWhile)) {
2953 expected("while");
2954 return false;
2955 }
2956
2957 // LEFT_PAREN condition RIGHT_PAREN
2958 TIntermTyped* condition;
2959 if (! acceptParenExpression(condition))
2960 return false;
2961
2962 if (! acceptTokenClass(EHTokSemicolon))
2963 expected(";");
2964
2965 parseContext.unnestLooping();
2966
2967 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2968
2969 return true;
2970
2971 case EHTokFor:
2972 {
2973 // LEFT_PAREN
2974 if (! acceptTokenClass(EHTokLeftParen))
2975 expected("(");
2976
2977 // so that something declared in the condition is scoped to the lifetime
2978 // of the for sub-statement
2979 parseContext.pushScope();
2980
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002981 // initializer
2982 TIntermNode* initNode = nullptr;
2983 if (! acceptControlDeclaration(initNode)) {
2984 TIntermTyped* initExpr = nullptr;
2985 acceptExpression(initExpr);
2986 initNode = initExpr;
2987 }
2988 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002989 if (! acceptTokenClass(EHTokSemicolon))
2990 expected(";");
2991
2992 parseContext.nestLooping();
2993
2994 // condition SEMI_COLON
2995 acceptExpression(condition);
2996 if (! acceptTokenClass(EHTokSemicolon))
2997 expected(";");
2998
2999 // iterator SEMI_COLON
3000 TIntermTyped* iterator = nullptr;
3001 acceptExpression(iterator);
3002 if (! acceptTokenClass(EHTokRightParen))
3003 expected(")");
3004
3005 // statement
3006 if (! acceptScopedStatement(statement)) {
3007 expected("for sub-statement");
3008 return false;
3009 }
3010
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003011 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06003012
3013 parseContext.popScope();
3014 parseContext.unnestLooping();
3015
3016 return true;
3017 }
3018
3019 default:
3020 return false;
3021 }
John Kessenich21472ae2016-06-04 11:46:33 -06003022}
3023
3024// jump_statement
3025// : CONTINUE SEMICOLON
3026// | BREAK SEMICOLON
3027// | DISCARD SEMICOLON
3028// | RETURN SEMICOLON
3029// | RETURN expression SEMICOLON
3030//
3031bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3032{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003033 EHlslTokenClass jump = peek();
3034 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003035 case EHTokContinue:
3036 case EHTokBreak:
3037 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003038 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003039 advanceToken();
3040 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003041 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003042 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003043 return false;
3044 }
John Kessenich21472ae2016-06-04 11:46:33 -06003045
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003046 switch (jump) {
3047 case EHTokContinue:
3048 statement = intermediate.addBranch(EOpContinue, token.loc);
3049 break;
3050 case EHTokBreak:
3051 statement = intermediate.addBranch(EOpBreak, token.loc);
3052 break;
3053 case EHTokDiscard:
3054 statement = intermediate.addBranch(EOpKill, token.loc);
3055 break;
3056
3057 case EHTokReturn:
3058 {
3059 // expression
3060 TIntermTyped* node;
3061 if (acceptExpression(node)) {
3062 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003063 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003064 } else
3065 statement = intermediate.addBranch(EOpReturn, token.loc);
3066 break;
3067 }
3068
3069 default:
3070 assert(0);
3071 return false;
3072 }
3073
3074 // SEMICOLON
3075 if (! acceptTokenClass(EHTokSemicolon))
3076 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003077
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003078 return true;
3079}
John Kessenich21472ae2016-06-04 11:46:33 -06003080
John Kessenichd02dc5d2016-07-01 00:04:11 -06003081// case_label
3082// : CASE expression COLON
3083//
John Kessenich21472ae2016-06-04 11:46:33 -06003084bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3085{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003086 TSourceLoc loc = token.loc;
3087 if (! acceptTokenClass(EHTokCase))
3088 return false;
3089
3090 TIntermTyped* expression;
3091 if (! acceptExpression(expression)) {
3092 expected("case expression");
3093 return false;
3094 }
3095
3096 if (! acceptTokenClass(EHTokColon)) {
3097 expected(":");
3098 return false;
3099 }
3100
3101 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3102
3103 return true;
3104}
3105
3106// default_label
3107// : DEFAULT COLON
3108//
3109bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3110{
3111 TSourceLoc loc = token.loc;
3112 if (! acceptTokenClass(EHTokDefault))
3113 return false;
3114
3115 if (! acceptTokenClass(EHTokColon)) {
3116 expected(":");
3117 return false;
3118 }
3119
3120 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3121
3122 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003123}
3124
John Kessenich19b92ff2016-06-19 11:50:34 -06003125// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003126// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3127// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003128//
3129void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3130{
3131 arraySizes = nullptr;
3132
steve-lunarg7b211a32016-10-13 12:26:18 -06003133 // Early-out if there aren't any array dimensions
3134 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003135 return;
3136
steve-lunarg7b211a32016-10-13 12:26:18 -06003137 // 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 -06003138 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003139
3140 // Collect each array dimension.
3141 while (acceptTokenClass(EHTokLeftBracket)) {
3142 TSourceLoc loc = token.loc;
3143 TIntermTyped* sizeExpr = nullptr;
3144
3145 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
3146 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3147
3148 if (! acceptTokenClass(EHTokRightBracket)) {
3149 expected("]");
3150 return;
3151 }
3152
3153 if (hasArraySize) {
3154 TArraySize arraySize;
3155 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3156 arraySizes->addInnerSize(arraySize);
3157 } else {
3158 arraySizes->addInnerSize(0); // sized by initializers.
3159 }
steve-lunarg265c0612016-09-27 10:57:35 -06003160 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003161}
3162
John Kessenich630dd7d2016-06-12 23:52:12 -06003163// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003164// : COLON semantic // optional
3165// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3166// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003167// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003168// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003169//
John Kessenich7735b942016-09-05 12:40:06 -06003170void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003171{
John Kessenich630dd7d2016-06-12 23:52:12 -06003172 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003173 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003174 if (acceptTokenClass(EHTokColon)) {
3175 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003176 if (peekTokenClass(EHTokLayout))
3177 acceptLayoutQualifierList(qualifier);
3178 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003179 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003180 if (! acceptTokenClass(EHTokLeftParen)) {
3181 expected("(");
3182 return;
3183 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003184 HlslToken locationToken;
3185 if (! acceptIdentifier(locationToken)) {
3186 expected("c[subcomponent][.component]");
3187 return;
3188 }
3189 HlslToken componentToken;
3190 if (acceptTokenClass(EHTokDot)) {
3191 if (! acceptIdentifier(componentToken)) {
3192 expected("component");
3193 return;
3194 }
3195 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003196 if (! acceptTokenClass(EHTokRightParen)) {
3197 expected(")");
3198 break;
3199 }
John Kessenich7735b942016-09-05 12:40:06 -06003200 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003201 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003202 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06003203 return;
3204 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003205 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3206 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003207 if (! acceptTokenClass(EHTokLeftParen)) {
3208 expected("(");
3209 return;
3210 }
John Kessenichb38f0712016-07-30 10:29:54 -06003211 HlslToken registerDesc; // for Type#
3212 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003213 if (! acceptIdentifier(registerDesc)) {
3214 expected("register number description");
3215 return;
3216 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003217 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3218 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003219 // Then we didn't really see the registerDesc yet, it was
3220 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003221 profile = registerDesc;
3222 if (! acceptIdentifier(registerDesc)) {
3223 expected("register number description");
3224 return;
3225 }
3226 }
John Kessenichb38f0712016-07-30 10:29:54 -06003227 int subComponent = 0;
3228 if (acceptTokenClass(EHTokLeftBracket)) {
3229 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3230 if (! peekTokenClass(EHTokIntConstant)) {
3231 expected("literal integer");
3232 return;
3233 }
3234 subComponent = token.i;
3235 advanceToken();
3236 if (! acceptTokenClass(EHTokRightBracket)) {
3237 expected("]");
3238 break;
3239 }
3240 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003241 // (COMMA SPACEN)opt
3242 HlslToken spaceDesc;
3243 if (acceptTokenClass(EHTokComma)) {
3244 if (! acceptIdentifier(spaceDesc)) {
3245 expected ("space identifier");
3246 return;
3247 }
3248 }
3249 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003250 if (! acceptTokenClass(EHTokRightParen)) {
3251 expected(")");
3252 break;
3253 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003254 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003255 } else {
3256 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003257 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003258 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003259 } else if (peekTokenClass(EHTokLeftAngle))
3260 acceptAnnotations(qualifier);
3261 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003262 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003263
John Kessenich630dd7d2016-06-12 23:52:12 -06003264 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003265}
3266
John Kesseniche01a9bc2016-03-12 20:11:22 -07003267} // end namespace glslang