blob: f0d7b723c1c74243d7edfb5681be779cbcbcbd88 [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 // TODO: things scoped within an annotation need their own name space;
410 // TODO: strings are not yet handled.
411 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
412 if (typedefDecl)
413 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
414 else if (variableType.getBasicType() == EbtBlock)
steve-lunargdd8287a2017-02-23 18:04:12 -0700415 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
John Kessenich6dbc0a72016-09-27 19:13:05 -0600416 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700417 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600418 // this isn't really an individual variable, but a member of the $Global buffer
419 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
420 } else {
421 // Declare the variable and add any initializer code to the AST.
422 // The top-level node is always made into an aggregate, as that's
423 // historically how the AST has been.
424 node = intermediate.growAggregate(node,
425 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
426 expressionNode),
427 idToken.loc);
428 }
429 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600430 }
John Kessenich5f934b02016-03-13 17:58:25 -0600431 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600432
433 if (acceptTokenClass(EHTokComma)) {
434 list = true;
435 continue;
436 }
437 };
438
439 // The top-level node is a sequence.
440 if (node != nullptr)
441 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700442
John Kessenich078d7f22016-03-14 10:02:11 -0600443 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600444 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700445 // This may have been a false detection of what appeared to be a declaration, but
446 // was actually an assignment such as "float = 4", where "float" is an identifier.
447 // We put the token back to let further parsing happen for cases where that may
448 // happen. This errors on the side of caution, and mostly triggers the error.
449
450 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
451 recedeToken();
452 else
453 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600454 return false;
455 }
John Kessenichecba76f2017-01-06 00:34:48 -0700456
John Kesseniche01a9bc2016-03-12 20:11:22 -0700457 return true;
458}
459
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600460// control_declaration
461// : fully_specified_type identifier EQUAL expression
462//
463bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
464{
465 node = nullptr;
466
467 // fully_specified_type
468 TType type;
469 if (! acceptFullySpecifiedType(type))
470 return false;
471
472 // identifier
473 HlslToken idToken;
474 if (! acceptIdentifier(idToken)) {
475 expected("identifier");
476 return false;
477 }
478
479 // EQUAL
480 TIntermTyped* expressionNode = nullptr;
481 if (! acceptTokenClass(EHTokAssign)) {
482 expected("=");
483 return false;
484 }
485
486 // expression
487 if (! acceptExpression(expressionNode)) {
488 expected("initializer");
489 return false;
490 }
491
John Kesseniche82061d2016-09-27 14:38:57 -0600492 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600493
494 return true;
495}
496
John Kessenich87142c72016-03-12 20:24:24 -0700497// fully_specified_type
498// : type_specifier
499// | type_qualifier type_specifier
500//
501bool HlslGrammar::acceptFullySpecifiedType(TType& type)
502{
503 // type_qualifier
504 TQualifier qualifier;
505 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600506 if (! acceptQualifier(qualifier))
507 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600508 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700509
510 // type_specifier
steve-lunarga64ed3e2016-12-18 17:51:14 -0700511 if (! acceptType(type)) {
512 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700513 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700514 // qualifier. Back it out, if we did.
515 if (qualifier.sample)
516 recedeToken();
517
John Kessenich87142c72016-03-12 20:24:24 -0700518 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700519 }
John Kessenich3d157c52016-07-25 16:05:33 -0600520 if (type.getBasicType() == EbtBlock) {
521 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600522 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600523 // further, it can create an anonymous instance of the block
524 if (peekTokenClass(EHTokSemicolon))
525 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600526 } else {
527 // Some qualifiers are set when parsing the type. Merge those with
528 // whatever comes from acceptQualifier.
529 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700530
steve-lunargbb0183f2016-10-04 16:58:14 -0600531 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600532 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700533
steve-lunarg5da1f032017-02-12 17:50:28 -0700534 if (type.getQualifier().storage == EvqVaryingOut ||
535 type.getQualifier().storage == EvqBuffer) {
steve-lunargf49cdf42016-11-17 15:04:20 -0700536 qualifier.storage = type.getQualifier().storage;
steve-lunarg5da1f032017-02-12 17:50:28 -0700537 qualifier.readonly = type.getQualifier().readonly;
538 }
steve-lunargf49cdf42016-11-17 15:04:20 -0700539
540 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600541 }
John Kessenich87142c72016-03-12 20:24:24 -0700542
543 return true;
544}
545
John Kessenich630dd7d2016-06-12 23:52:12 -0600546// type_qualifier
547// : qualifier qualifier ...
548//
549// Zero or more of these, so this can't return false.
550//
John Kessenichb9e39122016-08-17 10:22:08 -0600551bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700552{
John Kessenich630dd7d2016-06-12 23:52:12 -0600553 do {
554 switch (peek()) {
555 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600556 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600557 break;
558 case EHTokExtern:
559 // TODO: no meaning in glslang?
560 break;
561 case EHTokShared:
562 // TODO: hint
563 break;
564 case EHTokGroupShared:
565 qualifier.storage = EvqShared;
566 break;
567 case EHTokUniform:
568 qualifier.storage = EvqUniform;
569 break;
570 case EHTokConst:
571 qualifier.storage = EvqConst;
572 break;
573 case EHTokVolatile:
574 qualifier.volatil = true;
575 break;
576 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600577 qualifier.smooth = true;
578 break;
579 case EHTokCentroid:
580 qualifier.centroid = true;
581 break;
582 case EHTokNointerpolation:
583 qualifier.flat = true;
584 break;
585 case EHTokNoperspective:
586 qualifier.nopersp = true;
587 break;
588 case EHTokSample:
589 qualifier.sample = true;
590 break;
591 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600592 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600593 break;
594 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600595 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600596 break;
597 case EHTokPrecise:
598 qualifier.noContraction = true;
599 break;
LoopDawg9249c702016-07-12 20:44:32 -0600600 case EHTokIn:
601 qualifier.storage = EvqIn;
602 break;
603 case EHTokOut:
604 qualifier.storage = EvqOut;
605 break;
606 case EHTokInOut:
607 qualifier.storage = EvqInOut;
608 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600609 case EHTokLayout:
610 if (! acceptLayoutQualifierList(qualifier))
611 return false;
612 continue;
steve-lunarg5da1f032017-02-12 17:50:28 -0700613 case EHTokGloballyCoherent:
614 qualifier.coherent = true;
615 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700616
617 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
618 // for output variables.
619 case EHTokPoint:
620 qualifier.storage = EvqIn;
621 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
622 return false;
623 break;
624 case EHTokLine:
625 qualifier.storage = EvqIn;
626 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
627 return false;
628 break;
629 case EHTokTriangle:
630 qualifier.storage = EvqIn;
631 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
632 return false;
633 break;
634 case EHTokLineAdj:
635 qualifier.storage = EvqIn;
636 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
637 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700638 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700639 case EHTokTriangleAdj:
640 qualifier.storage = EvqIn;
641 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
642 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700643 break;
644
John Kessenich630dd7d2016-06-12 23:52:12 -0600645 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600646 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600647 }
648 advanceToken();
649 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700650}
651
John Kessenichb9e39122016-08-17 10:22:08 -0600652// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600653// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600654//
655// layout_qualifier
656// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600657// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600658//
659// Zero or more of these, so this can't return false.
660//
661bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
662{
663 if (! acceptTokenClass(EHTokLayout))
664 return false;
665
666 // LEFT_PAREN
667 if (! acceptTokenClass(EHTokLeftParen))
668 return false;
669
670 do {
671 // identifier
672 HlslToken idToken;
673 if (! acceptIdentifier(idToken))
674 break;
675
676 // EQUAL expression
677 if (acceptTokenClass(EHTokAssign)) {
678 TIntermTyped* expr;
679 if (! acceptConditionalExpression(expr)) {
680 expected("expression");
681 return false;
682 }
683 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
684 } else
685 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
686
687 // COMMA
688 if (! acceptTokenClass(EHTokComma))
689 break;
690 } while (true);
691
692 // RIGHT_PAREN
693 if (! acceptTokenClass(EHTokRightParen)) {
694 expected(")");
695 return false;
696 }
697
698 return true;
699}
700
LoopDawg6daaa4f2016-06-23 19:13:48 -0600701// template_type
702// : FLOAT
703// | DOUBLE
704// | INT
705// | DWORD
706// | UINT
707// | BOOL
708//
steve-lunargf49cdf42016-11-17 15:04:20 -0700709bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600710{
711 switch (peek()) {
712 case EHTokFloat:
713 basicType = EbtFloat;
714 break;
715 case EHTokDouble:
716 basicType = EbtDouble;
717 break;
718 case EHTokInt:
719 case EHTokDword:
720 basicType = EbtInt;
721 break;
722 case EHTokUint:
723 basicType = EbtUint;
724 break;
725 case EHTokBool:
726 basicType = EbtBool;
727 break;
728 default:
729 return false;
730 }
731
732 advanceToken();
733
734 return true;
735}
736
737// vector_template_type
738// : VECTOR
739// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
740//
741bool HlslGrammar::acceptVectorTemplateType(TType& type)
742{
743 if (! acceptTokenClass(EHTokVector))
744 return false;
745
746 if (! acceptTokenClass(EHTokLeftAngle)) {
747 // in HLSL, 'vector' alone means float4.
748 new(&type) TType(EbtFloat, EvqTemporary, 4);
749 return true;
750 }
751
752 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700753 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600754 expected("scalar type");
755 return false;
756 }
757
758 // COMMA
759 if (! acceptTokenClass(EHTokComma)) {
760 expected(",");
761 return false;
762 }
763
764 // integer
765 if (! peekTokenClass(EHTokIntConstant)) {
766 expected("literal integer");
767 return false;
768 }
769
770 TIntermTyped* vecSize;
771 if (! acceptLiteral(vecSize))
772 return false;
773
774 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
775
776 new(&type) TType(basicType, EvqTemporary, vecSizeI);
777
778 if (vecSizeI == 1)
779 type.makeVector();
780
781 if (!acceptTokenClass(EHTokRightAngle)) {
782 expected("right angle bracket");
783 return false;
784 }
785
786 return true;
787}
788
789// matrix_template_type
790// : MATRIX
791// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
792//
793bool HlslGrammar::acceptMatrixTemplateType(TType& type)
794{
795 if (! acceptTokenClass(EHTokMatrix))
796 return false;
797
798 if (! acceptTokenClass(EHTokLeftAngle)) {
799 // in HLSL, 'matrix' alone means float4x4.
800 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
801 return true;
802 }
803
804 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700805 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600806 expected("scalar type");
807 return false;
808 }
809
810 // COMMA
811 if (! acceptTokenClass(EHTokComma)) {
812 expected(",");
813 return false;
814 }
815
816 // integer rows
817 if (! peekTokenClass(EHTokIntConstant)) {
818 expected("literal integer");
819 return false;
820 }
821
822 TIntermTyped* rows;
823 if (! acceptLiteral(rows))
824 return false;
825
826 // COMMA
827 if (! acceptTokenClass(EHTokComma)) {
828 expected(",");
829 return false;
830 }
John Kessenichecba76f2017-01-06 00:34:48 -0700831
LoopDawg6daaa4f2016-06-23 19:13:48 -0600832 // integer cols
833 if (! peekTokenClass(EHTokIntConstant)) {
834 expected("literal integer");
835 return false;
836 }
837
838 TIntermTyped* cols;
839 if (! acceptLiteral(cols))
840 return false;
841
842 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600843 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
844 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600845
846 if (!acceptTokenClass(EHTokRightAngle)) {
847 expected("right angle bracket");
848 return false;
849 }
850
851 return true;
852}
853
steve-lunargf49cdf42016-11-17 15:04:20 -0700854// layout_geometry
855// : LINESTREAM
856// | POINTSTREAM
857// | TRIANGLESTREAM
858//
859bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
860{
861 // read geometry type
862 const EHlslTokenClass geometryType = peek();
863
864 switch (geometryType) {
865 case EHTokPointStream: geometry = ElgPoints; break;
866 case EHTokLineStream: geometry = ElgLineStrip; break;
867 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
868 default:
869 return false; // not a layout geometry
870 }
871
872 advanceToken(); // consume the layout keyword
873 return true;
874}
875
steve-lunarg858c9282017-01-07 08:54:10 -0700876// tessellation_decl_type
877// : INPUTPATCH
878// | OUTPUTPATCH
879//
880bool HlslGrammar::acceptTessellationDeclType()
881{
882 // read geometry type
883 const EHlslTokenClass tessType = peek();
884
885 switch (tessType) {
886 case EHTokInputPatch: break;
887 case EHTokOutputPatch: break;
888 default:
889 return false; // not a tessellation decl
890 }
891
892 advanceToken(); // consume the keyword
893 return true;
894}
895
896// tessellation_patch_template_type
897// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
898//
899bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
900{
901 if (! acceptTessellationDeclType())
902 return false;
903
904 if (! acceptTokenClass(EHTokLeftAngle))
905 return false;
906
907 if (! acceptType(type)) {
908 expected("tessellation patch type");
909 return false;
910 }
911
912 if (! acceptTokenClass(EHTokComma))
913 return false;
914
915 // integer size
916 if (! peekTokenClass(EHTokIntConstant)) {
917 expected("literal integer");
918 return false;
919 }
920
921 TIntermTyped* size;
922 if (! acceptLiteral(size))
923 return false;
924
925 TArraySizes* arraySizes = new TArraySizes;
926 arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
927 type.newArraySizes(*arraySizes);
928
929 if (! acceptTokenClass(EHTokRightAngle)) {
930 expected("right angle bracket");
931 return false;
932 }
933
934 return true;
935}
936
steve-lunargf49cdf42016-11-17 15:04:20 -0700937// stream_out_template_type
938// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
939//
940bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
941{
942 geometry = ElgNone;
943
944 if (! acceptOutputPrimitiveGeometry(geometry))
945 return false;
946
947 if (! acceptTokenClass(EHTokLeftAngle))
948 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700949
steve-lunargf49cdf42016-11-17 15:04:20 -0700950 if (! acceptType(type)) {
951 expected("stream output type");
952 return false;
953 }
954
955 type.getQualifier().storage = EvqVaryingOut;
956
957 if (! acceptTokenClass(EHTokRightAngle)) {
958 expected("right angle bracket");
959 return false;
960 }
961
962 return true;
963}
John Kessenichecba76f2017-01-06 00:34:48 -0700964
John Kessenicha1e2d492016-09-20 13:22:58 -0600965// annotations
966// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600967//
John Kessenicha1e2d492016-09-20 13:22:58 -0600968bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600969{
John Kessenicha1e2d492016-09-20 13:22:58 -0600970 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600971 return false;
972
John Kessenicha1e2d492016-09-20 13:22:58 -0600973 // note that we are nesting a name space
974 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600975
976 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
977 do {
978 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
979 while (acceptTokenClass(EHTokSemicolon))
980 ;
981
982 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600983 break;
John Kessenich86f71382016-09-19 20:23:18 -0600984
985 // declaration
986 TIntermNode* node;
987 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600988 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600989 return false;
990 }
991 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600992
993 parseContext.unnestAnnotations();
994 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600995}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600996
LoopDawg4886f692016-06-29 10:58:58 -0600997// sampler_type
998// : SAMPLER
999// | SAMPLER1D
1000// | SAMPLER2D
1001// | SAMPLER3D
1002// | SAMPLERCUBE
1003// | SAMPLERSTATE
1004// | SAMPLERCOMPARISONSTATE
1005bool HlslGrammar::acceptSamplerType(TType& type)
1006{
1007 // read sampler type
1008 const EHlslTokenClass samplerType = peek();
1009
LoopDawga78b0292016-07-19 14:28:05 -06001010 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -06001011 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -06001012
LoopDawga78b0292016-07-19 14:28:05 -06001013 bool isShadow = false;
1014
LoopDawg4886f692016-06-29 10:58:58 -06001015 switch (samplerType) {
1016 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -06001017 case EHTokSampler1d: /*dim = Esd1D*/; break;
1018 case EHTokSampler2d: /*dim = Esd2D*/; break;
1019 case EHTokSampler3d: /*dim = Esd3D*/; break;
1020 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -06001021 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -06001022 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001023 default:
1024 return false; // not a sampler declaration
1025 }
1026
1027 advanceToken(); // consume the sampler type keyword
1028
1029 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -06001030
1031 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -06001032 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -06001033
1034 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1035
1036 return true;
1037}
1038
1039// texture_type
1040// | BUFFER
1041// | TEXTURE1D
1042// | TEXTURE1DARRAY
1043// | TEXTURE2D
1044// | TEXTURE2DARRAY
1045// | TEXTURE3D
1046// | TEXTURECUBE
1047// | TEXTURECUBEARRAY
1048// | TEXTURE2DMS
1049// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -06001050// | RWBUFFER
1051// | RWTEXTURE1D
1052// | RWTEXTURE1DARRAY
1053// | RWTEXTURE2D
1054// | RWTEXTURE2DARRAY
1055// | RWTEXTURE3D
1056
LoopDawg4886f692016-06-29 10:58:58 -06001057bool HlslGrammar::acceptTextureType(TType& type)
1058{
1059 const EHlslTokenClass textureType = peek();
1060
1061 TSamplerDim dim = EsdNone;
1062 bool array = false;
1063 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001064 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -06001065
1066 switch (textureType) {
1067 case EHTokBuffer: dim = EsdBuffer; break;
1068 case EHTokTexture1d: dim = Esd1D; break;
1069 case EHTokTexture1darray: dim = Esd1D; array = true; break;
1070 case EHTokTexture2d: dim = Esd2D; break;
1071 case EHTokTexture2darray: dim = Esd2D; array = true; break;
John Kessenichecba76f2017-01-06 00:34:48 -07001072 case EHTokTexture3d: dim = Esd3D; break;
LoopDawg4886f692016-06-29 10:58:58 -06001073 case EHTokTextureCube: dim = EsdCube; break;
1074 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
1075 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
1076 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -06001077 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1078 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1079 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1080 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1081 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1082 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001083 default:
1084 return false; // not a texture declaration
1085 }
1086
1087 advanceToken(); // consume the texture object keyword
1088
1089 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001090
LoopDawg4886f692016-06-29 10:58:58 -06001091 TIntermTyped* msCount = nullptr;
1092
steve-lunargbb0183f2016-10-04 16:58:14 -06001093 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001094 if (acceptTokenClass(EHTokLeftAngle)) {
1095 if (! acceptType(txType)) {
1096 expected("scalar or vector type");
1097 return false;
1098 }
1099
1100 const TBasicType basicRetType = txType.getBasicType() ;
1101
1102 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1103 unimplemented("basic type in texture");
1104 return false;
1105 }
1106
steve-lunargd53f7172016-07-27 15:46:48 -06001107 // Buffers can handle small mats if they fit in 4 components
1108 if (dim == EsdBuffer && txType.isMatrix()) {
1109 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1110 expected("components < 4 in matrix buffer type");
1111 return false;
1112 }
1113
1114 // TODO: except we don't handle it yet...
1115 unimplemented("matrix type in buffer");
1116 return false;
1117 }
1118
LoopDawg4886f692016-06-29 10:58:58 -06001119 if (!txType.isScalar() && !txType.isVector()) {
1120 expected("scalar or vector type");
1121 return false;
1122 }
1123
LoopDawg4886f692016-06-29 10:58:58 -06001124 if (ms && acceptTokenClass(EHTokComma)) {
1125 // read sample count for multisample types, if given
1126 if (! peekTokenClass(EHTokIntConstant)) {
1127 expected("multisample count");
1128 return false;
1129 }
1130
1131 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1132 return false;
1133 }
1134
1135 if (! acceptTokenClass(EHTokRightAngle)) {
1136 expected("right angle bracket");
1137 return false;
1138 }
1139 } else if (ms) {
1140 expected("texture type for multisample");
1141 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001142 } else if (image) {
1143 expected("type for RWTexture/RWBuffer");
1144 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001145 }
1146
1147 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001148 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001149
1150 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001151 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001152
steve-lunarg4f2da272016-10-10 15:24:57 -06001153 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1154 if (image || dim == EsdBuffer)
1155 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001156
1157 // Non-image Buffers are combined
1158 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001159 sampler.set(txType.getBasicType(), dim, array);
1160 } else {
1161 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001162 if (image) {
1163 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1164 } else {
1165 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1166 }
steve-lunargd53f7172016-07-27 15:46:48 -06001167 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001168
1169 // Remember the declared vector size.
1170 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001171
LoopDawg4886f692016-06-29 10:58:58 -06001172 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001173 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001174
1175 return true;
1176}
1177
John Kessenich87142c72016-03-12 20:24:24 -07001178// If token is for a type, update 'type' with the type information,
1179// and return true and advance.
1180// Otherwise, return false, and don't advance
1181bool HlslGrammar::acceptType(TType& type)
1182{
steve-lunarg3226b082016-10-26 19:18:55 -06001183 // Basic types for min* types, broken out here in case of future
1184 // changes, e.g, to use native halfs.
1185 static const TBasicType min16float_bt = EbtFloat;
1186 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001187 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001188 static const TBasicType min16int_bt = EbtInt;
1189 static const TBasicType min12int_bt = EbtInt;
1190 static const TBasicType min16uint_bt = EbtUint;
1191
John Kessenich9c86c6a2016-05-03 22:49:24 -06001192 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001193 case EHTokVector:
1194 return acceptVectorTemplateType(type);
1195 break;
1196
1197 case EHTokMatrix:
1198 return acceptMatrixTemplateType(type);
1199 break;
1200
steve-lunargf49cdf42016-11-17 15:04:20 -07001201 case EHTokPointStream: // fall through
1202 case EHTokLineStream: // ...
1203 case EHTokTriangleStream: // ...
1204 {
1205 TLayoutGeometry geometry;
1206 if (! acceptStreamOutTemplateType(type, geometry))
1207 return false;
1208
1209 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1210 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001211
steve-lunargf49cdf42016-11-17 15:04:20 -07001212 return true;
1213 }
1214
steve-lunarg858c9282017-01-07 08:54:10 -07001215 case EHTokInputPatch: // fall through
1216 case EHTokOutputPatch: // ...
1217 {
1218 if (! acceptTessellationPatchTemplateType(type))
1219 return false;
1220
1221 return true;
1222 }
1223
LoopDawg4886f692016-06-29 10:58:58 -06001224 case EHTokSampler: // fall through
1225 case EHTokSampler1d: // ...
1226 case EHTokSampler2d: // ...
1227 case EHTokSampler3d: // ...
1228 case EHTokSamplerCube: // ...
1229 case EHTokSamplerState: // ...
1230 case EHTokSamplerComparisonState: // ...
1231 return acceptSamplerType(type);
1232 break;
1233
1234 case EHTokBuffer: // fall through
1235 case EHTokTexture1d: // ...
1236 case EHTokTexture1darray: // ...
1237 case EHTokTexture2d: // ...
1238 case EHTokTexture2darray: // ...
1239 case EHTokTexture3d: // ...
1240 case EHTokTextureCube: // ...
1241 case EHTokTextureCubearray: // ...
1242 case EHTokTexture2DMS: // ...
1243 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001244 case EHTokRWTexture1d: // ...
1245 case EHTokRWTexture1darray: // ...
1246 case EHTokRWTexture2d: // ...
1247 case EHTokRWTexture2darray: // ...
1248 case EHTokRWTexture3d: // ...
1249 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001250 return acceptTextureType(type);
1251 break;
1252
steve-lunarg5da1f032017-02-12 17:50:28 -07001253 case EHTokAppendStructuredBuffer:
1254 case EHTokByteAddressBuffer:
1255 case EHTokConsumeStructuredBuffer:
1256 case EHTokRWByteAddressBuffer:
1257 case EHTokRWStructuredBuffer:
1258 case EHTokStructuredBuffer:
1259 return acceptStructBufferType(type);
1260 break;
1261
John Kessenich27ffb292017-03-03 17:01:01 -07001262 case EHTokClass:
John Kesseniche6e74942016-06-11 16:43:14 -06001263 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001264 case EHTokCBuffer:
1265 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001266 return acceptStruct(type);
John Kesseniche6e74942016-06-11 16:43:14 -06001267
1268 case EHTokIdentifier:
1269 // An identifier could be for a user-defined type.
1270 // Note we cache the symbol table lookup, to save for a later rule
1271 // when this is not a type.
John Kessenich854fe242017-03-02 14:30:59 -07001272 token.symbol = parseContext.lookupUserType(*token.string, type);
1273 if (token.symbol != nullptr) {
John Kesseniche6e74942016-06-11 16:43:14 -06001274 advanceToken();
1275 return true;
1276 } else
1277 return false;
1278
John Kessenich71351de2016-06-08 12:50:56 -06001279 case EHTokVoid:
1280 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001281 break;
John Kessenich71351de2016-06-08 12:50:56 -06001282
John Kessenicha1e2d492016-09-20 13:22:58 -06001283 case EHTokString:
1284 new(&type) TType(EbtString);
1285 break;
1286
John Kessenich87142c72016-03-12 20:24:24 -07001287 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001288 new(&type) TType(EbtFloat);
1289 break;
John Kessenich87142c72016-03-12 20:24:24 -07001290 case EHTokFloat1:
1291 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001292 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001293 break;
John Kessenich87142c72016-03-12 20:24:24 -07001294 case EHTokFloat2:
1295 new(&type) TType(EbtFloat, EvqTemporary, 2);
1296 break;
1297 case EHTokFloat3:
1298 new(&type) TType(EbtFloat, EvqTemporary, 3);
1299 break;
1300 case EHTokFloat4:
1301 new(&type) TType(EbtFloat, EvqTemporary, 4);
1302 break;
1303
John Kessenich71351de2016-06-08 12:50:56 -06001304 case EHTokDouble:
1305 new(&type) TType(EbtDouble);
1306 break;
1307 case EHTokDouble1:
1308 new(&type) TType(EbtDouble);
1309 type.makeVector();
1310 break;
1311 case EHTokDouble2:
1312 new(&type) TType(EbtDouble, EvqTemporary, 2);
1313 break;
1314 case EHTokDouble3:
1315 new(&type) TType(EbtDouble, EvqTemporary, 3);
1316 break;
1317 case EHTokDouble4:
1318 new(&type) TType(EbtDouble, EvqTemporary, 4);
1319 break;
1320
1321 case EHTokInt:
1322 case EHTokDword:
1323 new(&type) TType(EbtInt);
1324 break;
1325 case EHTokInt1:
1326 new(&type) TType(EbtInt);
1327 type.makeVector();
1328 break;
John Kessenich87142c72016-03-12 20:24:24 -07001329 case EHTokInt2:
1330 new(&type) TType(EbtInt, EvqTemporary, 2);
1331 break;
1332 case EHTokInt3:
1333 new(&type) TType(EbtInt, EvqTemporary, 3);
1334 break;
1335 case EHTokInt4:
1336 new(&type) TType(EbtInt, EvqTemporary, 4);
1337 break;
1338
John Kessenich71351de2016-06-08 12:50:56 -06001339 case EHTokUint:
1340 new(&type) TType(EbtUint);
1341 break;
1342 case EHTokUint1:
1343 new(&type) TType(EbtUint);
1344 type.makeVector();
1345 break;
1346 case EHTokUint2:
1347 new(&type) TType(EbtUint, EvqTemporary, 2);
1348 break;
1349 case EHTokUint3:
1350 new(&type) TType(EbtUint, EvqTemporary, 3);
1351 break;
1352 case EHTokUint4:
1353 new(&type) TType(EbtUint, EvqTemporary, 4);
1354 break;
1355
1356 case EHTokBool:
1357 new(&type) TType(EbtBool);
1358 break;
1359 case EHTokBool1:
1360 new(&type) TType(EbtBool);
1361 type.makeVector();
1362 break;
John Kessenich87142c72016-03-12 20:24:24 -07001363 case EHTokBool2:
1364 new(&type) TType(EbtBool, EvqTemporary, 2);
1365 break;
1366 case EHTokBool3:
1367 new(&type) TType(EbtBool, EvqTemporary, 3);
1368 break;
1369 case EHTokBool4:
1370 new(&type) TType(EbtBool, EvqTemporary, 4);
1371 break;
1372
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001373 case EHTokHalf:
1374 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1375 break;
1376 case EHTokHalf1:
1377 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1378 type.makeVector();
1379 break;
1380 case EHTokHalf2:
1381 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1382 break;
1383 case EHTokHalf3:
1384 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1385 break;
1386 case EHTokHalf4:
1387 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1388 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001389
steve-lunarg3226b082016-10-26 19:18:55 -06001390 case EHTokMin16float:
1391 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1392 break;
1393 case EHTokMin16float1:
1394 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1395 type.makeVector();
1396 break;
1397 case EHTokMin16float2:
1398 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1399 break;
1400 case EHTokMin16float3:
1401 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1402 break;
1403 case EHTokMin16float4:
1404 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1405 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001406
steve-lunarg3226b082016-10-26 19:18:55 -06001407 case EHTokMin10float:
1408 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1409 break;
1410 case EHTokMin10float1:
1411 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1412 type.makeVector();
1413 break;
1414 case EHTokMin10float2:
1415 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1416 break;
1417 case EHTokMin10float3:
1418 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1419 break;
1420 case EHTokMin10float4:
1421 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1422 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001423
steve-lunarg3226b082016-10-26 19:18:55 -06001424 case EHTokMin16int:
1425 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1426 break;
1427 case EHTokMin16int1:
1428 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1429 type.makeVector();
1430 break;
1431 case EHTokMin16int2:
1432 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1433 break;
1434 case EHTokMin16int3:
1435 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1436 break;
1437 case EHTokMin16int4:
1438 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1439 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001440
steve-lunarg3226b082016-10-26 19:18:55 -06001441 case EHTokMin12int:
1442 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1443 break;
1444 case EHTokMin12int1:
1445 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1446 type.makeVector();
1447 break;
1448 case EHTokMin12int2:
1449 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1450 break;
1451 case EHTokMin12int3:
1452 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1453 break;
1454 case EHTokMin12int4:
1455 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1456 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001457
steve-lunarg3226b082016-10-26 19:18:55 -06001458 case EHTokMin16uint:
1459 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1460 break;
1461 case EHTokMin16uint1:
1462 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1463 type.makeVector();
1464 break;
1465 case EHTokMin16uint2:
1466 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1467 break;
1468 case EHTokMin16uint3:
1469 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1470 break;
1471 case EHTokMin16uint4:
1472 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1473 break;
1474
John Kessenich0133c122016-05-20 12:17:26 -06001475 case EHTokInt1x1:
1476 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1477 break;
1478 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001479 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001480 break;
1481 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001482 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001483 break;
1484 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001485 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001486 break;
1487 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001488 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001489 break;
1490 case EHTokInt2x2:
1491 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1492 break;
1493 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001494 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001495 break;
1496 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001497 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001498 break;
1499 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001500 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001501 break;
1502 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001503 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001504 break;
1505 case EHTokInt3x3:
1506 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1507 break;
1508 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001509 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001510 break;
1511 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001512 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001513 break;
1514 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001515 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001516 break;
1517 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001518 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001519 break;
1520 case EHTokInt4x4:
1521 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1522 break;
1523
John Kessenich71351de2016-06-08 12:50:56 -06001524 case EHTokUint1x1:
1525 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1526 break;
1527 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001528 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001529 break;
1530 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001531 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001532 break;
1533 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001534 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001535 break;
1536 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001537 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001538 break;
1539 case EHTokUint2x2:
1540 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1541 break;
1542 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001543 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001544 break;
1545 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001546 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001547 break;
1548 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001549 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001550 break;
1551 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001552 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001553 break;
1554 case EHTokUint3x3:
1555 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1556 break;
1557 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001558 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001559 break;
1560 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001561 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001562 break;
1563 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001564 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001565 break;
1566 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001567 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001568 break;
1569 case EHTokUint4x4:
1570 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1571 break;
1572
1573 case EHTokBool1x1:
1574 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1575 break;
1576 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001577 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001578 break;
1579 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001580 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001581 break;
1582 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001583 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001584 break;
1585 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001586 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001587 break;
1588 case EHTokBool2x2:
1589 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1590 break;
1591 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001592 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001593 break;
1594 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001595 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001596 break;
1597 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001598 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001599 break;
1600 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001601 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001602 break;
1603 case EHTokBool3x3:
1604 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1605 break;
1606 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001607 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001608 break;
1609 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001610 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001611 break;
1612 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001613 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001614 break;
1615 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001616 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001617 break;
1618 case EHTokBool4x4:
1619 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1620 break;
1621
John Kessenich0133c122016-05-20 12:17:26 -06001622 case EHTokFloat1x1:
1623 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1624 break;
1625 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001626 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001627 break;
1628 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001629 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001630 break;
1631 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001632 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001633 break;
1634 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001635 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001636 break;
John Kessenich87142c72016-03-12 20:24:24 -07001637 case EHTokFloat2x2:
1638 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1639 break;
1640 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001641 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001642 break;
1643 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001644 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001645 break;
John Kessenich0133c122016-05-20 12:17:26 -06001646 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001647 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001648 break;
John Kessenich87142c72016-03-12 20:24:24 -07001649 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001650 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001651 break;
1652 case EHTokFloat3x3:
1653 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1654 break;
1655 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001656 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001657 break;
John Kessenich0133c122016-05-20 12:17:26 -06001658 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001659 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001660 break;
John Kessenich87142c72016-03-12 20:24:24 -07001661 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001662 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001663 break;
1664 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001665 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001666 break;
1667 case EHTokFloat4x4:
1668 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1669 break;
1670
John Kessenich0133c122016-05-20 12:17:26 -06001671 case EHTokDouble1x1:
1672 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1673 break;
1674 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001675 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001676 break;
1677 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001678 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001679 break;
1680 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001681 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001682 break;
1683 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001684 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001685 break;
1686 case EHTokDouble2x2:
1687 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1688 break;
1689 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001690 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001691 break;
1692 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001693 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001694 break;
1695 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001696 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001697 break;
1698 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001699 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001700 break;
1701 case EHTokDouble3x3:
1702 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1703 break;
1704 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001705 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001706 break;
1707 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001708 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001709 break;
1710 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001711 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001712 break;
1713 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001714 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001715 break;
1716 case EHTokDouble4x4:
1717 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1718 break;
1719
John Kessenich87142c72016-03-12 20:24:24 -07001720 default:
1721 return false;
1722 }
1723
1724 advanceToken();
1725
1726 return true;
1727}
1728
John Kesseniche6e74942016-06-11 16:43:14 -06001729// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001730// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1731// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07001732// | struct_type IDENTIFIER // use of previously declared struct type
John Kessenich3d157c52016-07-25 16:05:33 -06001733//
1734// struct_type
1735// : STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001736// | CLASS
John Kessenich3d157c52016-07-25 16:05:33 -06001737// | CBUFFER
1738// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001739//
1740bool HlslGrammar::acceptStruct(TType& type)
1741{
John Kessenichb804de62016-09-05 12:19:18 -06001742 // This storage qualifier will tell us whether it's an AST
1743 // block type or just a generic structure type.
1744 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001745
1746 // CBUFFER
1747 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001748 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001749 // TBUFFER
1750 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001751 storageQualifier = EvqBuffer;
John Kessenich27ffb292017-03-03 17:01:01 -07001752 // CLASS
John Kesseniche6e74942016-06-11 16:43:14 -06001753 // STRUCT
John Kessenich27ffb292017-03-03 17:01:01 -07001754 else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001755 return false;
1756
1757 // IDENTIFIER
1758 TString structName = "";
1759 if (peekTokenClass(EHTokIdentifier)) {
1760 structName = *token.string;
1761 advanceToken();
1762 }
1763
John Kessenich3d157c52016-07-25 16:05:33 -06001764 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001765 TQualifier postDeclQualifier;
1766 postDeclQualifier.clear();
John Kessenich854fe242017-03-02 14:30:59 -07001767 bool postDeclsFound = acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001768
John Kesseniche6e74942016-06-11 16:43:14 -06001769 // LEFT_BRACE
John Kessenich854fe242017-03-02 14:30:59 -07001770 // struct_type IDENTIFIER
John Kesseniche6e74942016-06-11 16:43:14 -06001771 if (! acceptTokenClass(EHTokLeftBrace)) {
John Kessenich854fe242017-03-02 14:30:59 -07001772 if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
1773 // struct_type IDENTIFIER
1774 return true;
1775 } else {
1776 expected("{");
1777 return false;
1778 }
John Kesseniche6e74942016-06-11 16:43:14 -06001779 }
1780
1781 // struct_declaration_list
1782 TTypeList* typeList;
1783 if (! acceptStructDeclarationList(typeList)) {
1784 expected("struct member declarations");
1785 return false;
1786 }
1787
1788 // RIGHT_BRACE
1789 if (! acceptTokenClass(EHTokRightBrace)) {
1790 expected("}");
1791 return false;
1792 }
1793
1794 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001795 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001796 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001797 else {
John Kessenich7735b942016-09-05 12:40:06 -06001798 postDeclQualifier.storage = storageQualifier;
1799 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001800 }
John Kesseniche6e74942016-06-11 16:43:14 -06001801
John Kessenich727b3742017-02-03 17:57:55 -07001802 parseContext.declareStruct(token.loc, structName, type);
John Kesseniche6e74942016-06-11 16:43:14 -06001803
1804 return true;
1805}
1806
steve-lunarg5da1f032017-02-12 17:50:28 -07001807// struct_buffer
1808// : APPENDSTRUCTUREDBUFFER
1809// | BYTEADDRESSBUFFER
1810// | CONSUMESTRUCTUREDBUFFER
1811// | RWBYTEADDRESSBUFFER
1812// | RWSTRUCTUREDBUFFER
1813// | STRUCTUREDBUFFER
1814bool HlslGrammar::acceptStructBufferType(TType& type)
1815{
1816 const EHlslTokenClass structBuffType = peek();
1817
1818 // TODO: globallycoherent
1819 bool hasTemplateType = true;
1820 bool readonly = false;
1821
1822 TStorageQualifier storage = EvqBuffer;
1823
1824 switch (structBuffType) {
1825 case EHTokAppendStructuredBuffer:
1826 unimplemented("AppendStructuredBuffer");
1827 return false;
1828 case EHTokByteAddressBuffer:
1829 hasTemplateType = false;
1830 readonly = true;
1831 break;
1832 case EHTokConsumeStructuredBuffer:
1833 unimplemented("ConsumeStructuredBuffer");
1834 return false;
1835 case EHTokRWByteAddressBuffer:
1836 hasTemplateType = false;
1837 break;
1838 case EHTokRWStructuredBuffer:
1839 break;
1840 case EHTokStructuredBuffer:
1841 readonly = true;
1842 break;
1843 default:
1844 return false; // not a structure buffer type
1845 }
1846
1847 advanceToken(); // consume the structure keyword
1848
1849 // type on which this StructedBuffer is templatized. E.g, StructedBuffer<MyStruct> ==> MyStruct
1850 TType* templateType = new TType;
1851
1852 if (hasTemplateType) {
1853 if (! acceptTokenClass(EHTokLeftAngle)) {
1854 expected("left angle bracket");
1855 return false;
1856 }
1857
1858 if (! acceptType(*templateType)) {
1859 expected("type");
1860 return false;
1861 }
1862 if (! acceptTokenClass(EHTokRightAngle)) {
1863 expected("right angle bracket");
1864 return false;
1865 }
1866 } else {
1867 // byte address buffers have no explicit type.
1868 TType uintType(EbtUint, storage);
1869 templateType->shallowCopy(uintType);
1870 }
1871
1872 // Create an unsized array out of that type.
1873 // TODO: does this work if it's already an array type?
1874 TArraySizes unsizedArray;
1875 unsizedArray.addInnerSize(UnsizedArraySize);
1876 templateType->newArraySizes(unsizedArray);
steve-lunarg40efe5c2017-03-06 12:01:44 -07001877 templateType->getQualifier().storage = storage;
steve-lunargdd8287a2017-02-23 18:04:12 -07001878
1879 // field name is canonical for all structbuffers
1880 templateType->setFieldName("@data");
steve-lunarg5da1f032017-02-12 17:50:28 -07001881
1882 // Create block type. TODO: hidden internal uint member when needed
steve-lunargdd8287a2017-02-23 18:04:12 -07001883
steve-lunarg5da1f032017-02-12 17:50:28 -07001884 TTypeList* blockStruct = new TTypeList;
1885 TTypeLoc member = { templateType, token.loc };
1886 blockStruct->push_back(member);
1887
steve-lunargdd8287a2017-02-23 18:04:12 -07001888 // This is the type of the buffer block (SSBO)
steve-lunarg5da1f032017-02-12 17:50:28 -07001889 TType blockType(blockStruct, "", templateType->getQualifier());
1890
steve-lunargdd8287a2017-02-23 18:04:12 -07001891 blockType.getQualifier().storage = storage;
1892 blockType.getQualifier().readonly = readonly;
1893
1894 // We may have created an equivalent type before, in which case we should use its
1895 // deep structure.
1896 parseContext.shareStructBufferType(blockType);
1897
steve-lunarg5da1f032017-02-12 17:50:28 -07001898 type.shallowCopy(blockType);
1899
1900 return true;
1901}
1902
John Kesseniche6e74942016-06-11 16:43:14 -06001903// struct_declaration_list
1904// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1905//
1906// struct_declaration
1907// : fully_specified_type struct_declarator COMMA struct_declarator ...
1908//
1909// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001910// : IDENTIFIER post_decls
1911// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001912//
1913bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1914{
1915 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001916 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001917
1918 do {
1919 // success on seeing the RIGHT_BRACE coming up
1920 if (peekTokenClass(EHTokRightBrace))
1921 return true;
1922
1923 // struct_declaration
1924
1925 // fully_specified_type
1926 TType memberType;
1927 if (! acceptFullySpecifiedType(memberType)) {
1928 expected("member type");
1929 return false;
1930 }
1931
1932 // struct_declarator COMMA struct_declarator ...
1933 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001934 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001935 expected("member name");
1936 return false;
1937 }
1938
1939 // add it to the list of members
1940 TTypeLoc member = { new TType(EbtVoid), token.loc };
1941 member.type->shallowCopy(memberType);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001942 member.type->setFieldName(*idToken.string);
John Kesseniche6e74942016-06-11 16:43:14 -06001943 typeList->push_back(member);
1944
John Kesseniche6e74942016-06-11 16:43:14 -06001945 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001946 TArraySizes* arraySizes = nullptr;
1947 acceptArraySpecifier(arraySizes);
1948 if (arraySizes)
1949 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001950
John Kessenich7735b942016-09-05 12:40:06 -06001951 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001952
John Kessenich18adbdb2017-02-02 15:16:20 -07001953 // EQUAL assignment_expression
1954 if (acceptTokenClass(EHTokAssign)) {
1955 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
1956 TIntermTyped* expressionNode = nullptr;
1957 if (! acceptAssignmentExpression(expressionNode)) {
1958 expected("initializer");
1959 return false;
1960 }
1961 }
1962
John Kesseniche6e74942016-06-11 16:43:14 -06001963 // success on seeing the SEMICOLON coming up
1964 if (peekTokenClass(EHTokSemicolon))
1965 break;
1966
1967 // COMMA
1968 if (! acceptTokenClass(EHTokComma)) {
1969 expected(",");
1970 return false;
1971 }
1972
1973 } while (true);
1974
1975 // SEMI_COLON
1976 if (! acceptTokenClass(EHTokSemicolon)) {
1977 expected(";");
1978 return false;
1979 }
1980
1981 } while (true);
1982}
1983
John Kessenich5f934b02016-03-13 17:58:25 -06001984// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001985// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001986// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001987//
1988bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1989{
John Kessenich078d7f22016-03-14 10:02:11 -06001990 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001991 if (! acceptTokenClass(EHTokLeftParen))
1992 return false;
1993
John Kessenich71351de2016-06-08 12:50:56 -06001994 // VOID RIGHT_PAREN
1995 if (! acceptTokenClass(EHTokVoid)) {
1996 do {
1997 // parameter_declaration
1998 if (! acceptParameterDeclaration(function))
1999 break;
John Kessenich5f934b02016-03-13 17:58:25 -06002000
John Kessenich71351de2016-06-08 12:50:56 -06002001 // COMMA
2002 if (! acceptTokenClass(EHTokComma))
2003 break;
2004 } while (true);
2005 }
John Kessenich5f934b02016-03-13 17:58:25 -06002006
John Kessenich078d7f22016-03-14 10:02:11 -06002007 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06002008 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002009 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06002010 return false;
2011 }
2012
2013 return true;
2014}
2015
steve-lunarg26d31452016-12-23 18:56:57 -07002016// default_parameter_declaration
2017// : EQUAL conditional_expression
2018// : EQUAL initializer
2019bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2020{
2021 node = nullptr;
2022
2023 // Valid not to have a default_parameter_declaration
2024 if (!acceptTokenClass(EHTokAssign))
2025 return true;
2026
2027 if (!acceptConditionalExpression(node)) {
2028 if (!acceptInitializer(node))
2029 return false;
2030
2031 // For initializer lists, we have to const-fold into a constructor for the type, so build
2032 // that.
2033 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
2034 if (constructor == nullptr) // cannot construct
2035 return false;
2036
2037 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07002038 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07002039 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07002040
steve-lunarg26d31452016-12-23 18:56:57 -07002041 node = parseContext.handleFunctionCall(token.loc, constructor, node);
2042 }
2043
2044 // If this is simply a constant, we can use it directly.
2045 if (node->getAsConstantUnion())
2046 return true;
2047
2048 // Otherwise, it has to be const-foldable.
2049 TIntermTyped* origNode = node;
2050
2051 node = intermediate.fold(node->getAsAggregate());
2052
2053 if (node != nullptr && origNode != node)
2054 return true;
2055
2056 parseContext.error(token.loc, "invalid default parameter value", "", "");
2057
2058 return false;
2059}
2060
John Kessenich5f934b02016-03-13 17:58:25 -06002061// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07002062// : fully_specified_type post_decls [ = default_parameter_declaration ]
2063// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06002064//
2065bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2066{
2067 // fully_specified_type
2068 TType* type = new TType;
2069 if (! acceptFullySpecifiedType(*type))
2070 return false;
2071
2072 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06002073 HlslToken idToken;
2074 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06002075
John Kessenich19b92ff2016-06-19 11:50:34 -06002076 // array_specifier
2077 TArraySizes* arraySizes = nullptr;
2078 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002079 if (arraySizes) {
2080 if (arraySizes->isImplicit()) {
2081 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
2082 return false;
2083 }
2084
John Kessenich19b92ff2016-06-19 11:50:34 -06002085 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06002086 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002087
2088 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06002089 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06002090
steve-lunarg26d31452016-12-23 18:56:57 -07002091 TIntermTyped* defaultValue;
2092 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2093 return false;
2094
John Kessenich5aa59e22016-06-17 15:50:47 -06002095 parseContext.paramFix(*type);
2096
steve-lunarg26d31452016-12-23 18:56:57 -07002097 // If any prior parameters have default values, all the parameters after that must as well.
2098 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2099 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2100 return false;
2101 }
2102
2103 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06002104 function.addParameter(param);
2105
2106 return true;
2107}
2108
2109// Do the work to create the function definition in addition to
2110// parsing the body (compound_statement).
John Kessenich02467d82017-01-19 15:41:47 -07002111bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, TIntermNode*& node2, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06002112{
John Kessenicha3051662016-09-02 19:13:36 -06002113 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06002114 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06002115
John Kessenich077e0522016-06-09 02:02:17 -06002116 // This does a pushScope()
John Kessenich02467d82017-01-19 15:41:47 -07002117 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
John Kessenich5f934b02016-03-13 17:58:25 -06002118
2119 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002120 TIntermNode* functionBody = nullptr;
John Kessenich02467d82017-01-19 15:41:47 -07002121 if (! acceptCompoundStatement(functionBody))
2122 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002123
John Kessenich02467d82017-01-19 15:41:47 -07002124 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
2125
2126 return true;
John Kessenich5f934b02016-03-13 17:58:25 -06002127}
2128
John Kessenich0d2b6de2016-06-05 11:23:11 -06002129// Accept an expression with parenthesis around it, where
2130// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002131// syntactically required ones like in "if ( expression )".
2132//
2133// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06002134//
2135// Note this one is not set up to be speculative; as it gives
2136// errors if not found.
2137//
2138bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2139{
2140 // LEFT_PAREN
2141 if (! acceptTokenClass(EHTokLeftParen))
2142 expected("(");
2143
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002144 bool decl = false;
2145 TIntermNode* declNode = nullptr;
2146 decl = acceptControlDeclaration(declNode);
2147 if (decl) {
2148 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2149 expected("initialized declaration");
2150 return false;
2151 } else
2152 expression = declNode->getAsTyped();
2153 } else {
2154 // no declaration
2155 if (! acceptExpression(expression)) {
2156 expected("expression");
2157 return false;
2158 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002159 }
2160
2161 // RIGHT_PAREN
2162 if (! acceptTokenClass(EHTokRightParen))
2163 expected(")");
2164
2165 return true;
2166}
2167
John Kessenich34fb0362016-05-03 23:17:20 -06002168// The top-level full expression recognizer.
2169//
John Kessenich87142c72016-03-12 20:24:24 -07002170// expression
John Kessenich34fb0362016-05-03 23:17:20 -06002171// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07002172//
2173bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2174{
LoopDawgef764a22016-06-03 09:17:51 -06002175 node = nullptr;
2176
John Kessenich34fb0362016-05-03 23:17:20 -06002177 // assignment_expression
2178 if (! acceptAssignmentExpression(node))
2179 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002180
John Kessenich34fb0362016-05-03 23:17:20 -06002181 if (! peekTokenClass(EHTokComma))
2182 return true;
2183
2184 do {
2185 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06002186 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06002187 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06002188
John Kessenich34fb0362016-05-03 23:17:20 -06002189 // ... assignment_expression
2190 TIntermTyped* rightNode = nullptr;
2191 if (! acceptAssignmentExpression(rightNode)) {
2192 expected("assignment expression");
2193 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002194 }
2195
John Kessenich34fb0362016-05-03 23:17:20 -06002196 node = intermediate.addComma(node, rightNode, loc);
2197
2198 if (! peekTokenClass(EHTokComma))
2199 return true;
2200 } while (true);
2201}
2202
John Kessenich07354242016-07-01 19:58:06 -06002203// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002204// : LEFT_BRACE RIGHT_BRACE
2205// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002206//
2207// initializer_list
2208// : assignment_expression COMMA assignment_expression COMMA ...
2209//
2210bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2211{
2212 // LEFT_BRACE
2213 if (! acceptTokenClass(EHTokLeftBrace))
2214 return false;
2215
John Kessenich98ad4852016-11-27 17:39:07 -07002216 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002217 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002218 if (acceptTokenClass(EHTokRightBrace)) {
2219 // a zero-length initializer list
2220 node = intermediate.makeAggregate(loc);
2221 return true;
2222 }
2223
2224 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002225 node = nullptr;
2226 do {
2227 // assignment_expression
2228 TIntermTyped* expr;
2229 if (! acceptAssignmentExpression(expr)) {
2230 expected("assignment expression in initializer list");
2231 return false;
2232 }
2233 node = intermediate.growAggregate(node, expr, loc);
2234
2235 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002236 if (acceptTokenClass(EHTokComma)) {
2237 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2238 return true;
John Kessenich07354242016-07-01 19:58:06 -06002239 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002240 }
John Kessenich07354242016-07-01 19:58:06 -06002241
2242 // RIGHT_BRACE
2243 if (acceptTokenClass(EHTokRightBrace))
2244 return true;
2245
2246 expected(", or }");
2247 return false;
2248 } while (true);
2249}
2250
John Kessenich34fb0362016-05-03 23:17:20 -06002251// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002252// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002253//
2254// a op (b op (c op d))
2255//
2256// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002257// : initializer
2258// | conditional_expression
2259// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002260//
2261bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2262{
John Kessenich07354242016-07-01 19:58:06 -06002263 // initializer
2264 if (peekTokenClass(EHTokLeftBrace)) {
2265 if (acceptInitializer(node))
2266 return true;
2267
2268 expected("initializer");
2269 return false;
2270 }
2271
John Kessenich00957f82016-07-27 10:39:57 -06002272 // conditional_expression
2273 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002274 return false;
2275
John Kessenich07354242016-07-01 19:58:06 -06002276 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002277 TOperator assignOp = HlslOpMap::assignment(peek());
2278 if (assignOp == EOpNull)
2279 return true;
2280
John Kessenich00957f82016-07-27 10:39:57 -06002281 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002282 TSourceLoc loc = token.loc;
2283 advanceToken();
2284
John Kessenich00957f82016-07-27 10:39:57 -06002285 // conditional_expression assign_op conditional_expression ...
2286 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002287 // gets the right-to-left associativity.
2288 TIntermTyped* rightNode = nullptr;
2289 if (! acceptAssignmentExpression(rightNode)) {
2290 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002291 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002292 }
2293
John Kessenichd21baed2016-09-16 03:05:12 -06002294 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002295 node = parseContext.handleLvalue(loc, "assign", node);
2296
John Kessenichfea226b2016-07-28 17:53:56 -06002297 if (node == nullptr) {
2298 parseContext.error(loc, "could not create assignment", "", "");
2299 return false;
2300 }
John Kessenich34fb0362016-05-03 23:17:20 -06002301
2302 if (! peekTokenClass(EHTokComma))
2303 return true;
2304
2305 return true;
2306}
2307
John Kessenich00957f82016-07-27 10:39:57 -06002308// Accept a conditional expression, which associates right-to-left,
2309// accomplished by the "true" expression calling down to lower
2310// precedence levels than this level.
2311//
2312// conditional_expression
2313// : binary_expression
2314// | binary_expression QUESTION expression COLON assignment_expression
2315//
2316bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2317{
2318 // binary_expression
2319 if (! acceptBinaryExpression(node, PlLogicalOr))
2320 return false;
2321
2322 if (! acceptTokenClass(EHTokQuestion))
2323 return true;
2324
2325 TIntermTyped* trueNode = nullptr;
2326 if (! acceptExpression(trueNode)) {
2327 expected("expression after ?");
2328 return false;
2329 }
2330 TSourceLoc loc = token.loc;
2331
2332 if (! acceptTokenClass(EHTokColon)) {
2333 expected(":");
2334 return false;
2335 }
2336
2337 TIntermTyped* falseNode = nullptr;
2338 if (! acceptAssignmentExpression(falseNode)) {
2339 expected("expression after :");
2340 return false;
2341 }
2342
2343 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2344
2345 return true;
2346}
2347
John Kessenich34fb0362016-05-03 23:17:20 -06002348// Accept a binary expression, for binary operations that
2349// associate left-to-right. This is, it is implicit, for example
2350//
2351// ((a op b) op c) op d
2352//
2353// binary_expression
2354// : expression op expression op expression ...
2355//
2356// where 'expression' is the next higher level in precedence.
2357//
2358bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2359{
2360 if (precedenceLevel > PlMul)
2361 return acceptUnaryExpression(node);
2362
2363 // assignment_expression
2364 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2365 return false;
2366
John Kessenich34fb0362016-05-03 23:17:20 -06002367 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002368 TOperator op = HlslOpMap::binary(peek());
2369 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2370 if (tokenLevel < precedenceLevel)
2371 return true;
2372
John Kessenich34fb0362016-05-03 23:17:20 -06002373 // ... op
2374 TSourceLoc loc = token.loc;
2375 advanceToken();
2376
2377 // ... expression
2378 TIntermTyped* rightNode = nullptr;
2379 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2380 expected("expression");
2381 return false;
2382 }
2383
2384 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002385 if (node == nullptr) {
2386 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2387 return false;
2388 }
John Kessenich34fb0362016-05-03 23:17:20 -06002389 } while (true);
2390}
2391
2392// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002393// : (type) unary_expression
2394// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002395// | - unary_expression
2396// | ! unary_expression
2397// | ~ unary_expression
2398// | ++ unary_expression
2399// | -- unary_expression
2400// | postfix_expression
2401//
2402bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2403{
John Kessenich1cc1a282016-06-03 16:55:49 -06002404 // (type) unary_expression
2405 // Have to look two steps ahead, because this could be, e.g., a
2406 // postfix_expression instead, since that also starts with at "(".
2407 if (acceptTokenClass(EHTokLeftParen)) {
2408 TType castType;
2409 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002410 if (acceptTokenClass(EHTokRightParen)) {
2411 // We've matched "(type)" now, get the expression to cast
2412 TSourceLoc loc = token.loc;
2413 if (! acceptUnaryExpression(node))
2414 return false;
2415
2416 // Hook it up like a constructor
2417 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2418 if (constructorFunction == nullptr) {
2419 expected("type that can be constructed");
2420 return false;
2421 }
2422 TIntermTyped* arguments = nullptr;
2423 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2424 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2425
2426 return true;
2427 } else {
2428 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2429 // the '(int' part. We must back up twice.
2430 recedeToken();
2431 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002432 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002433 } else {
2434 // This isn't a type cast, but it still started "(", so if it is a
2435 // unary expression, it can only be a postfix_expression, so try that.
2436 // Back it up first.
2437 recedeToken();
2438 return acceptPostfixExpression(node);
2439 }
2440 }
2441
2442 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002443 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002444
John Kessenich1cc1a282016-06-03 16:55:49 -06002445 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002446 if (unaryOp == EOpNull)
2447 return acceptPostfixExpression(node);
2448
2449 // op unary_expression
2450 TSourceLoc loc = token.loc;
2451 advanceToken();
2452 if (! acceptUnaryExpression(node))
2453 return false;
2454
2455 // + is a no-op
2456 if (unaryOp == EOpAdd)
2457 return true;
2458
2459 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002460
2461 // These unary ops require lvalues
2462 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2463 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002464
2465 return node != nullptr;
2466}
2467
2468// postfix_expression
2469// : LEFT_PAREN expression RIGHT_PAREN
2470// | literal
2471// | constructor
2472// | identifier
2473// | function_call
2474// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2475// | postfix_expression DOT IDENTIFIER
2476// | postfix_expression INC_OP
2477// | postfix_expression DEC_OP
2478//
2479bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2480{
2481 // Not implemented as self-recursive:
2482 // The logical "right recursion" is done with an loop at the end
2483
2484 // idToken will pick up either a variable or a function name in a function call
2485 HlslToken idToken;
2486
John Kessenich21472ae2016-06-04 11:46:33 -06002487 // Find something before the postfix operations, as they can't operate
2488 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002489 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002490 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002491 if (! acceptExpression(node)) {
2492 expected("expression");
2493 return false;
2494 }
2495 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002496 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002497 return false;
2498 }
John Kessenich34fb0362016-05-03 23:17:20 -06002499 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002500 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002501 } else if (acceptConstructor(node)) {
2502 // constructor (nothing else to do yet)
2503 } else if (acceptIdentifier(idToken)) {
2504 // identifier or function_call name
2505 if (! peekTokenClass(EHTokLeftParen)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -07002506 node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002507 } else if (acceptFunctionCall(idToken, node)) {
2508 // function_call (nothing else to do yet)
2509 } else {
2510 expected("function call arguments");
2511 return false;
2512 }
John Kessenich21472ae2016-06-04 11:46:33 -06002513 } else {
2514 // nothing found, can't post operate
2515 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002516 }
2517
steve-lunarga2b01a02016-11-28 17:09:54 -07002518 // This is to guarantee we do this no matter how we get out of the stack frame.
2519 // This way there's no bug if an early return forgets to do it.
2520 struct tFinalize {
2521 tFinalize(HlslParseContext& p) : parseContext(p) { }
2522 ~tFinalize() { parseContext.finalizeFlattening(); }
John Kessenichf8d0d8c2017-02-08 17:31:03 -07002523 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002524 private:
John Kessenichefeefd92017-03-01 13:12:26 -07002525 const tFinalize& operator=(const tFinalize& f) { return *this; }
2526 tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
steve-lunarga2b01a02016-11-28 17:09:54 -07002527 } finalize(parseContext);
2528
2529 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2530 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2531 // level: hence the init and finalize. Even though in practice these must be
2532 // constants, they are parsed no matter what.
2533 parseContext.initFlattening();
2534
John Kessenich21472ae2016-06-04 11:46:33 -06002535 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002536 do {
2537 TSourceLoc loc = token.loc;
2538 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002539
John Kessenich34fb0362016-05-03 23:17:20 -06002540 // Consume only a valid post-unary operator, otherwise we are done.
2541 switch (postOp) {
2542 case EOpIndexDirectStruct:
2543 case EOpIndexIndirect:
2544 case EOpPostIncrement:
2545 case EOpPostDecrement:
2546 advanceToken();
2547 break;
2548 default:
2549 return true;
2550 }
John Kessenich87142c72016-03-12 20:24:24 -07002551
John Kessenich34fb0362016-05-03 23:17:20 -06002552 // We have a valid post-unary operator, process it.
2553 switch (postOp) {
2554 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002555 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002556 // DOT IDENTIFIER
2557 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002558 HlslToken field;
2559 if (! acceptIdentifier(field)) {
2560 expected("swizzle or member");
2561 return false;
2562 }
LoopDawg4886f692016-06-29 10:58:58 -06002563
2564 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002565 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002566
2567 // 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 -07002568 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002569 if (! acceptFunctionCall(field, node, base)) {
2570 expected("function parameters");
2571 return false;
2572 }
2573 }
2574
John Kessenich34fb0362016-05-03 23:17:20 -06002575 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002576 }
John Kessenich34fb0362016-05-03 23:17:20 -06002577 case EOpIndexIndirect:
2578 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002579 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002580 TIntermTyped* indexNode = nullptr;
2581 if (! acceptExpression(indexNode) ||
2582 ! peekTokenClass(EHTokRightBracket)) {
2583 expected("expression followed by ']'");
2584 return false;
2585 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002586 advanceToken();
2587 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2588 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002589 }
2590 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002591 // INC_OP
2592 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002593 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002594 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002595 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002596 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002597 break;
2598 default:
2599 assert(0);
2600 break;
2601 }
2602 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002603}
2604
John Kessenichd016be12016-03-13 11:24:20 -06002605// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002606// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002607//
2608bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2609{
2610 // type
2611 TType type;
2612 if (acceptType(type)) {
2613 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2614 if (constructorFunction == nullptr)
2615 return false;
2616
2617 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002618 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002619 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002620 // It's possible this is a type keyword used as an identifier. Put the token back
2621 // for later use.
2622 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002623 return false;
2624 }
2625
2626 // hook it up
2627 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2628
2629 return true;
2630 }
2631
2632 return false;
2633}
2634
John Kessenich34fb0362016-05-03 23:17:20 -06002635// The function_call identifier was already recognized, and passed in as idToken.
2636//
2637// function_call
2638// : [idToken] arguments
2639//
LoopDawg4886f692016-06-29 10:58:58 -06002640bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002641{
John Kessenich4678ca92016-05-13 09:33:42 -06002642 // arguments
2643 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2644 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002645
2646 // methods have an implicit first argument of the calling object.
2647 if (base != nullptr)
2648 parseContext.handleFunctionArgument(function, arguments, base);
2649
John Kessenich4678ca92016-05-13 09:33:42 -06002650 if (! acceptArguments(function, arguments))
2651 return false;
2652
2653 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2654
2655 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002656}
2657
John Kessenich87142c72016-03-12 20:24:24 -07002658// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002659// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002660//
John Kessenichd016be12016-03-13 11:24:20 -06002661// The arguments are pushed onto the 'function' argument list and
2662// onto the 'arguments' aggregate.
2663//
John Kessenich4678ca92016-05-13 09:33:42 -06002664bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002665{
John Kessenich078d7f22016-03-14 10:02:11 -06002666 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002667 if (! acceptTokenClass(EHTokLeftParen))
2668 return false;
2669
2670 do {
John Kessenichd016be12016-03-13 11:24:20 -06002671 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002672 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002673 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002674 break;
John Kessenichd016be12016-03-13 11:24:20 -06002675
2676 // hook it up
2677 parseContext.handleFunctionArgument(function, arguments, arg);
2678
John Kessenich078d7f22016-03-14 10:02:11 -06002679 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002680 if (! acceptTokenClass(EHTokComma))
2681 break;
2682 } while (true);
2683
John Kessenich078d7f22016-03-14 10:02:11 -06002684 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002685 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002686 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002687 return false;
2688 }
2689
2690 return true;
2691}
2692
2693bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2694{
2695 switch (token.tokenClass) {
2696 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002697 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002698 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002699 case EHTokUintConstant:
2700 node = intermediate.addConstantUnion(token.u, token.loc, true);
2701 break;
John Kessenich87142c72016-03-12 20:24:24 -07002702 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002703 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002704 break;
2705 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002706 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002707 break;
2708 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002709 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002710 break;
John Kessenich86f71382016-09-19 20:23:18 -06002711 case EHTokStringConstant:
steve-lunarg858c9282017-01-07 08:54:10 -07002712 node = intermediate.addConstantUnion(token.string, token.loc, true);
John Kessenich86f71382016-09-19 20:23:18 -06002713 break;
John Kessenich87142c72016-03-12 20:24:24 -07002714
2715 default:
2716 return false;
2717 }
2718
2719 advanceToken();
2720
2721 return true;
2722}
2723
John Kessenich5f934b02016-03-13 17:58:25 -06002724// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002725// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002726//
John Kessenich21472ae2016-06-04 11:46:33 -06002727bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002728{
John Kessenich21472ae2016-06-04 11:46:33 -06002729 TIntermAggregate* compoundStatement = nullptr;
2730
John Kessenich34fb0362016-05-03 23:17:20 -06002731 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002732 if (! acceptTokenClass(EHTokLeftBrace))
2733 return false;
2734
2735 // statement statement ...
2736 TIntermNode* statement = nullptr;
2737 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002738 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2739 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2740 branch->getFlowOp() == EOpDefault)) {
2741 // hook up individual subsequences within a switch statement
2742 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2743 compoundStatement = nullptr;
2744 } else {
2745 // hook it up to the growing compound statement
2746 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2747 }
John Kessenich5f934b02016-03-13 17:58:25 -06002748 }
John Kessenich34fb0362016-05-03 23:17:20 -06002749 if (compoundStatement)
2750 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002751
John Kessenich21472ae2016-06-04 11:46:33 -06002752 retStatement = compoundStatement;
2753
John Kessenich34fb0362016-05-03 23:17:20 -06002754 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002755 return acceptTokenClass(EHTokRightBrace);
2756}
2757
John Kessenich0d2b6de2016-06-05 11:23:11 -06002758bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2759{
2760 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002761 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002762 parseContext.popScope();
2763
2764 return result;
2765}
2766
John Kessenich077e0522016-06-09 02:02:17 -06002767bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002768{
John Kessenich077e0522016-06-09 02:02:17 -06002769 parseContext.pushScope();
2770 bool result = acceptCompoundStatement(statement);
2771 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002772
2773 return result;
2774}
2775
John Kessenich5f934b02016-03-13 17:58:25 -06002776// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002777// : attributes attributed_statement
2778//
2779// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002780// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002781// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002782// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002783// | declaration_statement
2784// | selection_statement
2785// | switch_statement
2786// | case_label
2787// | iteration_statement
2788// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002789//
2790bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2791{
John Kessenich21472ae2016-06-04 11:46:33 -06002792 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002793
John Kessenich21472ae2016-06-04 11:46:33 -06002794 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002795 TAttributeMap attributes;
2796 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002797
John Kessenich21472ae2016-06-04 11:46:33 -06002798 // attributed_statement
2799 switch (peek()) {
2800 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002801 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002802
John Kessenich21472ae2016-06-04 11:46:33 -06002803 case EHTokIf:
2804 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002805
John Kessenich21472ae2016-06-04 11:46:33 -06002806 case EHTokSwitch:
2807 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002808
John Kessenich21472ae2016-06-04 11:46:33 -06002809 case EHTokFor:
2810 case EHTokDo:
2811 case EHTokWhile:
2812 return acceptIterationStatement(statement);
2813
2814 case EHTokContinue:
2815 case EHTokBreak:
2816 case EHTokDiscard:
2817 case EHTokReturn:
2818 return acceptJumpStatement(statement);
2819
2820 case EHTokCase:
2821 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002822 case EHTokDefault:
2823 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002824
2825 case EHTokSemicolon:
2826 return acceptTokenClass(EHTokSemicolon);
2827
2828 case EHTokRightBrace:
2829 // Performance: not strictly necessary, but stops a bunch of hunting early,
2830 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002831 return false;
2832
John Kessenich21472ae2016-06-04 11:46:33 -06002833 default:
2834 {
2835 // declaration
2836 if (acceptDeclaration(statement))
2837 return true;
2838
2839 // expression
2840 TIntermTyped* node;
2841 if (acceptExpression(node))
2842 statement = node;
2843 else
2844 return false;
2845
2846 // SEMICOLON (following an expression)
2847 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002848 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002849 return false;
2850 }
2851 }
2852 }
2853
John Kessenich5f934b02016-03-13 17:58:25 -06002854 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002855}
2856
John Kessenich21472ae2016-06-04 11:46:33 -06002857// attributes
2858// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2859//
2860// attribute:
2861// : UNROLL
2862// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2863// | FASTOPT
2864// | ALLOW_UAV_CONDITION
2865// | BRANCH
2866// | FLATTEN
2867// | FORCECASE
2868// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002869// | DOMAIN
2870// | EARLYDEPTHSTENCIL
2871// | INSTANCE
2872// | MAXTESSFACTOR
2873// | OUTPUTCONTROLPOINTS
2874// | OUTPUTTOPOLOGY
2875// | PARTITIONING
2876// | PATCHCONSTANTFUNC
2877// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002878//
steve-lunarg1868b142016-10-20 13:07:10 -06002879void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002880{
steve-lunarg1868b142016-10-20 13:07:10 -06002881 // For now, accept the [ XXX(X) ] syntax, but drop all but
2882 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002883 // TODO: subset to correct set? Pass on?
2884 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002885 HlslToken idToken;
2886
John Kessenich0d2b6de2016-06-05 11:23:11 -06002887 // LEFT_BRACKET?
2888 if (! acceptTokenClass(EHTokLeftBracket))
2889 return;
2890
2891 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002892 if (acceptIdentifier(idToken)) {
2893 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002894 } else if (! peekTokenClass(EHTokRightBracket)) {
2895 expected("identifier");
2896 advanceToken();
2897 }
2898
steve-lunarga22f7db2016-11-11 08:17:44 -07002899 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002900
2901 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002902 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002903 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002904
John Kessenich0d2b6de2016-06-05 11:23:11 -06002905 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002906 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07002907
steve-lunarga22f7db2016-11-11 08:17:44 -07002908 while (acceptAssignmentExpression(node)) {
2909 expectingExpression = false;
2910 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002911 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002912 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002913 }
2914
steve-lunarga22f7db2016-11-11 08:17:44 -07002915 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002916 if (! acceptTokenClass(EHTokRightParen))
2917 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002918
2919 // Error for partial or missing expression
2920 if (expectingExpression || expressions->getSequence().empty())
2921 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002922 }
2923
2924 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002925 if (!acceptTokenClass(EHTokRightBracket)) {
2926 expected("]");
2927 return;
2928 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002929
steve-lunarg1868b142016-10-20 13:07:10 -06002930 // Add any values we found into the attribute map. This accepts
2931 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002932 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002933 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002934}
2935
John Kessenich0d2b6de2016-06-05 11:23:11 -06002936// selection_statement
2937// : IF LEFT_PAREN expression RIGHT_PAREN statement
2938// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2939//
John Kessenich21472ae2016-06-04 11:46:33 -06002940bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2941{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002942 TSourceLoc loc = token.loc;
2943
2944 // IF
2945 if (! acceptTokenClass(EHTokIf))
2946 return false;
2947
2948 // so that something declared in the condition is scoped to the lifetimes
2949 // of the then-else statements
2950 parseContext.pushScope();
2951
2952 // LEFT_PAREN expression RIGHT_PAREN
2953 TIntermTyped* condition;
2954 if (! acceptParenExpression(condition))
2955 return false;
2956
2957 // create the child statements
2958 TIntermNodePair thenElse = { nullptr, nullptr };
2959
2960 // then statement
2961 if (! acceptScopedStatement(thenElse.node1)) {
2962 expected("then statement");
2963 return false;
2964 }
2965
2966 // ELSE
2967 if (acceptTokenClass(EHTokElse)) {
2968 // else statement
2969 if (! acceptScopedStatement(thenElse.node2)) {
2970 expected("else statement");
2971 return false;
2972 }
2973 }
2974
2975 // Put the pieces together
2976 statement = intermediate.addSelection(condition, thenElse, loc);
2977 parseContext.popScope();
2978
2979 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002980}
2981
John Kessenichd02dc5d2016-07-01 00:04:11 -06002982// switch_statement
2983// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2984//
John Kessenich21472ae2016-06-04 11:46:33 -06002985bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2986{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002987 // SWITCH
2988 TSourceLoc loc = token.loc;
2989 if (! acceptTokenClass(EHTokSwitch))
2990 return false;
2991
2992 // LEFT_PAREN expression RIGHT_PAREN
2993 parseContext.pushScope();
2994 TIntermTyped* switchExpression;
2995 if (! acceptParenExpression(switchExpression)) {
2996 parseContext.popScope();
2997 return false;
2998 }
2999
3000 // compound_statement
3001 parseContext.pushSwitchSequence(new TIntermSequence);
3002 bool statementOkay = acceptCompoundStatement(statement);
3003 if (statementOkay)
3004 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
3005
3006 parseContext.popSwitchSequence();
3007 parseContext.popScope();
3008
3009 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06003010}
3011
John Kessenich119f8f62016-06-05 15:44:07 -06003012// iteration_statement
3013// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3014// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3015// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3016//
3017// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06003018bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
3019{
John Kessenich119f8f62016-06-05 15:44:07 -06003020 TSourceLoc loc = token.loc;
3021 TIntermTyped* condition = nullptr;
3022
3023 EHlslTokenClass loop = peek();
3024 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3025
3026 // WHILE or DO or FOR
3027 advanceToken();
3028
3029 switch (loop) {
3030 case EHTokWhile:
3031 // so that something declared in the condition is scoped to the lifetime
3032 // of the while sub-statement
3033 parseContext.pushScope();
3034 parseContext.nestLooping();
3035
3036 // LEFT_PAREN condition RIGHT_PAREN
3037 if (! acceptParenExpression(condition))
3038 return false;
3039
3040 // statement
3041 if (! acceptScopedStatement(statement)) {
3042 expected("while sub-statement");
3043 return false;
3044 }
3045
3046 parseContext.unnestLooping();
3047 parseContext.popScope();
3048
3049 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
3050
3051 return true;
3052
3053 case EHTokDo:
3054 parseContext.nestLooping();
3055
3056 if (! acceptTokenClass(EHTokLeftBrace))
3057 expected("{");
3058
3059 // statement
3060 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
3061 expected("do sub-statement");
3062 return false;
3063 }
3064
3065 if (! acceptTokenClass(EHTokRightBrace))
3066 expected("}");
3067
3068 // WHILE
3069 if (! acceptTokenClass(EHTokWhile)) {
3070 expected("while");
3071 return false;
3072 }
3073
3074 // LEFT_PAREN condition RIGHT_PAREN
3075 TIntermTyped* condition;
3076 if (! acceptParenExpression(condition))
3077 return false;
3078
3079 if (! acceptTokenClass(EHTokSemicolon))
3080 expected(";");
3081
3082 parseContext.unnestLooping();
3083
3084 statement = intermediate.addLoop(statement, condition, 0, false, loc);
3085
3086 return true;
3087
3088 case EHTokFor:
3089 {
3090 // LEFT_PAREN
3091 if (! acceptTokenClass(EHTokLeftParen))
3092 expected("(");
3093
3094 // so that something declared in the condition is scoped to the lifetime
3095 // of the for sub-statement
3096 parseContext.pushScope();
3097
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003098 // initializer
3099 TIntermNode* initNode = nullptr;
3100 if (! acceptControlDeclaration(initNode)) {
3101 TIntermTyped* initExpr = nullptr;
3102 acceptExpression(initExpr);
3103 initNode = initExpr;
3104 }
3105 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06003106 if (! acceptTokenClass(EHTokSemicolon))
3107 expected(";");
3108
3109 parseContext.nestLooping();
3110
3111 // condition SEMI_COLON
3112 acceptExpression(condition);
3113 if (! acceptTokenClass(EHTokSemicolon))
3114 expected(";");
3115
3116 // iterator SEMI_COLON
3117 TIntermTyped* iterator = nullptr;
3118 acceptExpression(iterator);
3119 if (! acceptTokenClass(EHTokRightParen))
3120 expected(")");
3121
3122 // statement
3123 if (! acceptScopedStatement(statement)) {
3124 expected("for sub-statement");
3125 return false;
3126 }
3127
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003128 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06003129
3130 parseContext.popScope();
3131 parseContext.unnestLooping();
3132
3133 return true;
3134 }
3135
3136 default:
3137 return false;
3138 }
John Kessenich21472ae2016-06-04 11:46:33 -06003139}
3140
3141// jump_statement
3142// : CONTINUE SEMICOLON
3143// | BREAK SEMICOLON
3144// | DISCARD SEMICOLON
3145// | RETURN SEMICOLON
3146// | RETURN expression SEMICOLON
3147//
3148bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3149{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003150 EHlslTokenClass jump = peek();
3151 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06003152 case EHTokContinue:
3153 case EHTokBreak:
3154 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06003155 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003156 advanceToken();
3157 break;
John Kessenich21472ae2016-06-04 11:46:33 -06003158 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003159 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06003160 return false;
3161 }
John Kessenich21472ae2016-06-04 11:46:33 -06003162
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003163 switch (jump) {
3164 case EHTokContinue:
3165 statement = intermediate.addBranch(EOpContinue, token.loc);
3166 break;
3167 case EHTokBreak:
3168 statement = intermediate.addBranch(EOpBreak, token.loc);
3169 break;
3170 case EHTokDiscard:
3171 statement = intermediate.addBranch(EOpKill, token.loc);
3172 break;
3173
3174 case EHTokReturn:
3175 {
3176 // expression
3177 TIntermTyped* node;
3178 if (acceptExpression(node)) {
3179 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06003180 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003181 } else
3182 statement = intermediate.addBranch(EOpReturn, token.loc);
3183 break;
3184 }
3185
3186 default:
3187 assert(0);
3188 return false;
3189 }
3190
3191 // SEMICOLON
3192 if (! acceptTokenClass(EHTokSemicolon))
3193 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003194
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003195 return true;
3196}
John Kessenich21472ae2016-06-04 11:46:33 -06003197
John Kessenichd02dc5d2016-07-01 00:04:11 -06003198// case_label
3199// : CASE expression COLON
3200//
John Kessenich21472ae2016-06-04 11:46:33 -06003201bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3202{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003203 TSourceLoc loc = token.loc;
3204 if (! acceptTokenClass(EHTokCase))
3205 return false;
3206
3207 TIntermTyped* expression;
3208 if (! acceptExpression(expression)) {
3209 expected("case expression");
3210 return false;
3211 }
3212
3213 if (! acceptTokenClass(EHTokColon)) {
3214 expected(":");
3215 return false;
3216 }
3217
3218 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3219
3220 return true;
3221}
3222
3223// default_label
3224// : DEFAULT COLON
3225//
3226bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3227{
3228 TSourceLoc loc = token.loc;
3229 if (! acceptTokenClass(EHTokDefault))
3230 return false;
3231
3232 if (! acceptTokenClass(EHTokColon)) {
3233 expected(":");
3234 return false;
3235 }
3236
3237 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3238
3239 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003240}
3241
John Kessenich19b92ff2016-06-19 11:50:34 -06003242// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003243// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3244// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003245//
3246void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3247{
3248 arraySizes = nullptr;
3249
steve-lunarg7b211a32016-10-13 12:26:18 -06003250 // Early-out if there aren't any array dimensions
3251 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003252 return;
3253
steve-lunarg7b211a32016-10-13 12:26:18 -06003254 // 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 -06003255 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003256
3257 // Collect each array dimension.
3258 while (acceptTokenClass(EHTokLeftBracket)) {
3259 TSourceLoc loc = token.loc;
3260 TIntermTyped* sizeExpr = nullptr;
3261
3262 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
3263 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3264
3265 if (! acceptTokenClass(EHTokRightBracket)) {
3266 expected("]");
3267 return;
3268 }
3269
3270 if (hasArraySize) {
3271 TArraySize arraySize;
3272 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3273 arraySizes->addInnerSize(arraySize);
3274 } else {
3275 arraySizes->addInnerSize(0); // sized by initializers.
3276 }
steve-lunarg265c0612016-09-27 10:57:35 -06003277 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003278}
3279
John Kessenich630dd7d2016-06-12 23:52:12 -06003280// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003281// : COLON semantic // optional
3282// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3283// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003284// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003285// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003286//
John Kessenich854fe242017-03-02 14:30:59 -07003287// Return true if any tokens were accepted. That is,
3288// false can be returned on successfully recognizing nothing,
3289// not necessarily meaning bad syntax.
3290//
3291bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003292{
John Kessenich854fe242017-03-02 14:30:59 -07003293 bool found = false;
3294
John Kessenich630dd7d2016-06-12 23:52:12 -06003295 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003296 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003297 if (acceptTokenClass(EHTokColon)) {
John Kessenich854fe242017-03-02 14:30:59 -07003298 found = true;
John Kessenich630dd7d2016-06-12 23:52:12 -06003299 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003300 if (peekTokenClass(EHTokLayout))
3301 acceptLayoutQualifierList(qualifier);
3302 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003303 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003304 if (! acceptTokenClass(EHTokLeftParen)) {
3305 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003306 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003307 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003308 HlslToken locationToken;
3309 if (! acceptIdentifier(locationToken)) {
3310 expected("c[subcomponent][.component]");
John Kessenich854fe242017-03-02 14:30:59 -07003311 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003312 }
3313 HlslToken componentToken;
3314 if (acceptTokenClass(EHTokDot)) {
3315 if (! acceptIdentifier(componentToken)) {
3316 expected("component");
John Kessenich854fe242017-03-02 14:30:59 -07003317 return false;
John Kessenich82d6baf2016-07-29 13:03:05 -06003318 }
3319 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003320 if (! acceptTokenClass(EHTokRightParen)) {
3321 expected(")");
3322 break;
3323 }
John Kessenich7735b942016-09-05 12:40:06 -06003324 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003325 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003326 expected("layout, semantic, packoffset, or register");
John Kessenich854fe242017-03-02 14:30:59 -07003327 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003328 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003329 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3330 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003331 if (! acceptTokenClass(EHTokLeftParen)) {
3332 expected("(");
John Kessenich854fe242017-03-02 14:30:59 -07003333 return false;
John Kessenich630dd7d2016-06-12 23:52:12 -06003334 }
John Kessenichb38f0712016-07-30 10:29:54 -06003335 HlslToken registerDesc; // for Type#
3336 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003337 if (! acceptIdentifier(registerDesc)) {
3338 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003339 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003340 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003341 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3342 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003343 // Then we didn't really see the registerDesc yet, it was
3344 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003345 profile = registerDesc;
3346 if (! acceptIdentifier(registerDesc)) {
3347 expected("register number description");
John Kessenich854fe242017-03-02 14:30:59 -07003348 return false;
John Kessenich96e9f472016-07-29 14:28:39 -06003349 }
3350 }
John Kessenichb38f0712016-07-30 10:29:54 -06003351 int subComponent = 0;
3352 if (acceptTokenClass(EHTokLeftBracket)) {
3353 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3354 if (! peekTokenClass(EHTokIntConstant)) {
3355 expected("literal integer");
John Kessenich854fe242017-03-02 14:30:59 -07003356 return false;
John Kessenichb38f0712016-07-30 10:29:54 -06003357 }
3358 subComponent = token.i;
3359 advanceToken();
3360 if (! acceptTokenClass(EHTokRightBracket)) {
3361 expected("]");
3362 break;
3363 }
3364 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003365 // (COMMA SPACEN)opt
3366 HlslToken spaceDesc;
3367 if (acceptTokenClass(EHTokComma)) {
3368 if (! acceptIdentifier(spaceDesc)) {
3369 expected ("space identifier");
John Kessenich854fe242017-03-02 14:30:59 -07003370 return false;
John Kessenichcfd7ce82016-09-05 16:03:12 -06003371 }
3372 }
3373 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003374 if (! acceptTokenClass(EHTokRightParen)) {
3375 expected(")");
3376 break;
3377 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003378 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003379 } else {
3380 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003381 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003382 }
John Kessenich854fe242017-03-02 14:30:59 -07003383 } else if (peekTokenClass(EHTokLeftAngle)) {
3384 found = true;
John Kessenicha1e2d492016-09-20 13:22:58 -06003385 acceptAnnotations(qualifier);
John Kessenich854fe242017-03-02 14:30:59 -07003386 } else
John Kessenich630dd7d2016-06-12 23:52:12 -06003387 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003388
John Kessenich630dd7d2016-06-12 23:52:12 -06003389 } while (true);
John Kessenich854fe242017-03-02 14:30:59 -07003390
3391 return found;
John Kessenich078d7f22016-03-14 10:02:11 -06003392}
3393
John Kesseniche01a9bc2016-03-12 20:11:22 -07003394} // end namespace glslang