blob: 6c2041375422b440ad42f699f0c149c8c53d87bf [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
134 TIntermNode* declarationNode;
135 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700136 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600137
138 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600139 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700140 }
141
John Kessenichd016be12016-03-13 11:24:20 -0600142 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600143 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600144
John Kesseniche01a9bc2016-03-12 20:11:22 -0700145 return true;
146}
147
LoopDawg4886f692016-06-29 10:58:58 -0600148// sampler_state
John Kessenichecba76f2017-01-06 00:34:48 -0700149// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
LoopDawg4886f692016-06-29 10:58:58 -0600150//
151// sampler_state_assignment
152// : sampler_state_identifier EQUAL value SEMICOLON
153//
154// sampler_state_identifier
155// : ADDRESSU
156// | ADDRESSV
157// | ADDRESSW
158// | BORDERCOLOR
159// | FILTER
160// | MAXANISOTROPY
161// | MAXLOD
162// | MINLOD
163// | MIPLODBIAS
164//
165bool HlslGrammar::acceptSamplerState()
166{
167 // TODO: this should be genericized to accept a list of valid tokens and
168 // return token/value pairs. Presently it is specific to texture values.
169
170 if (! acceptTokenClass(EHTokLeftBrace))
171 return true;
172
173 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
John Kessenichecba76f2017-01-06 00:34:48 -0700174
LoopDawg4886f692016-06-29 10:58:58 -0600175 do {
176 // read state name
177 HlslToken state;
178 if (! acceptIdentifier(state))
179 break; // end of list
180
181 // FXC accepts any case
182 TString stateName = *state.string;
183 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
184
185 if (! acceptTokenClass(EHTokAssign)) {
186 expected("assign");
187 return false;
188 }
189
190 if (stateName == "minlod" || stateName == "maxlod") {
191 if (! peekTokenClass(EHTokIntConstant)) {
192 expected("integer");
193 return false;
194 }
195
196 TIntermTyped* lod = nullptr;
197 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
198 return false;
199 } else if (stateName == "maxanisotropy") {
200 if (! peekTokenClass(EHTokIntConstant)) {
201 expected("integer");
202 return false;
203 }
204
205 TIntermTyped* maxAnisotropy = nullptr;
206 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
207 return false;
208 } else if (stateName == "filter") {
209 HlslToken filterMode;
210 if (! acceptIdentifier(filterMode)) {
211 expected("filter mode");
212 return false;
213 }
214 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
215 HlslToken addrMode;
216 if (! acceptIdentifier(addrMode)) {
217 expected("texture address mode");
218 return false;
219 }
220 } else if (stateName == "miplodbias") {
221 TIntermTyped* lodBias = nullptr;
222 if (! acceptLiteral(lodBias)) {
223 expected("lod bias");
224 return false;
225 }
226 } else if (stateName == "bordercolor") {
227 return false;
228 } else {
229 expected("texture state");
230 return false;
231 }
232
233 // SEMICOLON
234 if (! acceptTokenClass(EHTokSemicolon)) {
235 expected("semicolon");
236 return false;
237 }
238 } while (true);
239
240 if (! acceptTokenClass(EHTokRightBrace))
241 return false;
242
243 return true;
244}
245
246// sampler_declaration_dx9
247// : SAMPLER identifier EQUAL sampler_type sampler_state
248//
John Kesseniche4821e42016-07-16 10:19:43 -0600249bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600250{
251 if (! acceptTokenClass(EHTokSampler))
252 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700253
LoopDawg4886f692016-06-29 10:58:58 -0600254 // TODO: remove this when DX9 style declarations are implemented.
255 unimplemented("Direct3D 9 sampler declaration");
256
257 // read sampler name
258 HlslToken name;
259 if (! acceptIdentifier(name)) {
260 expected("sampler name");
261 return false;
262 }
263
264 if (! acceptTokenClass(EHTokAssign)) {
265 expected("=");
266 return false;
267 }
268
269 return false;
270}
271
John Kesseniche01a9bc2016-03-12 20:11:22 -0700272// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600273// : sampler_declaration_dx9 post_decls SEMICOLON
274// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600275// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600276// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600277// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700278//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600279// declarator_list
280// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600281//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600282// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600283// : identifier array_specifier post_decls
284// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600285// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600286//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600287// Parsing has to go pretty far in to know whether it's a variable, prototype, or
288// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600289// as above. (The 'identifier' in the first item in init_declarator list is the
290// same as 'identifier' for function declarations.)
291//
292// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600293// or a function body.
294//
295bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700296{
John Kessenichd016be12016-03-13 11:24:20 -0600297 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600298 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600299
steve-lunarg1868b142016-10-20 13:07:10 -0600300 // attributes
301 TAttributeMap attributes;
302 acceptAttributes(attributes);
303
John Kessenich5e69ec62016-07-05 00:02:40 -0600304 // typedef
305 bool typedefDecl = acceptTokenClass(EHTokTypedef);
306
John Kesseniche82061d2016-09-27 14:38:57 -0600307 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600308
309 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600310 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
311 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
312 // HLSL shaders, this will have to be a master level switch
313 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
John Kessenichecba76f2017-01-06 00:34:48 -0700314 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400315
John Kesseniche82061d2016-09-27 14:38:57 -0600316 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400317 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600318
319 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600320 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700321 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600322
John Kessenich87142c72016-03-12 20:24:24 -0700323 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600324 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600325 while (acceptIdentifier(idToken)) {
steve-lunargf1e0c872016-10-31 15:13:43 -0600326 TString* fnName = idToken.string;
327
328 // Potentially rename shader entry point function. No-op most of the time.
329 parseContext.renameShaderFunction(fnName);
330
John Kessenich5f934b02016-03-13 17:58:25 -0600331 // function_parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600332 TFunction& function = *new TFunction(fnName, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600333 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600334 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600335 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600336
John Kessenichd5ed0b62016-07-04 17:32:45 -0600337 // compound_statement (function body definition) or just a prototype?
338 if (peekTokenClass(EHTokLeftBrace)) {
339 if (list)
340 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600341 if (typedefDecl)
342 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
steve-lunarg1868b142016-10-20 13:07:10 -0600343 return acceptFunctionDefinition(function, node, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600344 } else {
345 if (typedefDecl)
346 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600347 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600348 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600349 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600350 // A variable declaration. Fix the storage qualifier if it's a global.
351 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
352 declaredType.getQualifier().storage = EvqUniform;
353
John Kessenichecba76f2017-01-06 00:34:48 -0700354 // We can handle multiple variables per type declaration, so
John Kesseniche82061d2016-09-27 14:38:57 -0600355 // the number of types can expand when arrayness is different.
356 TType variableType;
357 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600358
John Kesseniche82061d2016-09-27 14:38:57 -0600359 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600360 TArraySizes* arraySizes = nullptr;
361 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600362
John Kesseniche82061d2016-09-27 14:38:57 -0600363 // Fix arrayness in the variableType
364 if (declaredType.isImplicitlySizedArray()) {
365 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
366 // of different sizes, for this case sharing the shallow copy of arrayness
367 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
368 variableType.newArraySizes(declaredType.getArraySizes());
369 }
370 if (arraySizes || variableType.isArray()) {
371 // In the most general case, arrayness is potentially coming both from the
372 // declared type and from the variable: "int[] a[];" or just one or the other.
373 // Merge it all to the variableType, so all arrayness is part of the variableType.
374 parseContext.arrayDimMerge(variableType, arraySizes);
375 }
376
LoopDawg4886f692016-06-29 10:58:58 -0600377 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600378 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600379 if (! acceptSamplerState())
380 return false;
381 }
382
John Kessenichd5ed0b62016-07-04 17:32:45 -0600383 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600384 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600385
386 // EQUAL assignment_expression
387 TIntermTyped* expressionNode = nullptr;
388 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600389 if (typedefDecl)
390 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600391 if (! acceptAssignmentExpression(expressionNode)) {
392 expected("initializer");
393 return false;
394 }
395 }
396
John Kessenich6dbc0a72016-09-27 19:13:05 -0600397 // Hand off the actual declaration
398
399 // TODO: things scoped within an annotation need their own name space;
400 // TODO: strings are not yet handled.
401 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
402 if (typedefDecl)
403 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
404 else if (variableType.getBasicType() == EbtBlock)
405 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
406 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700407 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600408 // this isn't really an individual variable, but a member of the $Global buffer
409 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
410 } else {
411 // Declare the variable and add any initializer code to the AST.
412 // The top-level node is always made into an aggregate, as that's
413 // historically how the AST has been.
414 node = intermediate.growAggregate(node,
415 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
416 expressionNode),
417 idToken.loc);
418 }
419 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600420 }
John Kessenich5f934b02016-03-13 17:58:25 -0600421 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600422
423 if (acceptTokenClass(EHTokComma)) {
424 list = true;
425 continue;
426 }
427 };
428
429 // The top-level node is a sequence.
430 if (node != nullptr)
431 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700432
John Kessenich078d7f22016-03-14 10:02:11 -0600433 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600434 if (! acceptTokenClass(EHTokSemicolon)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -0700435 // This may have been a false detection of what appeared to be a declaration, but
436 // was actually an assignment such as "float = 4", where "float" is an identifier.
437 // We put the token back to let further parsing happen for cases where that may
438 // happen. This errors on the side of caution, and mostly triggers the error.
439
440 if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
441 recedeToken();
442 else
443 expected(";");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600444 return false;
445 }
John Kessenichecba76f2017-01-06 00:34:48 -0700446
John Kesseniche01a9bc2016-03-12 20:11:22 -0700447 return true;
448}
449
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600450// control_declaration
451// : fully_specified_type identifier EQUAL expression
452//
453bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
454{
455 node = nullptr;
456
457 // fully_specified_type
458 TType type;
459 if (! acceptFullySpecifiedType(type))
460 return false;
461
462 // identifier
463 HlslToken idToken;
464 if (! acceptIdentifier(idToken)) {
465 expected("identifier");
466 return false;
467 }
468
469 // EQUAL
470 TIntermTyped* expressionNode = nullptr;
471 if (! acceptTokenClass(EHTokAssign)) {
472 expected("=");
473 return false;
474 }
475
476 // expression
477 if (! acceptExpression(expressionNode)) {
478 expected("initializer");
479 return false;
480 }
481
John Kesseniche82061d2016-09-27 14:38:57 -0600482 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600483
484 return true;
485}
486
John Kessenich87142c72016-03-12 20:24:24 -0700487// fully_specified_type
488// : type_specifier
489// | type_qualifier type_specifier
490//
491bool HlslGrammar::acceptFullySpecifiedType(TType& type)
492{
493 // type_qualifier
494 TQualifier qualifier;
495 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600496 if (! acceptQualifier(qualifier))
497 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600498 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700499
500 // type_specifier
steve-lunarga64ed3e2016-12-18 17:51:14 -0700501 if (! acceptType(type)) {
502 // If this is not a type, we may have inadvertently gone down a wrong path
steve-lunarg132d3312016-12-19 15:48:01 -0700503 // by parsing "sample", which can be treated like either an identifier or a
steve-lunarga64ed3e2016-12-18 17:51:14 -0700504 // qualifier. Back it out, if we did.
505 if (qualifier.sample)
506 recedeToken();
507
John Kessenich87142c72016-03-12 20:24:24 -0700508 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700509 }
John Kessenich3d157c52016-07-25 16:05:33 -0600510 if (type.getBasicType() == EbtBlock) {
511 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600512 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600513 // further, it can create an anonymous instance of the block
514 if (peekTokenClass(EHTokSemicolon))
515 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600516 } else {
517 // Some qualifiers are set when parsing the type. Merge those with
518 // whatever comes from acceptQualifier.
519 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700520
steve-lunargbb0183f2016-10-04 16:58:14 -0600521 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600522 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700523
524 if (type.getQualifier().storage == EvqVaryingOut)
525 qualifier.storage = type.getQualifier().storage;
526
527 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600528 }
John Kessenich87142c72016-03-12 20:24:24 -0700529
530 return true;
531}
532
John Kessenich630dd7d2016-06-12 23:52:12 -0600533// type_qualifier
534// : qualifier qualifier ...
535//
536// Zero or more of these, so this can't return false.
537//
John Kessenichb9e39122016-08-17 10:22:08 -0600538bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700539{
John Kessenich630dd7d2016-06-12 23:52:12 -0600540 do {
541 switch (peek()) {
542 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600543 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600544 break;
545 case EHTokExtern:
546 // TODO: no meaning in glslang?
547 break;
548 case EHTokShared:
549 // TODO: hint
550 break;
551 case EHTokGroupShared:
552 qualifier.storage = EvqShared;
553 break;
554 case EHTokUniform:
555 qualifier.storage = EvqUniform;
556 break;
557 case EHTokConst:
558 qualifier.storage = EvqConst;
559 break;
560 case EHTokVolatile:
561 qualifier.volatil = true;
562 break;
563 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600564 qualifier.smooth = true;
565 break;
566 case EHTokCentroid:
567 qualifier.centroid = true;
568 break;
569 case EHTokNointerpolation:
570 qualifier.flat = true;
571 break;
572 case EHTokNoperspective:
573 qualifier.nopersp = true;
574 break;
575 case EHTokSample:
576 qualifier.sample = true;
577 break;
578 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600579 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600580 break;
581 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600582 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600583 break;
584 case EHTokPrecise:
585 qualifier.noContraction = true;
586 break;
LoopDawg9249c702016-07-12 20:44:32 -0600587 case EHTokIn:
588 qualifier.storage = EvqIn;
589 break;
590 case EHTokOut:
591 qualifier.storage = EvqOut;
592 break;
593 case EHTokInOut:
594 qualifier.storage = EvqInOut;
595 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600596 case EHTokLayout:
597 if (! acceptLayoutQualifierList(qualifier))
598 return false;
599 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700600
601 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
602 // for output variables.
603 case EHTokPoint:
604 qualifier.storage = EvqIn;
605 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
606 return false;
607 break;
608 case EHTokLine:
609 qualifier.storage = EvqIn;
610 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
611 return false;
612 break;
613 case EHTokTriangle:
614 qualifier.storage = EvqIn;
615 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
616 return false;
617 break;
618 case EHTokLineAdj:
619 qualifier.storage = EvqIn;
620 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
621 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700622 break;
steve-lunargf49cdf42016-11-17 15:04:20 -0700623 case EHTokTriangleAdj:
624 qualifier.storage = EvqIn;
625 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
626 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700627 break;
628
John Kessenich630dd7d2016-06-12 23:52:12 -0600629 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600630 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600631 }
632 advanceToken();
633 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700634}
635
John Kessenichb9e39122016-08-17 10:22:08 -0600636// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600637// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600638//
639// layout_qualifier
640// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600641// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600642//
643// Zero or more of these, so this can't return false.
644//
645bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
646{
647 if (! acceptTokenClass(EHTokLayout))
648 return false;
649
650 // LEFT_PAREN
651 if (! acceptTokenClass(EHTokLeftParen))
652 return false;
653
654 do {
655 // identifier
656 HlslToken idToken;
657 if (! acceptIdentifier(idToken))
658 break;
659
660 // EQUAL expression
661 if (acceptTokenClass(EHTokAssign)) {
662 TIntermTyped* expr;
663 if (! acceptConditionalExpression(expr)) {
664 expected("expression");
665 return false;
666 }
667 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
668 } else
669 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
670
671 // COMMA
672 if (! acceptTokenClass(EHTokComma))
673 break;
674 } while (true);
675
676 // RIGHT_PAREN
677 if (! acceptTokenClass(EHTokRightParen)) {
678 expected(")");
679 return false;
680 }
681
682 return true;
683}
684
LoopDawg6daaa4f2016-06-23 19:13:48 -0600685// template_type
686// : FLOAT
687// | DOUBLE
688// | INT
689// | DWORD
690// | UINT
691// | BOOL
692//
steve-lunargf49cdf42016-11-17 15:04:20 -0700693bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600694{
695 switch (peek()) {
696 case EHTokFloat:
697 basicType = EbtFloat;
698 break;
699 case EHTokDouble:
700 basicType = EbtDouble;
701 break;
702 case EHTokInt:
703 case EHTokDword:
704 basicType = EbtInt;
705 break;
706 case EHTokUint:
707 basicType = EbtUint;
708 break;
709 case EHTokBool:
710 basicType = EbtBool;
711 break;
712 default:
713 return false;
714 }
715
716 advanceToken();
717
718 return true;
719}
720
721// vector_template_type
722// : VECTOR
723// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
724//
725bool HlslGrammar::acceptVectorTemplateType(TType& type)
726{
727 if (! acceptTokenClass(EHTokVector))
728 return false;
729
730 if (! acceptTokenClass(EHTokLeftAngle)) {
731 // in HLSL, 'vector' alone means float4.
732 new(&type) TType(EbtFloat, EvqTemporary, 4);
733 return true;
734 }
735
736 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700737 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600738 expected("scalar type");
739 return false;
740 }
741
742 // COMMA
743 if (! acceptTokenClass(EHTokComma)) {
744 expected(",");
745 return false;
746 }
747
748 // integer
749 if (! peekTokenClass(EHTokIntConstant)) {
750 expected("literal integer");
751 return false;
752 }
753
754 TIntermTyped* vecSize;
755 if (! acceptLiteral(vecSize))
756 return false;
757
758 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
759
760 new(&type) TType(basicType, EvqTemporary, vecSizeI);
761
762 if (vecSizeI == 1)
763 type.makeVector();
764
765 if (!acceptTokenClass(EHTokRightAngle)) {
766 expected("right angle bracket");
767 return false;
768 }
769
770 return true;
771}
772
773// matrix_template_type
774// : MATRIX
775// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
776//
777bool HlslGrammar::acceptMatrixTemplateType(TType& type)
778{
779 if (! acceptTokenClass(EHTokMatrix))
780 return false;
781
782 if (! acceptTokenClass(EHTokLeftAngle)) {
783 // in HLSL, 'matrix' alone means float4x4.
784 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
785 return true;
786 }
787
788 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700789 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600790 expected("scalar type");
791 return false;
792 }
793
794 // COMMA
795 if (! acceptTokenClass(EHTokComma)) {
796 expected(",");
797 return false;
798 }
799
800 // integer rows
801 if (! peekTokenClass(EHTokIntConstant)) {
802 expected("literal integer");
803 return false;
804 }
805
806 TIntermTyped* rows;
807 if (! acceptLiteral(rows))
808 return false;
809
810 // COMMA
811 if (! acceptTokenClass(EHTokComma)) {
812 expected(",");
813 return false;
814 }
John Kessenichecba76f2017-01-06 00:34:48 -0700815
LoopDawg6daaa4f2016-06-23 19:13:48 -0600816 // integer cols
817 if (! peekTokenClass(EHTokIntConstant)) {
818 expected("literal integer");
819 return false;
820 }
821
822 TIntermTyped* cols;
823 if (! acceptLiteral(cols))
824 return false;
825
826 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600827 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
828 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600829
830 if (!acceptTokenClass(EHTokRightAngle)) {
831 expected("right angle bracket");
832 return false;
833 }
834
835 return true;
836}
837
steve-lunargf49cdf42016-11-17 15:04:20 -0700838// layout_geometry
839// : LINESTREAM
840// | POINTSTREAM
841// | TRIANGLESTREAM
842//
843bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
844{
845 // read geometry type
846 const EHlslTokenClass geometryType = peek();
847
848 switch (geometryType) {
849 case EHTokPointStream: geometry = ElgPoints; break;
850 case EHTokLineStream: geometry = ElgLineStrip; break;
851 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
852 default:
853 return false; // not a layout geometry
854 }
855
856 advanceToken(); // consume the layout keyword
857 return true;
858}
859
860// stream_out_template_type
861// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
862//
863bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
864{
865 geometry = ElgNone;
866
867 if (! acceptOutputPrimitiveGeometry(geometry))
868 return false;
869
870 if (! acceptTokenClass(EHTokLeftAngle))
871 return false;
John Kessenichecba76f2017-01-06 00:34:48 -0700872
steve-lunargf49cdf42016-11-17 15:04:20 -0700873 if (! acceptType(type)) {
874 expected("stream output type");
875 return false;
876 }
877
878 type.getQualifier().storage = EvqVaryingOut;
879
880 if (! acceptTokenClass(EHTokRightAngle)) {
881 expected("right angle bracket");
882 return false;
883 }
884
885 return true;
886}
John Kessenichecba76f2017-01-06 00:34:48 -0700887
John Kessenicha1e2d492016-09-20 13:22:58 -0600888// annotations
889// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600890//
John Kessenicha1e2d492016-09-20 13:22:58 -0600891bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600892{
John Kessenicha1e2d492016-09-20 13:22:58 -0600893 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600894 return false;
895
John Kessenicha1e2d492016-09-20 13:22:58 -0600896 // note that we are nesting a name space
897 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600898
899 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
900 do {
901 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
902 while (acceptTokenClass(EHTokSemicolon))
903 ;
904
905 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600906 break;
John Kessenich86f71382016-09-19 20:23:18 -0600907
908 // declaration
909 TIntermNode* node;
910 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600911 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600912 return false;
913 }
914 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600915
916 parseContext.unnestAnnotations();
917 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600918}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600919
LoopDawg4886f692016-06-29 10:58:58 -0600920// sampler_type
921// : SAMPLER
922// | SAMPLER1D
923// | SAMPLER2D
924// | SAMPLER3D
925// | SAMPLERCUBE
926// | SAMPLERSTATE
927// | SAMPLERCOMPARISONSTATE
928bool HlslGrammar::acceptSamplerType(TType& type)
929{
930 // read sampler type
931 const EHlslTokenClass samplerType = peek();
932
LoopDawga78b0292016-07-19 14:28:05 -0600933 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600934 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600935
LoopDawga78b0292016-07-19 14:28:05 -0600936 bool isShadow = false;
937
LoopDawg4886f692016-06-29 10:58:58 -0600938 switch (samplerType) {
939 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600940 case EHTokSampler1d: /*dim = Esd1D*/; break;
941 case EHTokSampler2d: /*dim = Esd2D*/; break;
942 case EHTokSampler3d: /*dim = Esd3D*/; break;
943 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600944 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600945 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600946 default:
947 return false; // not a sampler declaration
948 }
949
950 advanceToken(); // consume the sampler type keyword
951
952 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600953
954 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600955 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600956
957 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
958
959 return true;
960}
961
962// texture_type
963// | BUFFER
964// | TEXTURE1D
965// | TEXTURE1DARRAY
966// | TEXTURE2D
967// | TEXTURE2DARRAY
968// | TEXTURE3D
969// | TEXTURECUBE
970// | TEXTURECUBEARRAY
971// | TEXTURE2DMS
972// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600973// | RWBUFFER
974// | RWTEXTURE1D
975// | RWTEXTURE1DARRAY
976// | RWTEXTURE2D
977// | RWTEXTURE2DARRAY
978// | RWTEXTURE3D
979
LoopDawg4886f692016-06-29 10:58:58 -0600980bool HlslGrammar::acceptTextureType(TType& type)
981{
982 const EHlslTokenClass textureType = peek();
983
984 TSamplerDim dim = EsdNone;
985 bool array = false;
986 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600987 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600988
989 switch (textureType) {
990 case EHTokBuffer: dim = EsdBuffer; break;
991 case EHTokTexture1d: dim = Esd1D; break;
992 case EHTokTexture1darray: dim = Esd1D; array = true; break;
993 case EHTokTexture2d: dim = Esd2D; break;
994 case EHTokTexture2darray: dim = Esd2D; array = true; break;
John Kessenichecba76f2017-01-06 00:34:48 -0700995 case EHTokTexture3d: dim = Esd3D; break;
LoopDawg4886f692016-06-29 10:58:58 -0600996 case EHTokTextureCube: dim = EsdCube; break;
997 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
998 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
999 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -06001000 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
1001 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
1002 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
1003 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
1004 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
1005 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -06001006 default:
1007 return false; // not a texture declaration
1008 }
1009
1010 advanceToken(); // consume the texture object keyword
1011
1012 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
John Kessenichecba76f2017-01-06 00:34:48 -07001013
LoopDawg4886f692016-06-29 10:58:58 -06001014 TIntermTyped* msCount = nullptr;
1015
steve-lunargbb0183f2016-10-04 16:58:14 -06001016 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -06001017 if (acceptTokenClass(EHTokLeftAngle)) {
1018 if (! acceptType(txType)) {
1019 expected("scalar or vector type");
1020 return false;
1021 }
1022
1023 const TBasicType basicRetType = txType.getBasicType() ;
1024
1025 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1026 unimplemented("basic type in texture");
1027 return false;
1028 }
1029
steve-lunargd53f7172016-07-27 15:46:48 -06001030 // Buffers can handle small mats if they fit in 4 components
1031 if (dim == EsdBuffer && txType.isMatrix()) {
1032 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1033 expected("components < 4 in matrix buffer type");
1034 return false;
1035 }
1036
1037 // TODO: except we don't handle it yet...
1038 unimplemented("matrix type in buffer");
1039 return false;
1040 }
1041
LoopDawg4886f692016-06-29 10:58:58 -06001042 if (!txType.isScalar() && !txType.isVector()) {
1043 expected("scalar or vector type");
1044 return false;
1045 }
1046
LoopDawg4886f692016-06-29 10:58:58 -06001047 if (ms && acceptTokenClass(EHTokComma)) {
1048 // read sample count for multisample types, if given
1049 if (! peekTokenClass(EHTokIntConstant)) {
1050 expected("multisample count");
1051 return false;
1052 }
1053
1054 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1055 return false;
1056 }
1057
1058 if (! acceptTokenClass(EHTokRightAngle)) {
1059 expected("right angle bracket");
1060 return false;
1061 }
1062 } else if (ms) {
1063 expected("texture type for multisample");
1064 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001065 } else if (image) {
1066 expected("type for RWTexture/RWBuffer");
1067 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001068 }
1069
1070 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001071 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001072
1073 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001074 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001075
steve-lunarg4f2da272016-10-10 15:24:57 -06001076 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1077 if (image || dim == EsdBuffer)
1078 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001079
1080 // Non-image Buffers are combined
1081 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001082 sampler.set(txType.getBasicType(), dim, array);
1083 } else {
1084 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001085 if (image) {
1086 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1087 } else {
1088 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1089 }
steve-lunargd53f7172016-07-27 15:46:48 -06001090 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001091
1092 // Remember the declared vector size.
1093 sampler.vectorSize = txType.getVectorSize();
John Kessenichecba76f2017-01-06 00:34:48 -07001094
LoopDawg4886f692016-06-29 10:58:58 -06001095 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001096 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001097
1098 return true;
1099}
1100
John Kessenich87142c72016-03-12 20:24:24 -07001101// If token is for a type, update 'type' with the type information,
1102// and return true and advance.
1103// Otherwise, return false, and don't advance
1104bool HlslGrammar::acceptType(TType& type)
1105{
steve-lunarg3226b082016-10-26 19:18:55 -06001106 // Basic types for min* types, broken out here in case of future
1107 // changes, e.g, to use native halfs.
1108 static const TBasicType min16float_bt = EbtFloat;
1109 static const TBasicType min10float_bt = EbtFloat;
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001110 static const TBasicType half_bt = EbtFloat;
steve-lunarg3226b082016-10-26 19:18:55 -06001111 static const TBasicType min16int_bt = EbtInt;
1112 static const TBasicType min12int_bt = EbtInt;
1113 static const TBasicType min16uint_bt = EbtUint;
1114
John Kessenich9c86c6a2016-05-03 22:49:24 -06001115 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001116 case EHTokVector:
1117 return acceptVectorTemplateType(type);
1118 break;
1119
1120 case EHTokMatrix:
1121 return acceptMatrixTemplateType(type);
1122 break;
1123
steve-lunargf49cdf42016-11-17 15:04:20 -07001124 case EHTokPointStream: // fall through
1125 case EHTokLineStream: // ...
1126 case EHTokTriangleStream: // ...
1127 {
1128 TLayoutGeometry geometry;
1129 if (! acceptStreamOutTemplateType(type, geometry))
1130 return false;
1131
1132 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1133 return false;
John Kessenichecba76f2017-01-06 00:34:48 -07001134
steve-lunargf49cdf42016-11-17 15:04:20 -07001135 return true;
1136 }
1137
LoopDawg4886f692016-06-29 10:58:58 -06001138 case EHTokSampler: // fall through
1139 case EHTokSampler1d: // ...
1140 case EHTokSampler2d: // ...
1141 case EHTokSampler3d: // ...
1142 case EHTokSamplerCube: // ...
1143 case EHTokSamplerState: // ...
1144 case EHTokSamplerComparisonState: // ...
1145 return acceptSamplerType(type);
1146 break;
1147
1148 case EHTokBuffer: // fall through
1149 case EHTokTexture1d: // ...
1150 case EHTokTexture1darray: // ...
1151 case EHTokTexture2d: // ...
1152 case EHTokTexture2darray: // ...
1153 case EHTokTexture3d: // ...
1154 case EHTokTextureCube: // ...
1155 case EHTokTextureCubearray: // ...
1156 case EHTokTexture2DMS: // ...
1157 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001158 case EHTokRWTexture1d: // ...
1159 case EHTokRWTexture1darray: // ...
1160 case EHTokRWTexture2d: // ...
1161 case EHTokRWTexture2darray: // ...
1162 case EHTokRWTexture3d: // ...
1163 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001164 return acceptTextureType(type);
1165 break;
1166
John Kesseniche6e74942016-06-11 16:43:14 -06001167 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001168 case EHTokCBuffer:
1169 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001170 return acceptStruct(type);
1171 break;
1172
1173 case EHTokIdentifier:
1174 // An identifier could be for a user-defined type.
1175 // Note we cache the symbol table lookup, to save for a later rule
1176 // when this is not a type.
1177 token.symbol = parseContext.symbolTable.find(*token.string);
1178 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1179 type.shallowCopy(token.symbol->getType());
1180 advanceToken();
1181 return true;
1182 } else
1183 return false;
1184
John Kessenich71351de2016-06-08 12:50:56 -06001185 case EHTokVoid:
1186 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001187 break;
John Kessenich71351de2016-06-08 12:50:56 -06001188
John Kessenicha1e2d492016-09-20 13:22:58 -06001189 case EHTokString:
1190 new(&type) TType(EbtString);
1191 break;
1192
John Kessenich87142c72016-03-12 20:24:24 -07001193 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001194 new(&type) TType(EbtFloat);
1195 break;
John Kessenich87142c72016-03-12 20:24:24 -07001196 case EHTokFloat1:
1197 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001198 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001199 break;
John Kessenich87142c72016-03-12 20:24:24 -07001200 case EHTokFloat2:
1201 new(&type) TType(EbtFloat, EvqTemporary, 2);
1202 break;
1203 case EHTokFloat3:
1204 new(&type) TType(EbtFloat, EvqTemporary, 3);
1205 break;
1206 case EHTokFloat4:
1207 new(&type) TType(EbtFloat, EvqTemporary, 4);
1208 break;
1209
John Kessenich71351de2016-06-08 12:50:56 -06001210 case EHTokDouble:
1211 new(&type) TType(EbtDouble);
1212 break;
1213 case EHTokDouble1:
1214 new(&type) TType(EbtDouble);
1215 type.makeVector();
1216 break;
1217 case EHTokDouble2:
1218 new(&type) TType(EbtDouble, EvqTemporary, 2);
1219 break;
1220 case EHTokDouble3:
1221 new(&type) TType(EbtDouble, EvqTemporary, 3);
1222 break;
1223 case EHTokDouble4:
1224 new(&type) TType(EbtDouble, EvqTemporary, 4);
1225 break;
1226
1227 case EHTokInt:
1228 case EHTokDword:
1229 new(&type) TType(EbtInt);
1230 break;
1231 case EHTokInt1:
1232 new(&type) TType(EbtInt);
1233 type.makeVector();
1234 break;
John Kessenich87142c72016-03-12 20:24:24 -07001235 case EHTokInt2:
1236 new(&type) TType(EbtInt, EvqTemporary, 2);
1237 break;
1238 case EHTokInt3:
1239 new(&type) TType(EbtInt, EvqTemporary, 3);
1240 break;
1241 case EHTokInt4:
1242 new(&type) TType(EbtInt, EvqTemporary, 4);
1243 break;
1244
John Kessenich71351de2016-06-08 12:50:56 -06001245 case EHTokUint:
1246 new(&type) TType(EbtUint);
1247 break;
1248 case EHTokUint1:
1249 new(&type) TType(EbtUint);
1250 type.makeVector();
1251 break;
1252 case EHTokUint2:
1253 new(&type) TType(EbtUint, EvqTemporary, 2);
1254 break;
1255 case EHTokUint3:
1256 new(&type) TType(EbtUint, EvqTemporary, 3);
1257 break;
1258 case EHTokUint4:
1259 new(&type) TType(EbtUint, EvqTemporary, 4);
1260 break;
1261
1262 case EHTokBool:
1263 new(&type) TType(EbtBool);
1264 break;
1265 case EHTokBool1:
1266 new(&type) TType(EbtBool);
1267 type.makeVector();
1268 break;
John Kessenich87142c72016-03-12 20:24:24 -07001269 case EHTokBool2:
1270 new(&type) TType(EbtBool, EvqTemporary, 2);
1271 break;
1272 case EHTokBool3:
1273 new(&type) TType(EbtBool, EvqTemporary, 3);
1274 break;
1275 case EHTokBool4:
1276 new(&type) TType(EbtBool, EvqTemporary, 4);
1277 break;
1278
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001279 case EHTokHalf:
1280 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1281 break;
1282 case EHTokHalf1:
1283 new(&type) TType(half_bt, EvqTemporary, EpqMedium);
1284 type.makeVector();
1285 break;
1286 case EHTokHalf2:
1287 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 2);
1288 break;
1289 case EHTokHalf3:
1290 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 3);
1291 break;
1292 case EHTokHalf4:
1293 new(&type) TType(half_bt, EvqTemporary, EpqMedium, 4);
1294 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001295
steve-lunarg3226b082016-10-26 19:18:55 -06001296 case EHTokMin16float:
1297 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1298 break;
1299 case EHTokMin16float1:
1300 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1301 type.makeVector();
1302 break;
1303 case EHTokMin16float2:
1304 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1305 break;
1306 case EHTokMin16float3:
1307 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1308 break;
1309 case EHTokMin16float4:
1310 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1311 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001312
steve-lunarg3226b082016-10-26 19:18:55 -06001313 case EHTokMin10float:
1314 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1315 break;
1316 case EHTokMin10float1:
1317 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1318 type.makeVector();
1319 break;
1320 case EHTokMin10float2:
1321 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1322 break;
1323 case EHTokMin10float3:
1324 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1325 break;
1326 case EHTokMin10float4:
1327 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1328 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001329
steve-lunarg3226b082016-10-26 19:18:55 -06001330 case EHTokMin16int:
1331 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1332 break;
1333 case EHTokMin16int1:
1334 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1335 type.makeVector();
1336 break;
1337 case EHTokMin16int2:
1338 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1339 break;
1340 case EHTokMin16int3:
1341 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1342 break;
1343 case EHTokMin16int4:
1344 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1345 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001346
steve-lunarg3226b082016-10-26 19:18:55 -06001347 case EHTokMin12int:
1348 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1349 break;
1350 case EHTokMin12int1:
1351 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1352 type.makeVector();
1353 break;
1354 case EHTokMin12int2:
1355 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1356 break;
1357 case EHTokMin12int3:
1358 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1359 break;
1360 case EHTokMin12int4:
1361 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1362 break;
John Kessenichecba76f2017-01-06 00:34:48 -07001363
steve-lunarg3226b082016-10-26 19:18:55 -06001364 case EHTokMin16uint:
1365 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1366 break;
1367 case EHTokMin16uint1:
1368 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1369 type.makeVector();
1370 break;
1371 case EHTokMin16uint2:
1372 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1373 break;
1374 case EHTokMin16uint3:
1375 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1376 break;
1377 case EHTokMin16uint4:
1378 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1379 break;
1380
John Kessenich0133c122016-05-20 12:17:26 -06001381 case EHTokInt1x1:
1382 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1383 break;
1384 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001385 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001386 break;
1387 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001388 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001389 break;
1390 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001391 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001392 break;
1393 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001394 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001395 break;
1396 case EHTokInt2x2:
1397 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1398 break;
1399 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001400 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001401 break;
1402 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001403 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001404 break;
1405 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001406 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001407 break;
1408 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001409 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001410 break;
1411 case EHTokInt3x3:
1412 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1413 break;
1414 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001415 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001416 break;
1417 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001418 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001419 break;
1420 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001421 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001422 break;
1423 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001424 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001425 break;
1426 case EHTokInt4x4:
1427 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1428 break;
1429
John Kessenich71351de2016-06-08 12:50:56 -06001430 case EHTokUint1x1:
1431 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1432 break;
1433 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001434 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001435 break;
1436 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001437 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001438 break;
1439 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001440 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001441 break;
1442 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001443 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001444 break;
1445 case EHTokUint2x2:
1446 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1447 break;
1448 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001449 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001450 break;
1451 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001452 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001453 break;
1454 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001455 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001456 break;
1457 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001458 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001459 break;
1460 case EHTokUint3x3:
1461 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1462 break;
1463 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001464 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001465 break;
1466 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001467 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001468 break;
1469 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001470 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001471 break;
1472 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001473 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001474 break;
1475 case EHTokUint4x4:
1476 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1477 break;
1478
1479 case EHTokBool1x1:
1480 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1481 break;
1482 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001483 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001484 break;
1485 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001486 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001487 break;
1488 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001489 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001490 break;
1491 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001492 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001493 break;
1494 case EHTokBool2x2:
1495 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1496 break;
1497 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001498 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001499 break;
1500 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001501 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001502 break;
1503 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001504 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001505 break;
1506 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001507 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001508 break;
1509 case EHTokBool3x3:
1510 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1511 break;
1512 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001513 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001514 break;
1515 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001516 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001517 break;
1518 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001519 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001520 break;
1521 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001522 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001523 break;
1524 case EHTokBool4x4:
1525 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1526 break;
1527
John Kessenich0133c122016-05-20 12:17:26 -06001528 case EHTokFloat1x1:
1529 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1530 break;
1531 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001532 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001533 break;
1534 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001535 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001536 break;
1537 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001538 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001539 break;
1540 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001541 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001542 break;
John Kessenich87142c72016-03-12 20:24:24 -07001543 case EHTokFloat2x2:
1544 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1545 break;
1546 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001547 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001548 break;
1549 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001550 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001551 break;
John Kessenich0133c122016-05-20 12:17:26 -06001552 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001553 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001554 break;
John Kessenich87142c72016-03-12 20:24:24 -07001555 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001556 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001557 break;
1558 case EHTokFloat3x3:
1559 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1560 break;
1561 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001562 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001563 break;
John Kessenich0133c122016-05-20 12:17:26 -06001564 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001565 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001566 break;
John Kessenich87142c72016-03-12 20:24:24 -07001567 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001568 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001569 break;
1570 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001571 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001572 break;
1573 case EHTokFloat4x4:
1574 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1575 break;
1576
John Kessenich0133c122016-05-20 12:17:26 -06001577 case EHTokDouble1x1:
1578 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1579 break;
1580 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001581 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001582 break;
1583 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001584 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001585 break;
1586 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001587 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001588 break;
1589 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001590 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001591 break;
1592 case EHTokDouble2x2:
1593 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1594 break;
1595 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001596 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001597 break;
1598 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001599 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001600 break;
1601 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001602 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001603 break;
1604 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001605 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001606 break;
1607 case EHTokDouble3x3:
1608 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1609 break;
1610 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001611 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001612 break;
1613 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001614 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001615 break;
1616 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001617 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001618 break;
1619 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001620 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001621 break;
1622 case EHTokDouble4x4:
1623 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1624 break;
1625
John Kessenich87142c72016-03-12 20:24:24 -07001626 default:
1627 return false;
1628 }
1629
1630 advanceToken();
1631
1632 return true;
1633}
1634
John Kesseniche6e74942016-06-11 16:43:14 -06001635// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001636// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1637// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1638//
1639// struct_type
1640// : STRUCT
1641// | CBUFFER
1642// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001643//
1644bool HlslGrammar::acceptStruct(TType& type)
1645{
John Kessenichb804de62016-09-05 12:19:18 -06001646 // This storage qualifier will tell us whether it's an AST
1647 // block type or just a generic structure type.
1648 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001649
1650 // CBUFFER
1651 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001652 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001653 // TBUFFER
1654 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001655 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001656 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001657 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001658 return false;
1659
1660 // IDENTIFIER
1661 TString structName = "";
1662 if (peekTokenClass(EHTokIdentifier)) {
1663 structName = *token.string;
1664 advanceToken();
1665 }
1666
John Kessenich3d157c52016-07-25 16:05:33 -06001667 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001668 TQualifier postDeclQualifier;
1669 postDeclQualifier.clear();
1670 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001671
John Kesseniche6e74942016-06-11 16:43:14 -06001672 // LEFT_BRACE
1673 if (! acceptTokenClass(EHTokLeftBrace)) {
1674 expected("{");
1675 return false;
1676 }
1677
1678 // struct_declaration_list
1679 TTypeList* typeList;
1680 if (! acceptStructDeclarationList(typeList)) {
1681 expected("struct member declarations");
1682 return false;
1683 }
1684
1685 // RIGHT_BRACE
1686 if (! acceptTokenClass(EHTokRightBrace)) {
1687 expected("}");
1688 return false;
1689 }
1690
1691 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001692 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001693 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001694 else {
John Kessenich7735b942016-09-05 12:40:06 -06001695 postDeclQualifier.storage = storageQualifier;
1696 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001697 }
John Kesseniche6e74942016-06-11 16:43:14 -06001698
John Kessenich3d157c52016-07-25 16:05:33 -06001699 // If it was named, which means the type can be reused later, add
1700 // it to the symbol table. (Unless it's a block, in which
1701 // case the name is not a type.)
1702 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001703 TVariable* userTypeDef = new TVariable(&structName, type, true);
1704 if (! parseContext.symbolTable.insert(*userTypeDef))
1705 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1706 }
1707
1708 return true;
1709}
1710
1711// struct_declaration_list
1712// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1713//
1714// struct_declaration
1715// : fully_specified_type struct_declarator COMMA struct_declarator ...
1716//
1717// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001718// : IDENTIFIER post_decls
1719// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001720//
1721bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1722{
1723 typeList = new TTypeList();
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001724 HlslToken idToken;
John Kesseniche6e74942016-06-11 16:43:14 -06001725
1726 do {
1727 // success on seeing the RIGHT_BRACE coming up
1728 if (peekTokenClass(EHTokRightBrace))
1729 return true;
1730
1731 // struct_declaration
1732
1733 // fully_specified_type
1734 TType memberType;
1735 if (! acceptFullySpecifiedType(memberType)) {
1736 expected("member type");
1737 return false;
1738 }
1739
1740 // struct_declarator COMMA struct_declarator ...
1741 do {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001742 if (! acceptIdentifier(idToken)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001743 expected("member name");
1744 return false;
1745 }
1746
1747 // add it to the list of members
1748 TTypeLoc member = { new TType(EbtVoid), token.loc };
1749 member.type->shallowCopy(memberType);
steve-lunarg5ca85ad2016-12-26 18:45:52 -07001750 member.type->setFieldName(*idToken.string);
John Kesseniche6e74942016-06-11 16:43:14 -06001751 typeList->push_back(member);
1752
John Kesseniche6e74942016-06-11 16:43:14 -06001753 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001754 TArraySizes* arraySizes = nullptr;
1755 acceptArraySpecifier(arraySizes);
1756 if (arraySizes)
1757 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001758
John Kessenich7735b942016-09-05 12:40:06 -06001759 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001760
John Kessenich18adbdb2017-02-02 15:16:20 -07001761 // EQUAL assignment_expression
1762 if (acceptTokenClass(EHTokAssign)) {
1763 parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
1764 TIntermTyped* expressionNode = nullptr;
1765 if (! acceptAssignmentExpression(expressionNode)) {
1766 expected("initializer");
1767 return false;
1768 }
1769 }
1770
John Kesseniche6e74942016-06-11 16:43:14 -06001771 // success on seeing the SEMICOLON coming up
1772 if (peekTokenClass(EHTokSemicolon))
1773 break;
1774
1775 // COMMA
1776 if (! acceptTokenClass(EHTokComma)) {
1777 expected(",");
1778 return false;
1779 }
1780
1781 } while (true);
1782
1783 // SEMI_COLON
1784 if (! acceptTokenClass(EHTokSemicolon)) {
1785 expected(";");
1786 return false;
1787 }
1788
1789 } while (true);
1790}
1791
John Kessenich5f934b02016-03-13 17:58:25 -06001792// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001793// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001794// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001795//
1796bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1797{
John Kessenich078d7f22016-03-14 10:02:11 -06001798 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001799 if (! acceptTokenClass(EHTokLeftParen))
1800 return false;
1801
John Kessenich71351de2016-06-08 12:50:56 -06001802 // VOID RIGHT_PAREN
1803 if (! acceptTokenClass(EHTokVoid)) {
1804 do {
1805 // parameter_declaration
1806 if (! acceptParameterDeclaration(function))
1807 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001808
John Kessenich71351de2016-06-08 12:50:56 -06001809 // COMMA
1810 if (! acceptTokenClass(EHTokComma))
1811 break;
1812 } while (true);
1813 }
John Kessenich5f934b02016-03-13 17:58:25 -06001814
John Kessenich078d7f22016-03-14 10:02:11 -06001815 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001816 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001817 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001818 return false;
1819 }
1820
1821 return true;
1822}
1823
steve-lunarg26d31452016-12-23 18:56:57 -07001824// default_parameter_declaration
1825// : EQUAL conditional_expression
1826// : EQUAL initializer
1827bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
1828{
1829 node = nullptr;
1830
1831 // Valid not to have a default_parameter_declaration
1832 if (!acceptTokenClass(EHTokAssign))
1833 return true;
1834
1835 if (!acceptConditionalExpression(node)) {
1836 if (!acceptInitializer(node))
1837 return false;
1838
1839 // For initializer lists, we have to const-fold into a constructor for the type, so build
1840 // that.
1841 TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
1842 if (constructor == nullptr) // cannot construct
1843 return false;
1844
1845 TIntermTyped* arguments = nullptr;
John Kessenichecba76f2017-01-06 00:34:48 -07001846 for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
steve-lunarg26d31452016-12-23 18:56:57 -07001847 parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
John Kessenichecba76f2017-01-06 00:34:48 -07001848
steve-lunarg26d31452016-12-23 18:56:57 -07001849 node = parseContext.handleFunctionCall(token.loc, constructor, node);
1850 }
1851
1852 // If this is simply a constant, we can use it directly.
1853 if (node->getAsConstantUnion())
1854 return true;
1855
1856 // Otherwise, it has to be const-foldable.
1857 TIntermTyped* origNode = node;
1858
1859 node = intermediate.fold(node->getAsAggregate());
1860
1861 if (node != nullptr && origNode != node)
1862 return true;
1863
1864 parseContext.error(token.loc, "invalid default parameter value", "", "");
1865
1866 return false;
1867}
1868
John Kessenich5f934b02016-03-13 17:58:25 -06001869// parameter_declaration
steve-lunarg26d31452016-12-23 18:56:57 -07001870// : fully_specified_type post_decls [ = default_parameter_declaration ]
1871// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
John Kessenich5f934b02016-03-13 17:58:25 -06001872//
1873bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1874{
1875 // fully_specified_type
1876 TType* type = new TType;
1877 if (! acceptFullySpecifiedType(*type))
1878 return false;
1879
1880 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001881 HlslToken idToken;
1882 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001883
John Kessenich19b92ff2016-06-19 11:50:34 -06001884 // array_specifier
1885 TArraySizes* arraySizes = nullptr;
1886 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001887 if (arraySizes) {
1888 if (arraySizes->isImplicit()) {
1889 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1890 return false;
1891 }
1892
John Kessenich19b92ff2016-06-19 11:50:34 -06001893 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001894 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001895
1896 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001897 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001898
steve-lunarg26d31452016-12-23 18:56:57 -07001899 TIntermTyped* defaultValue;
1900 if (!acceptDefaultParameterDeclaration(*type, defaultValue))
1901 return false;
1902
John Kessenich5aa59e22016-06-17 15:50:47 -06001903 parseContext.paramFix(*type);
1904
steve-lunarg26d31452016-12-23 18:56:57 -07001905 // If any prior parameters have default values, all the parameters after that must as well.
1906 if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
1907 parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
1908 return false;
1909 }
1910
1911 TParameter param = { idToken.string, type, defaultValue };
John Kessenich5f934b02016-03-13 17:58:25 -06001912 function.addParameter(param);
1913
1914 return true;
1915}
1916
1917// Do the work to create the function definition in addition to
1918// parsing the body (compound_statement).
steve-lunarg1868b142016-10-20 13:07:10 -06001919bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001920{
John Kessenicha3051662016-09-02 19:13:36 -06001921 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001922 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001923
John Kessenich077e0522016-06-09 02:02:17 -06001924 // This does a pushScope()
steve-lunarg1868b142016-10-20 13:07:10 -06001925 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06001926
1927 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001928 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001929 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001930 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001931 return true;
1932 }
1933
1934 return false;
1935}
1936
John Kessenich0d2b6de2016-06-05 11:23:11 -06001937// Accept an expression with parenthesis around it, where
1938// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001939// syntactically required ones like in "if ( expression )".
1940//
1941// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001942//
1943// Note this one is not set up to be speculative; as it gives
1944// errors if not found.
1945//
1946bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1947{
1948 // LEFT_PAREN
1949 if (! acceptTokenClass(EHTokLeftParen))
1950 expected("(");
1951
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001952 bool decl = false;
1953 TIntermNode* declNode = nullptr;
1954 decl = acceptControlDeclaration(declNode);
1955 if (decl) {
1956 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1957 expected("initialized declaration");
1958 return false;
1959 } else
1960 expression = declNode->getAsTyped();
1961 } else {
1962 // no declaration
1963 if (! acceptExpression(expression)) {
1964 expected("expression");
1965 return false;
1966 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001967 }
1968
1969 // RIGHT_PAREN
1970 if (! acceptTokenClass(EHTokRightParen))
1971 expected(")");
1972
1973 return true;
1974}
1975
John Kessenich34fb0362016-05-03 23:17:20 -06001976// The top-level full expression recognizer.
1977//
John Kessenich87142c72016-03-12 20:24:24 -07001978// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001979// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001980//
1981bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1982{
LoopDawgef764a22016-06-03 09:17:51 -06001983 node = nullptr;
1984
John Kessenich34fb0362016-05-03 23:17:20 -06001985 // assignment_expression
1986 if (! acceptAssignmentExpression(node))
1987 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001988
John Kessenich34fb0362016-05-03 23:17:20 -06001989 if (! peekTokenClass(EHTokComma))
1990 return true;
1991
1992 do {
1993 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001994 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001995 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001996
John Kessenich34fb0362016-05-03 23:17:20 -06001997 // ... assignment_expression
1998 TIntermTyped* rightNode = nullptr;
1999 if (! acceptAssignmentExpression(rightNode)) {
2000 expected("assignment expression");
2001 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06002002 }
2003
John Kessenich34fb0362016-05-03 23:17:20 -06002004 node = intermediate.addComma(node, rightNode, loc);
2005
2006 if (! peekTokenClass(EHTokComma))
2007 return true;
2008 } while (true);
2009}
2010
John Kessenich07354242016-07-01 19:58:06 -06002011// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07002012// : LEFT_BRACE RIGHT_BRACE
2013// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002014//
2015// initializer_list
2016// : assignment_expression COMMA assignment_expression COMMA ...
2017//
2018bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2019{
2020 // LEFT_BRACE
2021 if (! acceptTokenClass(EHTokLeftBrace))
2022 return false;
2023
John Kessenich98ad4852016-11-27 17:39:07 -07002024 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06002025 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07002026 if (acceptTokenClass(EHTokRightBrace)) {
2027 // a zero-length initializer list
2028 node = intermediate.makeAggregate(loc);
2029 return true;
2030 }
2031
2032 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06002033 node = nullptr;
2034 do {
2035 // assignment_expression
2036 TIntermTyped* expr;
2037 if (! acceptAssignmentExpression(expr)) {
2038 expected("assignment expression in initializer list");
2039 return false;
2040 }
2041 node = intermediate.growAggregate(node, expr, loc);
2042
2043 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002044 if (acceptTokenClass(EHTokComma)) {
2045 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
2046 return true;
John Kessenich07354242016-07-01 19:58:06 -06002047 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06002048 }
John Kessenich07354242016-07-01 19:58:06 -06002049
2050 // RIGHT_BRACE
2051 if (acceptTokenClass(EHTokRightBrace))
2052 return true;
2053
2054 expected(", or }");
2055 return false;
2056 } while (true);
2057}
2058
John Kessenich34fb0362016-05-03 23:17:20 -06002059// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06002060// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06002061//
2062// a op (b op (c op d))
2063//
2064// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06002065// : initializer
2066// | conditional_expression
2067// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06002068//
2069bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2070{
John Kessenich07354242016-07-01 19:58:06 -06002071 // initializer
2072 if (peekTokenClass(EHTokLeftBrace)) {
2073 if (acceptInitializer(node))
2074 return true;
2075
2076 expected("initializer");
2077 return false;
2078 }
2079
John Kessenich00957f82016-07-27 10:39:57 -06002080 // conditional_expression
2081 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06002082 return false;
2083
John Kessenich07354242016-07-01 19:58:06 -06002084 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06002085 TOperator assignOp = HlslOpMap::assignment(peek());
2086 if (assignOp == EOpNull)
2087 return true;
2088
John Kessenich00957f82016-07-27 10:39:57 -06002089 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06002090 TSourceLoc loc = token.loc;
2091 advanceToken();
2092
John Kessenich00957f82016-07-27 10:39:57 -06002093 // conditional_expression assign_op conditional_expression ...
2094 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06002095 // gets the right-to-left associativity.
2096 TIntermTyped* rightNode = nullptr;
2097 if (! acceptAssignmentExpression(rightNode)) {
2098 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06002099 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002100 }
2101
John Kessenichd21baed2016-09-16 03:05:12 -06002102 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002103 node = parseContext.handleLvalue(loc, "assign", node);
2104
John Kessenichfea226b2016-07-28 17:53:56 -06002105 if (node == nullptr) {
2106 parseContext.error(loc, "could not create assignment", "", "");
2107 return false;
2108 }
John Kessenich34fb0362016-05-03 23:17:20 -06002109
2110 if (! peekTokenClass(EHTokComma))
2111 return true;
2112
2113 return true;
2114}
2115
John Kessenich00957f82016-07-27 10:39:57 -06002116// Accept a conditional expression, which associates right-to-left,
2117// accomplished by the "true" expression calling down to lower
2118// precedence levels than this level.
2119//
2120// conditional_expression
2121// : binary_expression
2122// | binary_expression QUESTION expression COLON assignment_expression
2123//
2124bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2125{
2126 // binary_expression
2127 if (! acceptBinaryExpression(node, PlLogicalOr))
2128 return false;
2129
2130 if (! acceptTokenClass(EHTokQuestion))
2131 return true;
2132
2133 TIntermTyped* trueNode = nullptr;
2134 if (! acceptExpression(trueNode)) {
2135 expected("expression after ?");
2136 return false;
2137 }
2138 TSourceLoc loc = token.loc;
2139
2140 if (! acceptTokenClass(EHTokColon)) {
2141 expected(":");
2142 return false;
2143 }
2144
2145 TIntermTyped* falseNode = nullptr;
2146 if (! acceptAssignmentExpression(falseNode)) {
2147 expected("expression after :");
2148 return false;
2149 }
2150
2151 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2152
2153 return true;
2154}
2155
John Kessenich34fb0362016-05-03 23:17:20 -06002156// Accept a binary expression, for binary operations that
2157// associate left-to-right. This is, it is implicit, for example
2158//
2159// ((a op b) op c) op d
2160//
2161// binary_expression
2162// : expression op expression op expression ...
2163//
2164// where 'expression' is the next higher level in precedence.
2165//
2166bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2167{
2168 if (precedenceLevel > PlMul)
2169 return acceptUnaryExpression(node);
2170
2171 // assignment_expression
2172 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2173 return false;
2174
John Kessenich34fb0362016-05-03 23:17:20 -06002175 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002176 TOperator op = HlslOpMap::binary(peek());
2177 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2178 if (tokenLevel < precedenceLevel)
2179 return true;
2180
John Kessenich34fb0362016-05-03 23:17:20 -06002181 // ... op
2182 TSourceLoc loc = token.loc;
2183 advanceToken();
2184
2185 // ... expression
2186 TIntermTyped* rightNode = nullptr;
2187 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2188 expected("expression");
2189 return false;
2190 }
2191
2192 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002193 if (node == nullptr) {
2194 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2195 return false;
2196 }
John Kessenich34fb0362016-05-03 23:17:20 -06002197 } while (true);
2198}
2199
2200// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002201// : (type) unary_expression
2202// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002203// | - unary_expression
2204// | ! unary_expression
2205// | ~ unary_expression
2206// | ++ unary_expression
2207// | -- unary_expression
2208// | postfix_expression
2209//
2210bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2211{
John Kessenich1cc1a282016-06-03 16:55:49 -06002212 // (type) unary_expression
2213 // Have to look two steps ahead, because this could be, e.g., a
2214 // postfix_expression instead, since that also starts with at "(".
2215 if (acceptTokenClass(EHTokLeftParen)) {
2216 TType castType;
2217 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002218 if (acceptTokenClass(EHTokRightParen)) {
2219 // We've matched "(type)" now, get the expression to cast
2220 TSourceLoc loc = token.loc;
2221 if (! acceptUnaryExpression(node))
2222 return false;
2223
2224 // Hook it up like a constructor
2225 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2226 if (constructorFunction == nullptr) {
2227 expected("type that can be constructed");
2228 return false;
2229 }
2230 TIntermTyped* arguments = nullptr;
2231 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2232 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2233
2234 return true;
2235 } else {
2236 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2237 // the '(int' part. We must back up twice.
2238 recedeToken();
2239 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002240 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002241 } else {
2242 // This isn't a type cast, but it still started "(", so if it is a
2243 // unary expression, it can only be a postfix_expression, so try that.
2244 // Back it up first.
2245 recedeToken();
2246 return acceptPostfixExpression(node);
2247 }
2248 }
2249
2250 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002251 TOperator unaryOp = HlslOpMap::preUnary(peek());
John Kessenichecba76f2017-01-06 00:34:48 -07002252
John Kessenich1cc1a282016-06-03 16:55:49 -06002253 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002254 if (unaryOp == EOpNull)
2255 return acceptPostfixExpression(node);
2256
2257 // op unary_expression
2258 TSourceLoc loc = token.loc;
2259 advanceToken();
2260 if (! acceptUnaryExpression(node))
2261 return false;
2262
2263 // + is a no-op
2264 if (unaryOp == EOpAdd)
2265 return true;
2266
2267 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002268
2269 // These unary ops require lvalues
2270 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2271 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002272
2273 return node != nullptr;
2274}
2275
2276// postfix_expression
2277// : LEFT_PAREN expression RIGHT_PAREN
2278// | literal
2279// | constructor
2280// | identifier
2281// | function_call
2282// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2283// | postfix_expression DOT IDENTIFIER
2284// | postfix_expression INC_OP
2285// | postfix_expression DEC_OP
2286//
2287bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2288{
2289 // Not implemented as self-recursive:
2290 // The logical "right recursion" is done with an loop at the end
2291
2292 // idToken will pick up either a variable or a function name in a function call
2293 HlslToken idToken;
2294
John Kessenich21472ae2016-06-04 11:46:33 -06002295 // Find something before the postfix operations, as they can't operate
2296 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002297 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002298 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002299 if (! acceptExpression(node)) {
2300 expected("expression");
2301 return false;
2302 }
2303 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002304 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002305 return false;
2306 }
John Kessenich34fb0362016-05-03 23:17:20 -06002307 } else if (acceptLiteral(node)) {
John Kessenichecba76f2017-01-06 00:34:48 -07002308 // literal (nothing else to do yet), go on to the
John Kessenich34fb0362016-05-03 23:17:20 -06002309 } else if (acceptConstructor(node)) {
2310 // constructor (nothing else to do yet)
2311 } else if (acceptIdentifier(idToken)) {
2312 // identifier or function_call name
2313 if (! peekTokenClass(EHTokLeftParen)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -07002314 node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002315 } else if (acceptFunctionCall(idToken, node)) {
2316 // function_call (nothing else to do yet)
2317 } else {
2318 expected("function call arguments");
2319 return false;
2320 }
John Kessenich21472ae2016-06-04 11:46:33 -06002321 } else {
2322 // nothing found, can't post operate
2323 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002324 }
2325
steve-lunarga2b01a02016-11-28 17:09:54 -07002326 // This is to guarantee we do this no matter how we get out of the stack frame.
2327 // This way there's no bug if an early return forgets to do it.
2328 struct tFinalize {
2329 tFinalize(HlslParseContext& p) : parseContext(p) { }
2330 ~tFinalize() { parseContext.finalizeFlattening(); }
2331 HlslParseContext& parseContext;
John Kessenich32fd5d22017-02-02 14:55:02 -07002332 private:
2333 tFinalize& operator=(tFinalize&) { }
steve-lunarga2b01a02016-11-28 17:09:54 -07002334 } finalize(parseContext);
2335
2336 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2337 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2338 // level: hence the init and finalize. Even though in practice these must be
2339 // constants, they are parsed no matter what.
2340 parseContext.initFlattening();
2341
John Kessenich21472ae2016-06-04 11:46:33 -06002342 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002343 do {
2344 TSourceLoc loc = token.loc;
2345 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002346
John Kessenich34fb0362016-05-03 23:17:20 -06002347 // Consume only a valid post-unary operator, otherwise we are done.
2348 switch (postOp) {
2349 case EOpIndexDirectStruct:
2350 case EOpIndexIndirect:
2351 case EOpPostIncrement:
2352 case EOpPostDecrement:
2353 advanceToken();
2354 break;
2355 default:
2356 return true;
2357 }
John Kessenich87142c72016-03-12 20:24:24 -07002358
John Kessenich34fb0362016-05-03 23:17:20 -06002359 // We have a valid post-unary operator, process it.
2360 switch (postOp) {
2361 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002362 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002363 // DOT IDENTIFIER
2364 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002365 HlslToken field;
2366 if (! acceptIdentifier(field)) {
2367 expected("swizzle or member");
2368 return false;
2369 }
LoopDawg4886f692016-06-29 10:58:58 -06002370
2371 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002372 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002373
2374 // 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 -07002375 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002376 if (! acceptFunctionCall(field, node, base)) {
2377 expected("function parameters");
2378 return false;
2379 }
2380 }
2381
John Kessenich34fb0362016-05-03 23:17:20 -06002382 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002383 }
John Kessenich34fb0362016-05-03 23:17:20 -06002384 case EOpIndexIndirect:
2385 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002386 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002387 TIntermTyped* indexNode = nullptr;
2388 if (! acceptExpression(indexNode) ||
2389 ! peekTokenClass(EHTokRightBracket)) {
2390 expected("expression followed by ']'");
2391 return false;
2392 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002393 advanceToken();
2394 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2395 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002396 }
2397 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002398 // INC_OP
2399 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002400 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002401 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002402 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002403 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002404 break;
2405 default:
2406 assert(0);
2407 break;
2408 }
2409 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002410}
2411
John Kessenichd016be12016-03-13 11:24:20 -06002412// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002413// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002414//
2415bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2416{
2417 // type
2418 TType type;
2419 if (acceptType(type)) {
2420 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2421 if (constructorFunction == nullptr)
2422 return false;
2423
2424 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002425 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002426 if (! acceptArguments(constructorFunction, arguments)) {
steve-lunarg5ca85ad2016-12-26 18:45:52 -07002427 // It's possible this is a type keyword used as an identifier. Put the token back
2428 // for later use.
2429 recedeToken();
John Kessenichd016be12016-03-13 11:24:20 -06002430 return false;
2431 }
2432
2433 // hook it up
2434 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2435
2436 return true;
2437 }
2438
2439 return false;
2440}
2441
John Kessenich34fb0362016-05-03 23:17:20 -06002442// The function_call identifier was already recognized, and passed in as idToken.
2443//
2444// function_call
2445// : [idToken] arguments
2446//
LoopDawg4886f692016-06-29 10:58:58 -06002447bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002448{
John Kessenich4678ca92016-05-13 09:33:42 -06002449 // arguments
2450 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2451 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002452
2453 // methods have an implicit first argument of the calling object.
2454 if (base != nullptr)
2455 parseContext.handleFunctionArgument(function, arguments, base);
2456
John Kessenich4678ca92016-05-13 09:33:42 -06002457 if (! acceptArguments(function, arguments))
2458 return false;
2459
2460 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2461
2462 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002463}
2464
John Kessenich87142c72016-03-12 20:24:24 -07002465// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002466// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002467//
John Kessenichd016be12016-03-13 11:24:20 -06002468// The arguments are pushed onto the 'function' argument list and
2469// onto the 'arguments' aggregate.
2470//
John Kessenich4678ca92016-05-13 09:33:42 -06002471bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002472{
John Kessenich078d7f22016-03-14 10:02:11 -06002473 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002474 if (! acceptTokenClass(EHTokLeftParen))
2475 return false;
2476
2477 do {
John Kessenichd016be12016-03-13 11:24:20 -06002478 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002479 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002480 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002481 break;
John Kessenichd016be12016-03-13 11:24:20 -06002482
2483 // hook it up
2484 parseContext.handleFunctionArgument(function, arguments, arg);
2485
John Kessenich078d7f22016-03-14 10:02:11 -06002486 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002487 if (! acceptTokenClass(EHTokComma))
2488 break;
2489 } while (true);
2490
John Kessenich078d7f22016-03-14 10:02:11 -06002491 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002492 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002493 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002494 return false;
2495 }
2496
2497 return true;
2498}
2499
2500bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2501{
2502 switch (token.tokenClass) {
2503 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002504 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002505 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002506 case EHTokUintConstant:
2507 node = intermediate.addConstantUnion(token.u, token.loc, true);
2508 break;
John Kessenich87142c72016-03-12 20:24:24 -07002509 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002510 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002511 break;
2512 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002513 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002514 break;
2515 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002516 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002517 break;
John Kessenich86f71382016-09-19 20:23:18 -06002518 case EHTokStringConstant:
2519 node = nullptr;
2520 break;
John Kessenich87142c72016-03-12 20:24:24 -07002521
2522 default:
2523 return false;
2524 }
2525
2526 advanceToken();
2527
2528 return true;
2529}
2530
John Kessenich5f934b02016-03-13 17:58:25 -06002531// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002532// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002533//
John Kessenich21472ae2016-06-04 11:46:33 -06002534bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002535{
John Kessenich21472ae2016-06-04 11:46:33 -06002536 TIntermAggregate* compoundStatement = nullptr;
2537
John Kessenich34fb0362016-05-03 23:17:20 -06002538 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002539 if (! acceptTokenClass(EHTokLeftBrace))
2540 return false;
2541
2542 // statement statement ...
2543 TIntermNode* statement = nullptr;
2544 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002545 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2546 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2547 branch->getFlowOp() == EOpDefault)) {
2548 // hook up individual subsequences within a switch statement
2549 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2550 compoundStatement = nullptr;
2551 } else {
2552 // hook it up to the growing compound statement
2553 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2554 }
John Kessenich5f934b02016-03-13 17:58:25 -06002555 }
John Kessenich34fb0362016-05-03 23:17:20 -06002556 if (compoundStatement)
2557 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002558
John Kessenich21472ae2016-06-04 11:46:33 -06002559 retStatement = compoundStatement;
2560
John Kessenich34fb0362016-05-03 23:17:20 -06002561 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002562 return acceptTokenClass(EHTokRightBrace);
2563}
2564
John Kessenich0d2b6de2016-06-05 11:23:11 -06002565bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2566{
2567 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002568 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002569 parseContext.popScope();
2570
2571 return result;
2572}
2573
John Kessenich077e0522016-06-09 02:02:17 -06002574bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002575{
John Kessenich077e0522016-06-09 02:02:17 -06002576 parseContext.pushScope();
2577 bool result = acceptCompoundStatement(statement);
2578 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002579
2580 return result;
2581}
2582
John Kessenich5f934b02016-03-13 17:58:25 -06002583// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002584// : attributes attributed_statement
2585//
2586// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002587// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002588// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002589// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002590// | declaration_statement
2591// | selection_statement
2592// | switch_statement
2593// | case_label
2594// | iteration_statement
2595// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002596//
2597bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2598{
John Kessenich21472ae2016-06-04 11:46:33 -06002599 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002600
John Kessenich21472ae2016-06-04 11:46:33 -06002601 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002602 TAttributeMap attributes;
2603 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002604
John Kessenich21472ae2016-06-04 11:46:33 -06002605 // attributed_statement
2606 switch (peek()) {
2607 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002608 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002609
John Kessenich21472ae2016-06-04 11:46:33 -06002610 case EHTokIf:
2611 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002612
John Kessenich21472ae2016-06-04 11:46:33 -06002613 case EHTokSwitch:
2614 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002615
John Kessenich21472ae2016-06-04 11:46:33 -06002616 case EHTokFor:
2617 case EHTokDo:
2618 case EHTokWhile:
2619 return acceptIterationStatement(statement);
2620
2621 case EHTokContinue:
2622 case EHTokBreak:
2623 case EHTokDiscard:
2624 case EHTokReturn:
2625 return acceptJumpStatement(statement);
2626
2627 case EHTokCase:
2628 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002629 case EHTokDefault:
2630 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002631
2632 case EHTokSemicolon:
2633 return acceptTokenClass(EHTokSemicolon);
2634
2635 case EHTokRightBrace:
2636 // Performance: not strictly necessary, but stops a bunch of hunting early,
2637 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002638 return false;
2639
John Kessenich21472ae2016-06-04 11:46:33 -06002640 default:
2641 {
2642 // declaration
2643 if (acceptDeclaration(statement))
2644 return true;
2645
2646 // expression
2647 TIntermTyped* node;
2648 if (acceptExpression(node))
2649 statement = node;
2650 else
2651 return false;
2652
2653 // SEMICOLON (following an expression)
2654 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002655 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002656 return false;
2657 }
2658 }
2659 }
2660
John Kessenich5f934b02016-03-13 17:58:25 -06002661 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002662}
2663
John Kessenich21472ae2016-06-04 11:46:33 -06002664// attributes
2665// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2666//
2667// attribute:
2668// : UNROLL
2669// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2670// | FASTOPT
2671// | ALLOW_UAV_CONDITION
2672// | BRANCH
2673// | FLATTEN
2674// | FORCECASE
2675// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002676// | DOMAIN
2677// | EARLYDEPTHSTENCIL
2678// | INSTANCE
2679// | MAXTESSFACTOR
2680// | OUTPUTCONTROLPOINTS
2681// | OUTPUTTOPOLOGY
2682// | PARTITIONING
2683// | PATCHCONSTANTFUNC
2684// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002685//
steve-lunarg1868b142016-10-20 13:07:10 -06002686void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002687{
steve-lunarg1868b142016-10-20 13:07:10 -06002688 // For now, accept the [ XXX(X) ] syntax, but drop all but
2689 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002690 // TODO: subset to correct set? Pass on?
2691 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002692 HlslToken idToken;
2693
John Kessenich0d2b6de2016-06-05 11:23:11 -06002694 // LEFT_BRACKET?
2695 if (! acceptTokenClass(EHTokLeftBracket))
2696 return;
2697
2698 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002699 if (acceptIdentifier(idToken)) {
2700 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002701 } else if (! peekTokenClass(EHTokRightBracket)) {
2702 expected("identifier");
2703 advanceToken();
2704 }
2705
steve-lunarga22f7db2016-11-11 08:17:44 -07002706 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002707
2708 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002709 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002710 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002711
John Kessenich0d2b6de2016-06-05 11:23:11 -06002712 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002713 bool expectingExpression = false;
John Kessenichecba76f2017-01-06 00:34:48 -07002714
steve-lunarga22f7db2016-11-11 08:17:44 -07002715 while (acceptAssignmentExpression(node)) {
2716 expectingExpression = false;
2717 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002718 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002719 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002720 }
2721
steve-lunarga22f7db2016-11-11 08:17:44 -07002722 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002723 if (! acceptTokenClass(EHTokRightParen))
2724 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002725
2726 // Error for partial or missing expression
2727 if (expectingExpression || expressions->getSequence().empty())
2728 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002729 }
2730
2731 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002732 if (!acceptTokenClass(EHTokRightBracket)) {
2733 expected("]");
2734 return;
2735 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002736
steve-lunarg1868b142016-10-20 13:07:10 -06002737 // Add any values we found into the attribute map. This accepts
2738 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002739 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002740 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002741}
2742
John Kessenich0d2b6de2016-06-05 11:23:11 -06002743// selection_statement
2744// : IF LEFT_PAREN expression RIGHT_PAREN statement
2745// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2746//
John Kessenich21472ae2016-06-04 11:46:33 -06002747bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2748{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002749 TSourceLoc loc = token.loc;
2750
2751 // IF
2752 if (! acceptTokenClass(EHTokIf))
2753 return false;
2754
2755 // so that something declared in the condition is scoped to the lifetimes
2756 // of the then-else statements
2757 parseContext.pushScope();
2758
2759 // LEFT_PAREN expression RIGHT_PAREN
2760 TIntermTyped* condition;
2761 if (! acceptParenExpression(condition))
2762 return false;
2763
2764 // create the child statements
2765 TIntermNodePair thenElse = { nullptr, nullptr };
2766
2767 // then statement
2768 if (! acceptScopedStatement(thenElse.node1)) {
2769 expected("then statement");
2770 return false;
2771 }
2772
2773 // ELSE
2774 if (acceptTokenClass(EHTokElse)) {
2775 // else statement
2776 if (! acceptScopedStatement(thenElse.node2)) {
2777 expected("else statement");
2778 return false;
2779 }
2780 }
2781
2782 // Put the pieces together
2783 statement = intermediate.addSelection(condition, thenElse, loc);
2784 parseContext.popScope();
2785
2786 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002787}
2788
John Kessenichd02dc5d2016-07-01 00:04:11 -06002789// switch_statement
2790// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2791//
John Kessenich21472ae2016-06-04 11:46:33 -06002792bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2793{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002794 // SWITCH
2795 TSourceLoc loc = token.loc;
2796 if (! acceptTokenClass(EHTokSwitch))
2797 return false;
2798
2799 // LEFT_PAREN expression RIGHT_PAREN
2800 parseContext.pushScope();
2801 TIntermTyped* switchExpression;
2802 if (! acceptParenExpression(switchExpression)) {
2803 parseContext.popScope();
2804 return false;
2805 }
2806
2807 // compound_statement
2808 parseContext.pushSwitchSequence(new TIntermSequence);
2809 bool statementOkay = acceptCompoundStatement(statement);
2810 if (statementOkay)
2811 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2812
2813 parseContext.popSwitchSequence();
2814 parseContext.popScope();
2815
2816 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002817}
2818
John Kessenich119f8f62016-06-05 15:44:07 -06002819// iteration_statement
2820// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2821// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2822// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2823//
2824// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002825bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2826{
John Kessenich119f8f62016-06-05 15:44:07 -06002827 TSourceLoc loc = token.loc;
2828 TIntermTyped* condition = nullptr;
2829
2830 EHlslTokenClass loop = peek();
2831 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2832
2833 // WHILE or DO or FOR
2834 advanceToken();
2835
2836 switch (loop) {
2837 case EHTokWhile:
2838 // so that something declared in the condition is scoped to the lifetime
2839 // of the while sub-statement
2840 parseContext.pushScope();
2841 parseContext.nestLooping();
2842
2843 // LEFT_PAREN condition RIGHT_PAREN
2844 if (! acceptParenExpression(condition))
2845 return false;
2846
2847 // statement
2848 if (! acceptScopedStatement(statement)) {
2849 expected("while sub-statement");
2850 return false;
2851 }
2852
2853 parseContext.unnestLooping();
2854 parseContext.popScope();
2855
2856 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2857
2858 return true;
2859
2860 case EHTokDo:
2861 parseContext.nestLooping();
2862
2863 if (! acceptTokenClass(EHTokLeftBrace))
2864 expected("{");
2865
2866 // statement
2867 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2868 expected("do sub-statement");
2869 return false;
2870 }
2871
2872 if (! acceptTokenClass(EHTokRightBrace))
2873 expected("}");
2874
2875 // WHILE
2876 if (! acceptTokenClass(EHTokWhile)) {
2877 expected("while");
2878 return false;
2879 }
2880
2881 // LEFT_PAREN condition RIGHT_PAREN
2882 TIntermTyped* condition;
2883 if (! acceptParenExpression(condition))
2884 return false;
2885
2886 if (! acceptTokenClass(EHTokSemicolon))
2887 expected(";");
2888
2889 parseContext.unnestLooping();
2890
2891 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2892
2893 return true;
2894
2895 case EHTokFor:
2896 {
2897 // LEFT_PAREN
2898 if (! acceptTokenClass(EHTokLeftParen))
2899 expected("(");
2900
2901 // so that something declared in the condition is scoped to the lifetime
2902 // of the for sub-statement
2903 parseContext.pushScope();
2904
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002905 // initializer
2906 TIntermNode* initNode = nullptr;
2907 if (! acceptControlDeclaration(initNode)) {
2908 TIntermTyped* initExpr = nullptr;
2909 acceptExpression(initExpr);
2910 initNode = initExpr;
2911 }
2912 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002913 if (! acceptTokenClass(EHTokSemicolon))
2914 expected(";");
2915
2916 parseContext.nestLooping();
2917
2918 // condition SEMI_COLON
2919 acceptExpression(condition);
2920 if (! acceptTokenClass(EHTokSemicolon))
2921 expected(";");
2922
2923 // iterator SEMI_COLON
2924 TIntermTyped* iterator = nullptr;
2925 acceptExpression(iterator);
2926 if (! acceptTokenClass(EHTokRightParen))
2927 expected(")");
2928
2929 // statement
2930 if (! acceptScopedStatement(statement)) {
2931 expected("for sub-statement");
2932 return false;
2933 }
2934
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002935 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002936
2937 parseContext.popScope();
2938 parseContext.unnestLooping();
2939
2940 return true;
2941 }
2942
2943 default:
2944 return false;
2945 }
John Kessenich21472ae2016-06-04 11:46:33 -06002946}
2947
2948// jump_statement
2949// : CONTINUE SEMICOLON
2950// | BREAK SEMICOLON
2951// | DISCARD SEMICOLON
2952// | RETURN SEMICOLON
2953// | RETURN expression SEMICOLON
2954//
2955bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2956{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002957 EHlslTokenClass jump = peek();
2958 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002959 case EHTokContinue:
2960 case EHTokBreak:
2961 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002962 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002963 advanceToken();
2964 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002965 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002966 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002967 return false;
2968 }
John Kessenich21472ae2016-06-04 11:46:33 -06002969
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002970 switch (jump) {
2971 case EHTokContinue:
2972 statement = intermediate.addBranch(EOpContinue, token.loc);
2973 break;
2974 case EHTokBreak:
2975 statement = intermediate.addBranch(EOpBreak, token.loc);
2976 break;
2977 case EHTokDiscard:
2978 statement = intermediate.addBranch(EOpKill, token.loc);
2979 break;
2980
2981 case EHTokReturn:
2982 {
2983 // expression
2984 TIntermTyped* node;
2985 if (acceptExpression(node)) {
2986 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002987 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002988 } else
2989 statement = intermediate.addBranch(EOpReturn, token.loc);
2990 break;
2991 }
2992
2993 default:
2994 assert(0);
2995 return false;
2996 }
2997
2998 // SEMICOLON
2999 if (! acceptTokenClass(EHTokSemicolon))
3000 expected(";");
John Kessenichecba76f2017-01-06 00:34:48 -07003001
John Kessenich5bc4d9a2016-06-20 01:22:38 -06003002 return true;
3003}
John Kessenich21472ae2016-06-04 11:46:33 -06003004
John Kessenichd02dc5d2016-07-01 00:04:11 -06003005// case_label
3006// : CASE expression COLON
3007//
John Kessenich21472ae2016-06-04 11:46:33 -06003008bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3009{
John Kessenichd02dc5d2016-07-01 00:04:11 -06003010 TSourceLoc loc = token.loc;
3011 if (! acceptTokenClass(EHTokCase))
3012 return false;
3013
3014 TIntermTyped* expression;
3015 if (! acceptExpression(expression)) {
3016 expected("case expression");
3017 return false;
3018 }
3019
3020 if (! acceptTokenClass(EHTokColon)) {
3021 expected(":");
3022 return false;
3023 }
3024
3025 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3026
3027 return true;
3028}
3029
3030// default_label
3031// : DEFAULT COLON
3032//
3033bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3034{
3035 TSourceLoc loc = token.loc;
3036 if (! acceptTokenClass(EHTokDefault))
3037 return false;
3038
3039 if (! acceptTokenClass(EHTokColon)) {
3040 expected(":");
3041 return false;
3042 }
3043
3044 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3045
3046 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06003047}
3048
John Kessenich19b92ff2016-06-19 11:50:34 -06003049// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06003050// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3051// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06003052//
3053void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3054{
3055 arraySizes = nullptr;
3056
steve-lunarg7b211a32016-10-13 12:26:18 -06003057 // Early-out if there aren't any array dimensions
3058 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06003059 return;
3060
steve-lunarg7b211a32016-10-13 12:26:18 -06003061 // 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 -06003062 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06003063
3064 // Collect each array dimension.
3065 while (acceptTokenClass(EHTokLeftBracket)) {
3066 TSourceLoc loc = token.loc;
3067 TIntermTyped* sizeExpr = nullptr;
3068
3069 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
3070 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3071
3072 if (! acceptTokenClass(EHTokRightBracket)) {
3073 expected("]");
3074 return;
3075 }
3076
3077 if (hasArraySize) {
3078 TArraySize arraySize;
3079 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3080 arraySizes->addInnerSize(arraySize);
3081 } else {
3082 arraySizes->addInnerSize(0); // sized by initializers.
3083 }
steve-lunarg265c0612016-09-27 10:57:35 -06003084 }
John Kessenich19b92ff2016-06-19 11:50:34 -06003085}
3086
John Kessenich630dd7d2016-06-12 23:52:12 -06003087// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06003088// : COLON semantic // optional
3089// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
3090// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06003091// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06003092// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06003093//
John Kessenich7735b942016-09-05 12:40:06 -06003094void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06003095{
John Kessenich630dd7d2016-06-12 23:52:12 -06003096 do {
John Kessenichecba76f2017-01-06 00:34:48 -07003097 // COLON
John Kessenich630dd7d2016-06-12 23:52:12 -06003098 if (acceptTokenClass(EHTokColon)) {
3099 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06003100 if (peekTokenClass(EHTokLayout))
3101 acceptLayoutQualifierList(qualifier);
3102 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06003103 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003104 if (! acceptTokenClass(EHTokLeftParen)) {
3105 expected("(");
3106 return;
3107 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003108 HlslToken locationToken;
3109 if (! acceptIdentifier(locationToken)) {
3110 expected("c[subcomponent][.component]");
3111 return;
3112 }
3113 HlslToken componentToken;
3114 if (acceptTokenClass(EHTokDot)) {
3115 if (! acceptIdentifier(componentToken)) {
3116 expected("component");
3117 return;
3118 }
3119 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003120 if (! acceptTokenClass(EHTokRightParen)) {
3121 expected(")");
3122 break;
3123 }
John Kessenich7735b942016-09-05 12:40:06 -06003124 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003125 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003126 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06003127 return;
3128 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003129 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3130 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003131 if (! acceptTokenClass(EHTokLeftParen)) {
3132 expected("(");
3133 return;
3134 }
John Kessenichb38f0712016-07-30 10:29:54 -06003135 HlslToken registerDesc; // for Type#
3136 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003137 if (! acceptIdentifier(registerDesc)) {
3138 expected("register number description");
3139 return;
3140 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003141 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3142 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003143 // Then we didn't really see the registerDesc yet, it was
3144 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003145 profile = registerDesc;
3146 if (! acceptIdentifier(registerDesc)) {
3147 expected("register number description");
3148 return;
3149 }
3150 }
John Kessenichb38f0712016-07-30 10:29:54 -06003151 int subComponent = 0;
3152 if (acceptTokenClass(EHTokLeftBracket)) {
3153 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3154 if (! peekTokenClass(EHTokIntConstant)) {
3155 expected("literal integer");
3156 return;
3157 }
3158 subComponent = token.i;
3159 advanceToken();
3160 if (! acceptTokenClass(EHTokRightBracket)) {
3161 expected("]");
3162 break;
3163 }
3164 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003165 // (COMMA SPACEN)opt
3166 HlslToken spaceDesc;
3167 if (acceptTokenClass(EHTokComma)) {
3168 if (! acceptIdentifier(spaceDesc)) {
3169 expected ("space identifier");
3170 return;
3171 }
3172 }
3173 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003174 if (! acceptTokenClass(EHTokRightParen)) {
3175 expected(")");
3176 break;
3177 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003178 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003179 } else {
3180 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003181 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003182 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003183 } else if (peekTokenClass(EHTokLeftAngle))
3184 acceptAnnotations(qualifier);
3185 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003186 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003187
John Kessenich630dd7d2016-06-12 23:52:12 -06003188 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003189}
3190
John Kesseniche01a9bc2016-03-12 20:11:22 -07003191} // end namespace glslang