blob: 4b2d6a2308fff339a94f93575c66e922baa3e8a9 [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
2//Copyright (C) 2016 Google, Inc.
LoopDawg6daaa4f2016-06-23 19:13:48 -06003//Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
5//All rights reserved.
6//
7//Redistribution and use in source and binary forms, with or without
8//modification, are permitted provided that the following conditions
9//are met:
10//
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//
23//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.
35//
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"
56
57namespace glslang {
58
59// Root entry point to this recursive decent parser.
60// Return true if compilation unit was successfully accepted.
61bool HlslGrammar::parse()
62{
63 advanceToken();
64 return acceptCompilationUnit();
65}
66
67void HlslGrammar::expected(const char* syntax)
68{
69 parseContext.error(token.loc, "Expected", syntax, "");
70}
71
LoopDawg4886f692016-06-29 10:58:58 -060072void HlslGrammar::unimplemented(const char* error)
73{
74 parseContext.error(token.loc, "Unimplemented", error, "");
75}
76
John Kessenichaecd4972016-03-14 10:46:34 -060077// Only process the next token if it is an identifier.
78// Return true if it was an identifier.
79bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
80{
81 if (peekTokenClass(EHTokIdentifier)) {
82 idToken = token;
83 advanceToken();
84 return true;
85 }
86
87 return false;
88}
89
John Kesseniche01a9bc2016-03-12 20:11:22 -070090// compilationUnit
91// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -060092// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -070093//
94bool HlslGrammar::acceptCompilationUnit()
95{
John Kessenichd016be12016-03-13 11:24:20 -060096 TIntermNode* unitNode = nullptr;
97
John Kessenich9c86c6a2016-05-03 22:49:24 -060098 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -060099 // HLSL allows semicolons between global declarations, e.g, between functions.
100 if (acceptTokenClass(EHTokSemicolon))
101 continue;
102
John Kessenichd016be12016-03-13 11:24:20 -0600103 // externalDeclaration
104 TIntermNode* declarationNode;
105 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700106 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600107
108 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600109 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700110 }
111
John Kessenichd016be12016-03-13 11:24:20 -0600112 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600113 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600114
John Kesseniche01a9bc2016-03-12 20:11:22 -0700115 return true;
116}
117
LoopDawg4886f692016-06-29 10:58:58 -0600118// sampler_state
119// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
120//
121// sampler_state_assignment
122// : sampler_state_identifier EQUAL value SEMICOLON
123//
124// sampler_state_identifier
125// : ADDRESSU
126// | ADDRESSV
127// | ADDRESSW
128// | BORDERCOLOR
129// | FILTER
130// | MAXANISOTROPY
131// | MAXLOD
132// | MINLOD
133// | MIPLODBIAS
134//
135bool HlslGrammar::acceptSamplerState()
136{
137 // TODO: this should be genericized to accept a list of valid tokens and
138 // return token/value pairs. Presently it is specific to texture values.
139
140 if (! acceptTokenClass(EHTokLeftBrace))
141 return true;
142
143 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
144
145 do {
146 // read state name
147 HlslToken state;
148 if (! acceptIdentifier(state))
149 break; // end of list
150
151 // FXC accepts any case
152 TString stateName = *state.string;
153 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
154
155 if (! acceptTokenClass(EHTokAssign)) {
156 expected("assign");
157 return false;
158 }
159
160 if (stateName == "minlod" || stateName == "maxlod") {
161 if (! peekTokenClass(EHTokIntConstant)) {
162 expected("integer");
163 return false;
164 }
165
166 TIntermTyped* lod = nullptr;
167 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
168 return false;
169 } else if (stateName == "maxanisotropy") {
170 if (! peekTokenClass(EHTokIntConstant)) {
171 expected("integer");
172 return false;
173 }
174
175 TIntermTyped* maxAnisotropy = nullptr;
176 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
177 return false;
178 } else if (stateName == "filter") {
179 HlslToken filterMode;
180 if (! acceptIdentifier(filterMode)) {
181 expected("filter mode");
182 return false;
183 }
184 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
185 HlslToken addrMode;
186 if (! acceptIdentifier(addrMode)) {
187 expected("texture address mode");
188 return false;
189 }
190 } else if (stateName == "miplodbias") {
191 TIntermTyped* lodBias = nullptr;
192 if (! acceptLiteral(lodBias)) {
193 expected("lod bias");
194 return false;
195 }
196 } else if (stateName == "bordercolor") {
197 return false;
198 } else {
199 expected("texture state");
200 return false;
201 }
202
203 // SEMICOLON
204 if (! acceptTokenClass(EHTokSemicolon)) {
205 expected("semicolon");
206 return false;
207 }
208 } while (true);
209
210 if (! acceptTokenClass(EHTokRightBrace))
211 return false;
212
213 return true;
214}
215
216// sampler_declaration_dx9
217// : SAMPLER identifier EQUAL sampler_type sampler_state
218//
John Kesseniche4821e42016-07-16 10:19:43 -0600219bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600220{
221 if (! acceptTokenClass(EHTokSampler))
222 return false;
223
224 // TODO: remove this when DX9 style declarations are implemented.
225 unimplemented("Direct3D 9 sampler declaration");
226
227 // read sampler name
228 HlslToken name;
229 if (! acceptIdentifier(name)) {
230 expected("sampler name");
231 return false;
232 }
233
234 if (! acceptTokenClass(EHTokAssign)) {
235 expected("=");
236 return false;
237 }
238
239 return false;
240}
241
242
John Kesseniche01a9bc2016-03-12 20:11:22 -0700243// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600244// : sampler_declaration_dx9 post_decls SEMICOLON
245// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600246// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600247// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600248// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700249//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600250// declarator_list
251// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600252//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600253// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600254// : identifier array_specifier post_decls
255// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600256// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600257//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600258// Parsing has to go pretty far in to know whether it's a variable, prototype, or
259// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600260// as above. (The 'identifier' in the first item in init_declarator list is the
261// same as 'identifier' for function declarations.)
262//
263// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600264// or a function body.
265//
266bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700267{
John Kessenichd016be12016-03-13 11:24:20 -0600268 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600269 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600270
John Kessenich5e69ec62016-07-05 00:02:40 -0600271 // typedef
272 bool typedefDecl = acceptTokenClass(EHTokTypedef);
273
John Kesseniche82061d2016-09-27 14:38:57 -0600274 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600275
276 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600277 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
278 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
279 // HLSL shaders, this will have to be a master level switch
280 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
281 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400282
John Kesseniche82061d2016-09-27 14:38:57 -0600283 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400284 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600285
286 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600287 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700288 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600289
John Kessenich87142c72016-03-12 20:24:24 -0700290 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600291 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600292 while (acceptIdentifier(idToken)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600293 // function_parameters
John Kesseniche82061d2016-09-27 14:38:57 -0600294 TFunction& function = *new TFunction(idToken.string, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600295 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600296 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600297 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600298
John Kessenichd5ed0b62016-07-04 17:32:45 -0600299 // compound_statement (function body definition) or just a prototype?
300 if (peekTokenClass(EHTokLeftBrace)) {
301 if (list)
302 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600303 if (typedefDecl)
304 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600305 return acceptFunctionDefinition(function, node);
John Kessenich5e69ec62016-07-05 00:02:40 -0600306 } else {
307 if (typedefDecl)
308 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600309 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600310 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600311 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600312 // A variable declaration. Fix the storage qualifier if it's a global.
313 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
314 declaredType.getQualifier().storage = EvqUniform;
315
John Kesseniche82061d2016-09-27 14:38:57 -0600316 // We can handle multiple variables per type declaration, so
317 // the number of types can expand when arrayness is different.
318 TType variableType;
319 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600320
John Kesseniche82061d2016-09-27 14:38:57 -0600321 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600322 TArraySizes* arraySizes = nullptr;
323 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600324
John Kesseniche82061d2016-09-27 14:38:57 -0600325 // Fix arrayness in the variableType
326 if (declaredType.isImplicitlySizedArray()) {
327 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
328 // of different sizes, for this case sharing the shallow copy of arrayness
329 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
330 variableType.newArraySizes(declaredType.getArraySizes());
331 }
332 if (arraySizes || variableType.isArray()) {
333 // In the most general case, arrayness is potentially coming both from the
334 // declared type and from the variable: "int[] a[];" or just one or the other.
335 // Merge it all to the variableType, so all arrayness is part of the variableType.
336 parseContext.arrayDimMerge(variableType, arraySizes);
337 }
338
LoopDawg4886f692016-06-29 10:58:58 -0600339 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600340 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600341 if (! acceptSamplerState())
342 return false;
343 }
344
John Kessenichd5ed0b62016-07-04 17:32:45 -0600345 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600346 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600347
348 // EQUAL assignment_expression
349 TIntermTyped* expressionNode = nullptr;
350 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600351 if (typedefDecl)
352 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600353 if (! acceptAssignmentExpression(expressionNode)) {
354 expected("initializer");
355 return false;
356 }
357 }
358
John Kessenich6dbc0a72016-09-27 19:13:05 -0600359 // Hand off the actual declaration
360
361 // TODO: things scoped within an annotation need their own name space;
362 // TODO: strings are not yet handled.
363 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
364 if (typedefDecl)
365 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
366 else if (variableType.getBasicType() == EbtBlock)
367 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
368 else {
John Kessenichf571d0c2016-10-01 12:35:01 -0600369 if (variableType.getQualifier().storage == EvqUniform && ! variableType.isOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600370 // this isn't really an individual variable, but a member of the $Global buffer
371 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
372 } else {
373 // Declare the variable and add any initializer code to the AST.
374 // The top-level node is always made into an aggregate, as that's
375 // historically how the AST has been.
376 node = intermediate.growAggregate(node,
377 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
378 expressionNode),
379 idToken.loc);
380 }
381 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600382 }
John Kessenich5f934b02016-03-13 17:58:25 -0600383 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600384
385 if (acceptTokenClass(EHTokComma)) {
386 list = true;
387 continue;
388 }
389 };
390
391 // The top-level node is a sequence.
392 if (node != nullptr)
393 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700394
John Kessenich078d7f22016-03-14 10:02:11 -0600395 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600396 if (! acceptTokenClass(EHTokSemicolon)) {
397 expected(";");
398 return false;
399 }
400
John Kesseniche01a9bc2016-03-12 20:11:22 -0700401 return true;
402}
403
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600404// control_declaration
405// : fully_specified_type identifier EQUAL expression
406//
407bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
408{
409 node = nullptr;
410
411 // fully_specified_type
412 TType type;
413 if (! acceptFullySpecifiedType(type))
414 return false;
415
416 // identifier
417 HlslToken idToken;
418 if (! acceptIdentifier(idToken)) {
419 expected("identifier");
420 return false;
421 }
422
423 // EQUAL
424 TIntermTyped* expressionNode = nullptr;
425 if (! acceptTokenClass(EHTokAssign)) {
426 expected("=");
427 return false;
428 }
429
430 // expression
431 if (! acceptExpression(expressionNode)) {
432 expected("initializer");
433 return false;
434 }
435
John Kesseniche82061d2016-09-27 14:38:57 -0600436 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600437
438 return true;
439}
440
John Kessenich87142c72016-03-12 20:24:24 -0700441// fully_specified_type
442// : type_specifier
443// | type_qualifier type_specifier
444//
445bool HlslGrammar::acceptFullySpecifiedType(TType& type)
446{
447 // type_qualifier
448 TQualifier qualifier;
449 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600450 if (! acceptQualifier(qualifier))
451 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600452 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700453
454 // type_specifier
455 if (! acceptType(type))
456 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600457 if (type.getBasicType() == EbtBlock) {
458 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600459 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600460 // further, it can create an anonymous instance of the block
461 if (peekTokenClass(EHTokSemicolon))
462 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600463 } else {
464 // Some qualifiers are set when parsing the type. Merge those with
465 // whatever comes from acceptQualifier.
466 assert(qualifier.layoutFormat == ElfNone);
467 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600468 qualifier.precision = type.getQualifier().precision;
John Kessenich3d157c52016-07-25 16:05:33 -0600469 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600470 }
John Kessenich87142c72016-03-12 20:24:24 -0700471
472 return true;
473}
474
John Kessenich630dd7d2016-06-12 23:52:12 -0600475// type_qualifier
476// : qualifier qualifier ...
477//
478// Zero or more of these, so this can't return false.
479//
John Kessenichb9e39122016-08-17 10:22:08 -0600480bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700481{
John Kessenich630dd7d2016-06-12 23:52:12 -0600482 do {
483 switch (peek()) {
484 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600485 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600486 break;
487 case EHTokExtern:
488 // TODO: no meaning in glslang?
489 break;
490 case EHTokShared:
491 // TODO: hint
492 break;
493 case EHTokGroupShared:
494 qualifier.storage = EvqShared;
495 break;
496 case EHTokUniform:
497 qualifier.storage = EvqUniform;
498 break;
499 case EHTokConst:
500 qualifier.storage = EvqConst;
501 break;
502 case EHTokVolatile:
503 qualifier.volatil = true;
504 break;
505 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600506 qualifier.smooth = true;
507 break;
508 case EHTokCentroid:
509 qualifier.centroid = true;
510 break;
511 case EHTokNointerpolation:
512 qualifier.flat = true;
513 break;
514 case EHTokNoperspective:
515 qualifier.nopersp = true;
516 break;
517 case EHTokSample:
518 qualifier.sample = true;
519 break;
520 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600521 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600522 break;
523 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600524 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600525 break;
526 case EHTokPrecise:
527 qualifier.noContraction = true;
528 break;
LoopDawg9249c702016-07-12 20:44:32 -0600529 case EHTokIn:
530 qualifier.storage = EvqIn;
531 break;
532 case EHTokOut:
533 qualifier.storage = EvqOut;
534 break;
535 case EHTokInOut:
536 qualifier.storage = EvqInOut;
537 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600538 case EHTokLayout:
539 if (! acceptLayoutQualifierList(qualifier))
540 return false;
541 continue;
John Kessenich630dd7d2016-06-12 23:52:12 -0600542 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600543 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600544 }
545 advanceToken();
546 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700547}
548
John Kessenichb9e39122016-08-17 10:22:08 -0600549// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600550// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600551//
552// layout_qualifier
553// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600554// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600555//
556// Zero or more of these, so this can't return false.
557//
558bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
559{
560 if (! acceptTokenClass(EHTokLayout))
561 return false;
562
563 // LEFT_PAREN
564 if (! acceptTokenClass(EHTokLeftParen))
565 return false;
566
567 do {
568 // identifier
569 HlslToken idToken;
570 if (! acceptIdentifier(idToken))
571 break;
572
573 // EQUAL expression
574 if (acceptTokenClass(EHTokAssign)) {
575 TIntermTyped* expr;
576 if (! acceptConditionalExpression(expr)) {
577 expected("expression");
578 return false;
579 }
580 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
581 } else
582 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
583
584 // COMMA
585 if (! acceptTokenClass(EHTokComma))
586 break;
587 } while (true);
588
589 // RIGHT_PAREN
590 if (! acceptTokenClass(EHTokRightParen)) {
591 expected(")");
592 return false;
593 }
594
595 return true;
596}
597
LoopDawg6daaa4f2016-06-23 19:13:48 -0600598// template_type
599// : FLOAT
600// | DOUBLE
601// | INT
602// | DWORD
603// | UINT
604// | BOOL
605//
606bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
607{
608 switch (peek()) {
609 case EHTokFloat:
610 basicType = EbtFloat;
611 break;
612 case EHTokDouble:
613 basicType = EbtDouble;
614 break;
615 case EHTokInt:
616 case EHTokDword:
617 basicType = EbtInt;
618 break;
619 case EHTokUint:
620 basicType = EbtUint;
621 break;
622 case EHTokBool:
623 basicType = EbtBool;
624 break;
625 default:
626 return false;
627 }
628
629 advanceToken();
630
631 return true;
632}
633
634// vector_template_type
635// : VECTOR
636// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
637//
638bool HlslGrammar::acceptVectorTemplateType(TType& type)
639{
640 if (! acceptTokenClass(EHTokVector))
641 return false;
642
643 if (! acceptTokenClass(EHTokLeftAngle)) {
644 // in HLSL, 'vector' alone means float4.
645 new(&type) TType(EbtFloat, EvqTemporary, 4);
646 return true;
647 }
648
649 TBasicType basicType;
650 if (! acceptTemplateType(basicType)) {
651 expected("scalar type");
652 return false;
653 }
654
655 // COMMA
656 if (! acceptTokenClass(EHTokComma)) {
657 expected(",");
658 return false;
659 }
660
661 // integer
662 if (! peekTokenClass(EHTokIntConstant)) {
663 expected("literal integer");
664 return false;
665 }
666
667 TIntermTyped* vecSize;
668 if (! acceptLiteral(vecSize))
669 return false;
670
671 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
672
673 new(&type) TType(basicType, EvqTemporary, vecSizeI);
674
675 if (vecSizeI == 1)
676 type.makeVector();
677
678 if (!acceptTokenClass(EHTokRightAngle)) {
679 expected("right angle bracket");
680 return false;
681 }
682
683 return true;
684}
685
686// matrix_template_type
687// : MATRIX
688// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
689//
690bool HlslGrammar::acceptMatrixTemplateType(TType& type)
691{
692 if (! acceptTokenClass(EHTokMatrix))
693 return false;
694
695 if (! acceptTokenClass(EHTokLeftAngle)) {
696 // in HLSL, 'matrix' alone means float4x4.
697 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
698 return true;
699 }
700
701 TBasicType basicType;
702 if (! acceptTemplateType(basicType)) {
703 expected("scalar type");
704 return false;
705 }
706
707 // COMMA
708 if (! acceptTokenClass(EHTokComma)) {
709 expected(",");
710 return false;
711 }
712
713 // integer rows
714 if (! peekTokenClass(EHTokIntConstant)) {
715 expected("literal integer");
716 return false;
717 }
718
719 TIntermTyped* rows;
720 if (! acceptLiteral(rows))
721 return false;
722
723 // COMMA
724 if (! acceptTokenClass(EHTokComma)) {
725 expected(",");
726 return false;
727 }
728
729 // integer cols
730 if (! peekTokenClass(EHTokIntConstant)) {
731 expected("literal integer");
732 return false;
733 }
734
735 TIntermTyped* cols;
736 if (! acceptLiteral(cols))
737 return false;
738
739 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600740 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
741 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600742
743 if (!acceptTokenClass(EHTokRightAngle)) {
744 expected("right angle bracket");
745 return false;
746 }
747
748 return true;
749}
750
John Kessenicha1e2d492016-09-20 13:22:58 -0600751// annotations
752// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600753//
John Kessenicha1e2d492016-09-20 13:22:58 -0600754bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600755{
John Kessenicha1e2d492016-09-20 13:22:58 -0600756 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600757 return false;
758
John Kessenicha1e2d492016-09-20 13:22:58 -0600759 // note that we are nesting a name space
760 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600761
762 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
763 do {
764 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
765 while (acceptTokenClass(EHTokSemicolon))
766 ;
767
768 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600769 break;
John Kessenich86f71382016-09-19 20:23:18 -0600770
771 // declaration
772 TIntermNode* node;
773 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600774 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600775 return false;
776 }
777 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600778
779 parseContext.unnestAnnotations();
780 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600781}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600782
LoopDawg4886f692016-06-29 10:58:58 -0600783// sampler_type
784// : SAMPLER
785// | SAMPLER1D
786// | SAMPLER2D
787// | SAMPLER3D
788// | SAMPLERCUBE
789// | SAMPLERSTATE
790// | SAMPLERCOMPARISONSTATE
791bool HlslGrammar::acceptSamplerType(TType& type)
792{
793 // read sampler type
794 const EHlslTokenClass samplerType = peek();
795
LoopDawga78b0292016-07-19 14:28:05 -0600796 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600797 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600798
LoopDawga78b0292016-07-19 14:28:05 -0600799 bool isShadow = false;
800
LoopDawg4886f692016-06-29 10:58:58 -0600801 switch (samplerType) {
802 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600803 case EHTokSampler1d: /*dim = Esd1D*/; break;
804 case EHTokSampler2d: /*dim = Esd2D*/; break;
805 case EHTokSampler3d: /*dim = Esd3D*/; break;
806 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600807 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600808 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600809 default:
810 return false; // not a sampler declaration
811 }
812
813 advanceToken(); // consume the sampler type keyword
814
815 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600816
817 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600818 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600819
820 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
821
822 return true;
823}
824
825// texture_type
826// | BUFFER
827// | TEXTURE1D
828// | TEXTURE1DARRAY
829// | TEXTURE2D
830// | TEXTURE2DARRAY
831// | TEXTURE3D
832// | TEXTURECUBE
833// | TEXTURECUBEARRAY
834// | TEXTURE2DMS
835// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600836// | RWBUFFER
837// | RWTEXTURE1D
838// | RWTEXTURE1DARRAY
839// | RWTEXTURE2D
840// | RWTEXTURE2DARRAY
841// | RWTEXTURE3D
842
LoopDawg4886f692016-06-29 10:58:58 -0600843bool HlslGrammar::acceptTextureType(TType& type)
844{
845 const EHlslTokenClass textureType = peek();
846
847 TSamplerDim dim = EsdNone;
848 bool array = false;
849 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600850 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600851
852 switch (textureType) {
853 case EHTokBuffer: dim = EsdBuffer; break;
854 case EHTokTexture1d: dim = Esd1D; break;
855 case EHTokTexture1darray: dim = Esd1D; array = true; break;
856 case EHTokTexture2d: dim = Esd2D; break;
857 case EHTokTexture2darray: dim = Esd2D; array = true; break;
858 case EHTokTexture3d: dim = Esd3D; break;
859 case EHTokTextureCube: dim = EsdCube; break;
860 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
861 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
862 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -0600863 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
864 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
865 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
866 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
867 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
868 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600869 default:
870 return false; // not a texture declaration
871 }
872
873 advanceToken(); // consume the texture object keyword
874
875 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
876
877 TIntermTyped* msCount = nullptr;
878
steve-lunargbb0183f2016-10-04 16:58:14 -0600879 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -0600880 if (acceptTokenClass(EHTokLeftAngle)) {
881 if (! acceptType(txType)) {
882 expected("scalar or vector type");
883 return false;
884 }
885
886 const TBasicType basicRetType = txType.getBasicType() ;
887
888 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
889 unimplemented("basic type in texture");
890 return false;
891 }
892
steve-lunargd53f7172016-07-27 15:46:48 -0600893 // Buffers can handle small mats if they fit in 4 components
894 if (dim == EsdBuffer && txType.isMatrix()) {
895 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
896 expected("components < 4 in matrix buffer type");
897 return false;
898 }
899
900 // TODO: except we don't handle it yet...
901 unimplemented("matrix type in buffer");
902 return false;
903 }
904
LoopDawg4886f692016-06-29 10:58:58 -0600905 if (!txType.isScalar() && !txType.isVector()) {
906 expected("scalar or vector type");
907 return false;
908 }
909
LoopDawg4886f692016-06-29 10:58:58 -0600910 if (ms && acceptTokenClass(EHTokComma)) {
911 // read sample count for multisample types, if given
912 if (! peekTokenClass(EHTokIntConstant)) {
913 expected("multisample count");
914 return false;
915 }
916
917 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
918 return false;
919 }
920
921 if (! acceptTokenClass(EHTokRightAngle)) {
922 expected("right angle bracket");
923 return false;
924 }
925 } else if (ms) {
926 expected("texture type for multisample");
927 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600928 } else if (image) {
929 expected("type for RWTexture/RWBuffer");
930 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600931 }
932
933 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -0600934 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -0600935
936 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -0600937 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -0600938
steve-lunarg4f2da272016-10-10 15:24:57 -0600939 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
940 if (image || dim == EsdBuffer)
941 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -0600942
943 // Non-image Buffers are combined
944 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -0600945 sampler.set(txType.getBasicType(), dim, array);
946 } else {
947 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -0600948 if (image) {
949 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
950 } else {
951 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
952 }
steve-lunargd53f7172016-07-27 15:46:48 -0600953 }
steve-lunarg8b0227c2016-10-14 16:40:32 -0600954
955 // Remember the declared vector size.
956 sampler.vectorSize = txType.getVectorSize();
LoopDawg4886f692016-06-29 10:58:58 -0600957
958 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -0600959 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -0600960
961 return true;
962}
963
964
John Kessenich87142c72016-03-12 20:24:24 -0700965// If token is for a type, update 'type' with the type information,
966// and return true and advance.
967// Otherwise, return false, and don't advance
968bool HlslGrammar::acceptType(TType& type)
969{
steve-lunarg3226b082016-10-26 19:18:55 -0600970 // Basic types for min* types, broken out here in case of future
971 // changes, e.g, to use native halfs.
972 static const TBasicType min16float_bt = EbtFloat;
973 static const TBasicType min10float_bt = EbtFloat;
974 static const TBasicType min16int_bt = EbtInt;
975 static const TBasicType min12int_bt = EbtInt;
976 static const TBasicType min16uint_bt = EbtUint;
977
John Kessenich9c86c6a2016-05-03 22:49:24 -0600978 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600979 case EHTokVector:
980 return acceptVectorTemplateType(type);
981 break;
982
983 case EHTokMatrix:
984 return acceptMatrixTemplateType(type);
985 break;
986
LoopDawg4886f692016-06-29 10:58:58 -0600987 case EHTokSampler: // fall through
988 case EHTokSampler1d: // ...
989 case EHTokSampler2d: // ...
990 case EHTokSampler3d: // ...
991 case EHTokSamplerCube: // ...
992 case EHTokSamplerState: // ...
993 case EHTokSamplerComparisonState: // ...
994 return acceptSamplerType(type);
995 break;
996
997 case EHTokBuffer: // fall through
998 case EHTokTexture1d: // ...
999 case EHTokTexture1darray: // ...
1000 case EHTokTexture2d: // ...
1001 case EHTokTexture2darray: // ...
1002 case EHTokTexture3d: // ...
1003 case EHTokTextureCube: // ...
1004 case EHTokTextureCubearray: // ...
1005 case EHTokTexture2DMS: // ...
1006 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001007 case EHTokRWTexture1d: // ...
1008 case EHTokRWTexture1darray: // ...
1009 case EHTokRWTexture2d: // ...
1010 case EHTokRWTexture2darray: // ...
1011 case EHTokRWTexture3d: // ...
1012 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001013 return acceptTextureType(type);
1014 break;
1015
John Kesseniche6e74942016-06-11 16:43:14 -06001016 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001017 case EHTokCBuffer:
1018 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001019 return acceptStruct(type);
1020 break;
1021
1022 case EHTokIdentifier:
1023 // An identifier could be for a user-defined type.
1024 // Note we cache the symbol table lookup, to save for a later rule
1025 // when this is not a type.
1026 token.symbol = parseContext.symbolTable.find(*token.string);
1027 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1028 type.shallowCopy(token.symbol->getType());
1029 advanceToken();
1030 return true;
1031 } else
1032 return false;
1033
John Kessenich71351de2016-06-08 12:50:56 -06001034 case EHTokVoid:
1035 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001036 break;
John Kessenich71351de2016-06-08 12:50:56 -06001037
John Kessenicha1e2d492016-09-20 13:22:58 -06001038 case EHTokString:
1039 new(&type) TType(EbtString);
1040 break;
1041
John Kessenich87142c72016-03-12 20:24:24 -07001042 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001043 new(&type) TType(EbtFloat);
1044 break;
John Kessenich87142c72016-03-12 20:24:24 -07001045 case EHTokFloat1:
1046 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001047 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001048 break;
John Kessenich87142c72016-03-12 20:24:24 -07001049 case EHTokFloat2:
1050 new(&type) TType(EbtFloat, EvqTemporary, 2);
1051 break;
1052 case EHTokFloat3:
1053 new(&type) TType(EbtFloat, EvqTemporary, 3);
1054 break;
1055 case EHTokFloat4:
1056 new(&type) TType(EbtFloat, EvqTemporary, 4);
1057 break;
1058
John Kessenich71351de2016-06-08 12:50:56 -06001059 case EHTokDouble:
1060 new(&type) TType(EbtDouble);
1061 break;
1062 case EHTokDouble1:
1063 new(&type) TType(EbtDouble);
1064 type.makeVector();
1065 break;
1066 case EHTokDouble2:
1067 new(&type) TType(EbtDouble, EvqTemporary, 2);
1068 break;
1069 case EHTokDouble3:
1070 new(&type) TType(EbtDouble, EvqTemporary, 3);
1071 break;
1072 case EHTokDouble4:
1073 new(&type) TType(EbtDouble, EvqTemporary, 4);
1074 break;
1075
1076 case EHTokInt:
1077 case EHTokDword:
1078 new(&type) TType(EbtInt);
1079 break;
1080 case EHTokInt1:
1081 new(&type) TType(EbtInt);
1082 type.makeVector();
1083 break;
John Kessenich87142c72016-03-12 20:24:24 -07001084 case EHTokInt2:
1085 new(&type) TType(EbtInt, EvqTemporary, 2);
1086 break;
1087 case EHTokInt3:
1088 new(&type) TType(EbtInt, EvqTemporary, 3);
1089 break;
1090 case EHTokInt4:
1091 new(&type) TType(EbtInt, EvqTemporary, 4);
1092 break;
1093
John Kessenich71351de2016-06-08 12:50:56 -06001094 case EHTokUint:
1095 new(&type) TType(EbtUint);
1096 break;
1097 case EHTokUint1:
1098 new(&type) TType(EbtUint);
1099 type.makeVector();
1100 break;
1101 case EHTokUint2:
1102 new(&type) TType(EbtUint, EvqTemporary, 2);
1103 break;
1104 case EHTokUint3:
1105 new(&type) TType(EbtUint, EvqTemporary, 3);
1106 break;
1107 case EHTokUint4:
1108 new(&type) TType(EbtUint, EvqTemporary, 4);
1109 break;
1110
LoopDawg6daaa4f2016-06-23 19:13:48 -06001111
John Kessenich71351de2016-06-08 12:50:56 -06001112 case EHTokBool:
1113 new(&type) TType(EbtBool);
1114 break;
1115 case EHTokBool1:
1116 new(&type) TType(EbtBool);
1117 type.makeVector();
1118 break;
John Kessenich87142c72016-03-12 20:24:24 -07001119 case EHTokBool2:
1120 new(&type) TType(EbtBool, EvqTemporary, 2);
1121 break;
1122 case EHTokBool3:
1123 new(&type) TType(EbtBool, EvqTemporary, 3);
1124 break;
1125 case EHTokBool4:
1126 new(&type) TType(EbtBool, EvqTemporary, 4);
1127 break;
1128
steve-lunarg3226b082016-10-26 19:18:55 -06001129 case EHTokMin16float:
1130 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1131 break;
1132 case EHTokMin16float1:
1133 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1134 type.makeVector();
1135 break;
1136 case EHTokMin16float2:
1137 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1138 break;
1139 case EHTokMin16float3:
1140 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1141 break;
1142 case EHTokMin16float4:
1143 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1144 break;
1145
1146 case EHTokMin10float:
1147 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1148 break;
1149 case EHTokMin10float1:
1150 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1151 type.makeVector();
1152 break;
1153 case EHTokMin10float2:
1154 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1155 break;
1156 case EHTokMin10float3:
1157 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1158 break;
1159 case EHTokMin10float4:
1160 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1161 break;
1162
1163 case EHTokMin16int:
1164 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1165 break;
1166 case EHTokMin16int1:
1167 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1168 type.makeVector();
1169 break;
1170 case EHTokMin16int2:
1171 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1172 break;
1173 case EHTokMin16int3:
1174 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1175 break;
1176 case EHTokMin16int4:
1177 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1178 break;
1179
1180 case EHTokMin12int:
1181 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1182 break;
1183 case EHTokMin12int1:
1184 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1185 type.makeVector();
1186 break;
1187 case EHTokMin12int2:
1188 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1189 break;
1190 case EHTokMin12int3:
1191 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1192 break;
1193 case EHTokMin12int4:
1194 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1195 break;
1196
1197 case EHTokMin16uint:
1198 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1199 break;
1200 case EHTokMin16uint1:
1201 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1202 type.makeVector();
1203 break;
1204 case EHTokMin16uint2:
1205 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1206 break;
1207 case EHTokMin16uint3:
1208 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1209 break;
1210 case EHTokMin16uint4:
1211 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1212 break;
1213
John Kessenich0133c122016-05-20 12:17:26 -06001214 case EHTokInt1x1:
1215 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1216 break;
1217 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001218 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001219 break;
1220 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001221 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001222 break;
1223 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001224 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001225 break;
1226 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001227 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001228 break;
1229 case EHTokInt2x2:
1230 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1231 break;
1232 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001233 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001234 break;
1235 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001236 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001237 break;
1238 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001239 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001240 break;
1241 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001242 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001243 break;
1244 case EHTokInt3x3:
1245 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1246 break;
1247 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001248 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001249 break;
1250 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001251 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001252 break;
1253 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001254 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001255 break;
1256 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001257 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001258 break;
1259 case EHTokInt4x4:
1260 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1261 break;
1262
John Kessenich71351de2016-06-08 12:50:56 -06001263 case EHTokUint1x1:
1264 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1265 break;
1266 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001267 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001268 break;
1269 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001270 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001271 break;
1272 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001273 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001274 break;
1275 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001276 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001277 break;
1278 case EHTokUint2x2:
1279 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1280 break;
1281 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001282 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001283 break;
1284 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001285 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001286 break;
1287 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001288 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001289 break;
1290 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001291 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001292 break;
1293 case EHTokUint3x3:
1294 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1295 break;
1296 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001297 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001298 break;
1299 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001300 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001301 break;
1302 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001303 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001304 break;
1305 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001306 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001307 break;
1308 case EHTokUint4x4:
1309 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1310 break;
1311
1312 case EHTokBool1x1:
1313 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1314 break;
1315 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001316 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001317 break;
1318 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001319 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001320 break;
1321 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001322 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001323 break;
1324 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001325 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001326 break;
1327 case EHTokBool2x2:
1328 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1329 break;
1330 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001331 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001332 break;
1333 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001334 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001335 break;
1336 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001337 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001338 break;
1339 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001340 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001341 break;
1342 case EHTokBool3x3:
1343 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1344 break;
1345 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001346 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001347 break;
1348 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001349 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001350 break;
1351 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001352 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001353 break;
1354 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001355 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001356 break;
1357 case EHTokBool4x4:
1358 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1359 break;
1360
John Kessenich0133c122016-05-20 12:17:26 -06001361 case EHTokFloat1x1:
1362 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1363 break;
1364 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001365 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001366 break;
1367 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001368 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001369 break;
1370 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001371 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001372 break;
1373 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001374 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001375 break;
John Kessenich87142c72016-03-12 20:24:24 -07001376 case EHTokFloat2x2:
1377 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1378 break;
1379 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001380 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001381 break;
1382 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001383 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001384 break;
John Kessenich0133c122016-05-20 12:17:26 -06001385 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001386 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001387 break;
John Kessenich87142c72016-03-12 20:24:24 -07001388 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001389 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001390 break;
1391 case EHTokFloat3x3:
1392 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1393 break;
1394 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001395 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001396 break;
John Kessenich0133c122016-05-20 12:17:26 -06001397 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001398 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001399 break;
John Kessenich87142c72016-03-12 20:24:24 -07001400 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001401 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001402 break;
1403 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001404 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001405 break;
1406 case EHTokFloat4x4:
1407 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1408 break;
1409
John Kessenich0133c122016-05-20 12:17:26 -06001410 case EHTokDouble1x1:
1411 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1412 break;
1413 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001414 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001415 break;
1416 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001417 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001418 break;
1419 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001420 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001421 break;
1422 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001423 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001424 break;
1425 case EHTokDouble2x2:
1426 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1427 break;
1428 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001429 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001430 break;
1431 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001432 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001433 break;
1434 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001435 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001436 break;
1437 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001438 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001439 break;
1440 case EHTokDouble3x3:
1441 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1442 break;
1443 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001444 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001445 break;
1446 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001447 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001448 break;
1449 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001450 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001451 break;
1452 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001453 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001454 break;
1455 case EHTokDouble4x4:
1456 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1457 break;
1458
John Kessenich87142c72016-03-12 20:24:24 -07001459 default:
1460 return false;
1461 }
1462
1463 advanceToken();
1464
1465 return true;
1466}
1467
John Kesseniche6e74942016-06-11 16:43:14 -06001468// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001469// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1470// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1471//
1472// struct_type
1473// : STRUCT
1474// | CBUFFER
1475// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001476//
1477bool HlslGrammar::acceptStruct(TType& type)
1478{
John Kessenichb804de62016-09-05 12:19:18 -06001479 // This storage qualifier will tell us whether it's an AST
1480 // block type or just a generic structure type.
1481 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001482
1483 // CBUFFER
1484 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001485 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001486 // TBUFFER
1487 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001488 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001489 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001490 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001491 return false;
1492
1493 // IDENTIFIER
1494 TString structName = "";
1495 if (peekTokenClass(EHTokIdentifier)) {
1496 structName = *token.string;
1497 advanceToken();
1498 }
1499
John Kessenich3d157c52016-07-25 16:05:33 -06001500 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001501 TQualifier postDeclQualifier;
1502 postDeclQualifier.clear();
1503 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001504
John Kesseniche6e74942016-06-11 16:43:14 -06001505 // LEFT_BRACE
1506 if (! acceptTokenClass(EHTokLeftBrace)) {
1507 expected("{");
1508 return false;
1509 }
1510
1511 // struct_declaration_list
1512 TTypeList* typeList;
1513 if (! acceptStructDeclarationList(typeList)) {
1514 expected("struct member declarations");
1515 return false;
1516 }
1517
1518 // RIGHT_BRACE
1519 if (! acceptTokenClass(EHTokRightBrace)) {
1520 expected("}");
1521 return false;
1522 }
1523
1524 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001525 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001526 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001527 else {
John Kessenich7735b942016-09-05 12:40:06 -06001528 postDeclQualifier.storage = storageQualifier;
1529 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001530 }
John Kesseniche6e74942016-06-11 16:43:14 -06001531
John Kessenich3d157c52016-07-25 16:05:33 -06001532 // If it was named, which means the type can be reused later, add
1533 // it to the symbol table. (Unless it's a block, in which
1534 // case the name is not a type.)
1535 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001536 TVariable* userTypeDef = new TVariable(&structName, type, true);
1537 if (! parseContext.symbolTable.insert(*userTypeDef))
1538 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1539 }
1540
1541 return true;
1542}
1543
1544// struct_declaration_list
1545// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1546//
1547// struct_declaration
1548// : fully_specified_type struct_declarator COMMA struct_declarator ...
1549//
1550// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001551// : IDENTIFIER post_decls
1552// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001553//
1554bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1555{
1556 typeList = new TTypeList();
1557
1558 do {
1559 // success on seeing the RIGHT_BRACE coming up
1560 if (peekTokenClass(EHTokRightBrace))
1561 return true;
1562
1563 // struct_declaration
1564
1565 // fully_specified_type
1566 TType memberType;
1567 if (! acceptFullySpecifiedType(memberType)) {
1568 expected("member type");
1569 return false;
1570 }
1571
1572 // struct_declarator COMMA struct_declarator ...
1573 do {
1574 // peek IDENTIFIER
1575 if (! peekTokenClass(EHTokIdentifier)) {
1576 expected("member name");
1577 return false;
1578 }
1579
1580 // add it to the list of members
1581 TTypeLoc member = { new TType(EbtVoid), token.loc };
1582 member.type->shallowCopy(memberType);
1583 member.type->setFieldName(*token.string);
1584 typeList->push_back(member);
1585
1586 // accept IDENTIFIER
1587 advanceToken();
1588
1589 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001590 TArraySizes* arraySizes = nullptr;
1591 acceptArraySpecifier(arraySizes);
1592 if (arraySizes)
1593 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001594
John Kessenich7735b942016-09-05 12:40:06 -06001595 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001596
John Kesseniche6e74942016-06-11 16:43:14 -06001597 // success on seeing the SEMICOLON coming up
1598 if (peekTokenClass(EHTokSemicolon))
1599 break;
1600
1601 // COMMA
1602 if (! acceptTokenClass(EHTokComma)) {
1603 expected(",");
1604 return false;
1605 }
1606
1607 } while (true);
1608
1609 // SEMI_COLON
1610 if (! acceptTokenClass(EHTokSemicolon)) {
1611 expected(";");
1612 return false;
1613 }
1614
1615 } while (true);
1616}
1617
John Kessenich5f934b02016-03-13 17:58:25 -06001618// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001619// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001620// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001621//
1622bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1623{
John Kessenich078d7f22016-03-14 10:02:11 -06001624 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001625 if (! acceptTokenClass(EHTokLeftParen))
1626 return false;
1627
John Kessenich71351de2016-06-08 12:50:56 -06001628 // VOID RIGHT_PAREN
1629 if (! acceptTokenClass(EHTokVoid)) {
1630 do {
1631 // parameter_declaration
1632 if (! acceptParameterDeclaration(function))
1633 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001634
John Kessenich71351de2016-06-08 12:50:56 -06001635 // COMMA
1636 if (! acceptTokenClass(EHTokComma))
1637 break;
1638 } while (true);
1639 }
John Kessenich5f934b02016-03-13 17:58:25 -06001640
John Kessenich078d7f22016-03-14 10:02:11 -06001641 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001642 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001643 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001644 return false;
1645 }
1646
1647 return true;
1648}
1649
1650// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001651// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001652// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001653//
1654bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1655{
1656 // fully_specified_type
1657 TType* type = new TType;
1658 if (! acceptFullySpecifiedType(*type))
1659 return false;
1660
1661 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001662 HlslToken idToken;
1663 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001664
John Kessenich19b92ff2016-06-19 11:50:34 -06001665 // array_specifier
1666 TArraySizes* arraySizes = nullptr;
1667 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001668 if (arraySizes) {
1669 if (arraySizes->isImplicit()) {
1670 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1671 return false;
1672 }
1673
John Kessenich19b92ff2016-06-19 11:50:34 -06001674 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001675 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001676
1677 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001678 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001679
John Kessenich5aa59e22016-06-17 15:50:47 -06001680 parseContext.paramFix(*type);
1681
John Kessenichaecd4972016-03-14 10:46:34 -06001682 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001683 function.addParameter(param);
1684
1685 return true;
1686}
1687
1688// Do the work to create the function definition in addition to
1689// parsing the body (compound_statement).
1690bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1691{
John Kessenicha3051662016-09-02 19:13:36 -06001692 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001693 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001694
John Kessenich077e0522016-06-09 02:02:17 -06001695 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001696 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001697
1698 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001699 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001700 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001701 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001702 return true;
1703 }
1704
1705 return false;
1706}
1707
John Kessenich0d2b6de2016-06-05 11:23:11 -06001708// Accept an expression with parenthesis around it, where
1709// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001710// syntactically required ones like in "if ( expression )".
1711//
1712// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001713//
1714// Note this one is not set up to be speculative; as it gives
1715// errors if not found.
1716//
1717bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1718{
1719 // LEFT_PAREN
1720 if (! acceptTokenClass(EHTokLeftParen))
1721 expected("(");
1722
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001723 bool decl = false;
1724 TIntermNode* declNode = nullptr;
1725 decl = acceptControlDeclaration(declNode);
1726 if (decl) {
1727 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1728 expected("initialized declaration");
1729 return false;
1730 } else
1731 expression = declNode->getAsTyped();
1732 } else {
1733 // no declaration
1734 if (! acceptExpression(expression)) {
1735 expected("expression");
1736 return false;
1737 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001738 }
1739
1740 // RIGHT_PAREN
1741 if (! acceptTokenClass(EHTokRightParen))
1742 expected(")");
1743
1744 return true;
1745}
1746
John Kessenich34fb0362016-05-03 23:17:20 -06001747// The top-level full expression recognizer.
1748//
John Kessenich87142c72016-03-12 20:24:24 -07001749// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001750// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001751//
1752bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1753{
LoopDawgef764a22016-06-03 09:17:51 -06001754 node = nullptr;
1755
John Kessenich34fb0362016-05-03 23:17:20 -06001756 // assignment_expression
1757 if (! acceptAssignmentExpression(node))
1758 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001759
John Kessenich34fb0362016-05-03 23:17:20 -06001760 if (! peekTokenClass(EHTokComma))
1761 return true;
1762
1763 do {
1764 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001765 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001766 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001767
John Kessenich34fb0362016-05-03 23:17:20 -06001768 // ... assignment_expression
1769 TIntermTyped* rightNode = nullptr;
1770 if (! acceptAssignmentExpression(rightNode)) {
1771 expected("assignment expression");
1772 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001773 }
1774
John Kessenich34fb0362016-05-03 23:17:20 -06001775 node = intermediate.addComma(node, rightNode, loc);
1776
1777 if (! peekTokenClass(EHTokComma))
1778 return true;
1779 } while (true);
1780}
1781
John Kessenich07354242016-07-01 19:58:06 -06001782// initializer
1783// : LEFT_BRACE initializer_list RIGHT_BRACE
1784//
1785// initializer_list
1786// : assignment_expression COMMA assignment_expression COMMA ...
1787//
1788bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1789{
1790 // LEFT_BRACE
1791 if (! acceptTokenClass(EHTokLeftBrace))
1792 return false;
1793
1794 // initializer_list
1795 TSourceLoc loc = token.loc;
1796 node = nullptr;
1797 do {
1798 // assignment_expression
1799 TIntermTyped* expr;
1800 if (! acceptAssignmentExpression(expr)) {
1801 expected("assignment expression in initializer list");
1802 return false;
1803 }
1804 node = intermediate.growAggregate(node, expr, loc);
1805
1806 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001807 if (acceptTokenClass(EHTokComma)) {
1808 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1809 return true;
John Kessenich07354242016-07-01 19:58:06 -06001810 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001811 }
John Kessenich07354242016-07-01 19:58:06 -06001812
1813 // RIGHT_BRACE
1814 if (acceptTokenClass(EHTokRightBrace))
1815 return true;
1816
1817 expected(", or }");
1818 return false;
1819 } while (true);
1820}
1821
John Kessenich34fb0362016-05-03 23:17:20 -06001822// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001823// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001824//
1825// a op (b op (c op d))
1826//
1827// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001828// : initializer
1829// | conditional_expression
1830// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001831//
1832bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1833{
John Kessenich07354242016-07-01 19:58:06 -06001834 // initializer
1835 if (peekTokenClass(EHTokLeftBrace)) {
1836 if (acceptInitializer(node))
1837 return true;
1838
1839 expected("initializer");
1840 return false;
1841 }
1842
John Kessenich00957f82016-07-27 10:39:57 -06001843 // conditional_expression
1844 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001845 return false;
1846
John Kessenich07354242016-07-01 19:58:06 -06001847 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001848 TOperator assignOp = HlslOpMap::assignment(peek());
1849 if (assignOp == EOpNull)
1850 return true;
1851
John Kessenich00957f82016-07-27 10:39:57 -06001852 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001853 TSourceLoc loc = token.loc;
1854 advanceToken();
1855
John Kessenich00957f82016-07-27 10:39:57 -06001856 // conditional_expression assign_op conditional_expression ...
1857 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001858 // gets the right-to-left associativity.
1859 TIntermTyped* rightNode = nullptr;
1860 if (! acceptAssignmentExpression(rightNode)) {
1861 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001862 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001863 }
1864
John Kessenichd21baed2016-09-16 03:05:12 -06001865 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06001866 node = parseContext.handleLvalue(loc, "assign", node);
1867
John Kessenichfea226b2016-07-28 17:53:56 -06001868 if (node == nullptr) {
1869 parseContext.error(loc, "could not create assignment", "", "");
1870 return false;
1871 }
John Kessenich34fb0362016-05-03 23:17:20 -06001872
1873 if (! peekTokenClass(EHTokComma))
1874 return true;
1875
1876 return true;
1877}
1878
John Kessenich00957f82016-07-27 10:39:57 -06001879// Accept a conditional expression, which associates right-to-left,
1880// accomplished by the "true" expression calling down to lower
1881// precedence levels than this level.
1882//
1883// conditional_expression
1884// : binary_expression
1885// | binary_expression QUESTION expression COLON assignment_expression
1886//
1887bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1888{
1889 // binary_expression
1890 if (! acceptBinaryExpression(node, PlLogicalOr))
1891 return false;
1892
1893 if (! acceptTokenClass(EHTokQuestion))
1894 return true;
1895
1896 TIntermTyped* trueNode = nullptr;
1897 if (! acceptExpression(trueNode)) {
1898 expected("expression after ?");
1899 return false;
1900 }
1901 TSourceLoc loc = token.loc;
1902
1903 if (! acceptTokenClass(EHTokColon)) {
1904 expected(":");
1905 return false;
1906 }
1907
1908 TIntermTyped* falseNode = nullptr;
1909 if (! acceptAssignmentExpression(falseNode)) {
1910 expected("expression after :");
1911 return false;
1912 }
1913
1914 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1915
1916 return true;
1917}
1918
John Kessenich34fb0362016-05-03 23:17:20 -06001919// Accept a binary expression, for binary operations that
1920// associate left-to-right. This is, it is implicit, for example
1921//
1922// ((a op b) op c) op d
1923//
1924// binary_expression
1925// : expression op expression op expression ...
1926//
1927// where 'expression' is the next higher level in precedence.
1928//
1929bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1930{
1931 if (precedenceLevel > PlMul)
1932 return acceptUnaryExpression(node);
1933
1934 // assignment_expression
1935 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1936 return false;
1937
John Kessenich34fb0362016-05-03 23:17:20 -06001938 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001939 TOperator op = HlslOpMap::binary(peek());
1940 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1941 if (tokenLevel < precedenceLevel)
1942 return true;
1943
John Kessenich34fb0362016-05-03 23:17:20 -06001944 // ... op
1945 TSourceLoc loc = token.loc;
1946 advanceToken();
1947
1948 // ... expression
1949 TIntermTyped* rightNode = nullptr;
1950 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1951 expected("expression");
1952 return false;
1953 }
1954
1955 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001956 if (node == nullptr) {
1957 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1958 return false;
1959 }
John Kessenich34fb0362016-05-03 23:17:20 -06001960 } while (true);
1961}
1962
1963// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001964// : (type) unary_expression
1965// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001966// | - unary_expression
1967// | ! unary_expression
1968// | ~ unary_expression
1969// | ++ unary_expression
1970// | -- unary_expression
1971// | postfix_expression
1972//
1973bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1974{
John Kessenich1cc1a282016-06-03 16:55:49 -06001975 // (type) unary_expression
1976 // Have to look two steps ahead, because this could be, e.g., a
1977 // postfix_expression instead, since that also starts with at "(".
1978 if (acceptTokenClass(EHTokLeftParen)) {
1979 TType castType;
1980 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001981 if (acceptTokenClass(EHTokRightParen)) {
1982 // We've matched "(type)" now, get the expression to cast
1983 TSourceLoc loc = token.loc;
1984 if (! acceptUnaryExpression(node))
1985 return false;
1986
1987 // Hook it up like a constructor
1988 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1989 if (constructorFunction == nullptr) {
1990 expected("type that can be constructed");
1991 return false;
1992 }
1993 TIntermTyped* arguments = nullptr;
1994 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1995 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1996
1997 return true;
1998 } else {
1999 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2000 // the '(int' part. We must back up twice.
2001 recedeToken();
2002 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002003 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002004 } else {
2005 // This isn't a type cast, but it still started "(", so if it is a
2006 // unary expression, it can only be a postfix_expression, so try that.
2007 // Back it up first.
2008 recedeToken();
2009 return acceptPostfixExpression(node);
2010 }
2011 }
2012
2013 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002014 TOperator unaryOp = HlslOpMap::preUnary(peek());
2015
John Kessenich1cc1a282016-06-03 16:55:49 -06002016 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002017 if (unaryOp == EOpNull)
2018 return acceptPostfixExpression(node);
2019
2020 // op unary_expression
2021 TSourceLoc loc = token.loc;
2022 advanceToken();
2023 if (! acceptUnaryExpression(node))
2024 return false;
2025
2026 // + is a no-op
2027 if (unaryOp == EOpAdd)
2028 return true;
2029
2030 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002031
2032 // These unary ops require lvalues
2033 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2034 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002035
2036 return node != nullptr;
2037}
2038
2039// postfix_expression
2040// : LEFT_PAREN expression RIGHT_PAREN
2041// | literal
2042// | constructor
2043// | identifier
2044// | function_call
2045// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2046// | postfix_expression DOT IDENTIFIER
2047// | postfix_expression INC_OP
2048// | postfix_expression DEC_OP
2049//
2050bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2051{
2052 // Not implemented as self-recursive:
2053 // The logical "right recursion" is done with an loop at the end
2054
2055 // idToken will pick up either a variable or a function name in a function call
2056 HlslToken idToken;
2057
John Kessenich21472ae2016-06-04 11:46:33 -06002058 // Find something before the postfix operations, as they can't operate
2059 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002060 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002061 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002062 if (! acceptExpression(node)) {
2063 expected("expression");
2064 return false;
2065 }
2066 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002067 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002068 return false;
2069 }
John Kessenich34fb0362016-05-03 23:17:20 -06002070 } else if (acceptLiteral(node)) {
2071 // literal (nothing else to do yet), go on to the
2072 } else if (acceptConstructor(node)) {
2073 // constructor (nothing else to do yet)
2074 } else if (acceptIdentifier(idToken)) {
2075 // identifier or function_call name
2076 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002077 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002078 } else if (acceptFunctionCall(idToken, node)) {
2079 // function_call (nothing else to do yet)
2080 } else {
2081 expected("function call arguments");
2082 return false;
2083 }
John Kessenich21472ae2016-06-04 11:46:33 -06002084 } else {
2085 // nothing found, can't post operate
2086 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002087 }
2088
John Kessenich21472ae2016-06-04 11:46:33 -06002089 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002090 do {
2091 TSourceLoc loc = token.loc;
2092 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002093
John Kessenich34fb0362016-05-03 23:17:20 -06002094 // Consume only a valid post-unary operator, otherwise we are done.
2095 switch (postOp) {
2096 case EOpIndexDirectStruct:
2097 case EOpIndexIndirect:
2098 case EOpPostIncrement:
2099 case EOpPostDecrement:
2100 advanceToken();
2101 break;
2102 default:
2103 return true;
2104 }
John Kessenich87142c72016-03-12 20:24:24 -07002105
John Kessenich34fb0362016-05-03 23:17:20 -06002106 // We have a valid post-unary operator, process it.
2107 switch (postOp) {
2108 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002109 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002110 // DOT IDENTIFIER
2111 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002112 HlslToken field;
2113 if (! acceptIdentifier(field)) {
2114 expected("swizzle or member");
2115 return false;
2116 }
LoopDawg4886f692016-06-29 10:58:58 -06002117
2118 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002119 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002120
2121 // In the event of a method node, we look for an open paren and accept the function call.
2122 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
2123 if (! acceptFunctionCall(field, node, base)) {
2124 expected("function parameters");
2125 return false;
2126 }
2127 }
2128
John Kessenich34fb0362016-05-03 23:17:20 -06002129 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002130 }
John Kessenich34fb0362016-05-03 23:17:20 -06002131 case EOpIndexIndirect:
2132 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002133 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002134 TIntermTyped* indexNode = nullptr;
2135 if (! acceptExpression(indexNode) ||
2136 ! peekTokenClass(EHTokRightBracket)) {
2137 expected("expression followed by ']'");
2138 return false;
2139 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002140 advanceToken();
2141 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2142 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002143 }
2144 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002145 // INC_OP
2146 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002147 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002148 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002149 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002150 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002151 break;
2152 default:
2153 assert(0);
2154 break;
2155 }
2156 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002157}
2158
John Kessenichd016be12016-03-13 11:24:20 -06002159// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002160// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002161//
2162bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2163{
2164 // type
2165 TType type;
2166 if (acceptType(type)) {
2167 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2168 if (constructorFunction == nullptr)
2169 return false;
2170
2171 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002172 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002173 if (! acceptArguments(constructorFunction, arguments)) {
2174 expected("constructor arguments");
2175 return false;
2176 }
2177
2178 // hook it up
2179 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2180
2181 return true;
2182 }
2183
2184 return false;
2185}
2186
John Kessenich34fb0362016-05-03 23:17:20 -06002187// The function_call identifier was already recognized, and passed in as idToken.
2188//
2189// function_call
2190// : [idToken] arguments
2191//
LoopDawg4886f692016-06-29 10:58:58 -06002192bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002193{
John Kessenich4678ca92016-05-13 09:33:42 -06002194 // arguments
2195 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2196 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002197
2198 // methods have an implicit first argument of the calling object.
2199 if (base != nullptr)
2200 parseContext.handleFunctionArgument(function, arguments, base);
2201
John Kessenich4678ca92016-05-13 09:33:42 -06002202 if (! acceptArguments(function, arguments))
2203 return false;
2204
2205 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2206
2207 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002208}
2209
John Kessenich87142c72016-03-12 20:24:24 -07002210// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002211// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002212//
John Kessenichd016be12016-03-13 11:24:20 -06002213// The arguments are pushed onto the 'function' argument list and
2214// onto the 'arguments' aggregate.
2215//
John Kessenich4678ca92016-05-13 09:33:42 -06002216bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002217{
John Kessenich078d7f22016-03-14 10:02:11 -06002218 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002219 if (! acceptTokenClass(EHTokLeftParen))
2220 return false;
2221
2222 do {
John Kessenichd016be12016-03-13 11:24:20 -06002223 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002224 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002225 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002226 break;
John Kessenichd016be12016-03-13 11:24:20 -06002227
2228 // hook it up
2229 parseContext.handleFunctionArgument(function, arguments, arg);
2230
John Kessenich078d7f22016-03-14 10:02:11 -06002231 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002232 if (! acceptTokenClass(EHTokComma))
2233 break;
2234 } while (true);
2235
John Kessenich078d7f22016-03-14 10:02:11 -06002236 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002237 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002238 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002239 return false;
2240 }
2241
2242 return true;
2243}
2244
2245bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2246{
2247 switch (token.tokenClass) {
2248 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002249 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002250 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002251 case EHTokUintConstant:
2252 node = intermediate.addConstantUnion(token.u, token.loc, true);
2253 break;
John Kessenich87142c72016-03-12 20:24:24 -07002254 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002255 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002256 break;
2257 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002258 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002259 break;
2260 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002261 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002262 break;
John Kessenich86f71382016-09-19 20:23:18 -06002263 case EHTokStringConstant:
2264 node = nullptr;
2265 break;
John Kessenich87142c72016-03-12 20:24:24 -07002266
2267 default:
2268 return false;
2269 }
2270
2271 advanceToken();
2272
2273 return true;
2274}
2275
John Kessenich5f934b02016-03-13 17:58:25 -06002276// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002277// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002278//
John Kessenich21472ae2016-06-04 11:46:33 -06002279bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002280{
John Kessenich21472ae2016-06-04 11:46:33 -06002281 TIntermAggregate* compoundStatement = nullptr;
2282
John Kessenich34fb0362016-05-03 23:17:20 -06002283 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002284 if (! acceptTokenClass(EHTokLeftBrace))
2285 return false;
2286
2287 // statement statement ...
2288 TIntermNode* statement = nullptr;
2289 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002290 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2291 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2292 branch->getFlowOp() == EOpDefault)) {
2293 // hook up individual subsequences within a switch statement
2294 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2295 compoundStatement = nullptr;
2296 } else {
2297 // hook it up to the growing compound statement
2298 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2299 }
John Kessenich5f934b02016-03-13 17:58:25 -06002300 }
John Kessenich34fb0362016-05-03 23:17:20 -06002301 if (compoundStatement)
2302 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002303
John Kessenich21472ae2016-06-04 11:46:33 -06002304 retStatement = compoundStatement;
2305
John Kessenich34fb0362016-05-03 23:17:20 -06002306 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002307 return acceptTokenClass(EHTokRightBrace);
2308}
2309
John Kessenich0d2b6de2016-06-05 11:23:11 -06002310bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2311{
2312 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002313 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002314 parseContext.popScope();
2315
2316 return result;
2317}
2318
John Kessenich077e0522016-06-09 02:02:17 -06002319bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002320{
John Kessenich077e0522016-06-09 02:02:17 -06002321 parseContext.pushScope();
2322 bool result = acceptCompoundStatement(statement);
2323 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002324
2325 return result;
2326}
2327
John Kessenich5f934b02016-03-13 17:58:25 -06002328// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002329// : attributes attributed_statement
2330//
2331// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002332// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002333// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002334// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002335// | declaration_statement
2336// | selection_statement
2337// | switch_statement
2338// | case_label
2339// | iteration_statement
2340// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002341//
2342bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2343{
John Kessenich21472ae2016-06-04 11:46:33 -06002344 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002345
John Kessenich21472ae2016-06-04 11:46:33 -06002346 // attributes
2347 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002348
John Kessenich21472ae2016-06-04 11:46:33 -06002349 // attributed_statement
2350 switch (peek()) {
2351 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002352 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002353
John Kessenich21472ae2016-06-04 11:46:33 -06002354 case EHTokIf:
2355 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002356
John Kessenich21472ae2016-06-04 11:46:33 -06002357 case EHTokSwitch:
2358 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002359
John Kessenich21472ae2016-06-04 11:46:33 -06002360 case EHTokFor:
2361 case EHTokDo:
2362 case EHTokWhile:
2363 return acceptIterationStatement(statement);
2364
2365 case EHTokContinue:
2366 case EHTokBreak:
2367 case EHTokDiscard:
2368 case EHTokReturn:
2369 return acceptJumpStatement(statement);
2370
2371 case EHTokCase:
2372 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002373 case EHTokDefault:
2374 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002375
2376 case EHTokSemicolon:
2377 return acceptTokenClass(EHTokSemicolon);
2378
2379 case EHTokRightBrace:
2380 // Performance: not strictly necessary, but stops a bunch of hunting early,
2381 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002382 return false;
2383
John Kessenich21472ae2016-06-04 11:46:33 -06002384 default:
2385 {
2386 // declaration
2387 if (acceptDeclaration(statement))
2388 return true;
2389
2390 // expression
2391 TIntermTyped* node;
2392 if (acceptExpression(node))
2393 statement = node;
2394 else
2395 return false;
2396
2397 // SEMICOLON (following an expression)
2398 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002399 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002400 return false;
2401 }
2402 }
2403 }
2404
John Kessenich5f934b02016-03-13 17:58:25 -06002405 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002406}
2407
John Kessenich21472ae2016-06-04 11:46:33 -06002408// attributes
2409// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2410//
2411// attribute:
2412// : UNROLL
2413// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2414// | FASTOPT
2415// | ALLOW_UAV_CONDITION
2416// | BRANCH
2417// | FLATTEN
2418// | FORCECASE
2419// | CALL
2420//
2421void HlslGrammar::acceptAttributes()
2422{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002423 // For now, accept the [ XXX(X) ] syntax, but drop.
2424 // TODO: subset to correct set? Pass on?
2425 do {
2426 // LEFT_BRACKET?
2427 if (! acceptTokenClass(EHTokLeftBracket))
2428 return;
2429
2430 // attribute
2431 if (peekTokenClass(EHTokIdentifier)) {
2432 // 'token.string' is the attribute
2433 advanceToken();
2434 } else if (! peekTokenClass(EHTokRightBracket)) {
2435 expected("identifier");
2436 advanceToken();
2437 }
2438
2439 // (x)
2440 if (acceptTokenClass(EHTokLeftParen)) {
2441 TIntermTyped* node;
2442 if (! acceptLiteral(node))
2443 expected("literal");
2444 // 'node' has the literal in it
2445 if (! acceptTokenClass(EHTokRightParen))
2446 expected(")");
2447 }
2448
2449 // RIGHT_BRACKET
2450 if (acceptTokenClass(EHTokRightBracket))
2451 continue;
2452
2453 expected("]");
2454 return;
2455
2456 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002457}
2458
John Kessenich0d2b6de2016-06-05 11:23:11 -06002459// selection_statement
2460// : IF LEFT_PAREN expression RIGHT_PAREN statement
2461// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2462//
John Kessenich21472ae2016-06-04 11:46:33 -06002463bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2464{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002465 TSourceLoc loc = token.loc;
2466
2467 // IF
2468 if (! acceptTokenClass(EHTokIf))
2469 return false;
2470
2471 // so that something declared in the condition is scoped to the lifetimes
2472 // of the then-else statements
2473 parseContext.pushScope();
2474
2475 // LEFT_PAREN expression RIGHT_PAREN
2476 TIntermTyped* condition;
2477 if (! acceptParenExpression(condition))
2478 return false;
2479
2480 // create the child statements
2481 TIntermNodePair thenElse = { nullptr, nullptr };
2482
2483 // then statement
2484 if (! acceptScopedStatement(thenElse.node1)) {
2485 expected("then statement");
2486 return false;
2487 }
2488
2489 // ELSE
2490 if (acceptTokenClass(EHTokElse)) {
2491 // else statement
2492 if (! acceptScopedStatement(thenElse.node2)) {
2493 expected("else statement");
2494 return false;
2495 }
2496 }
2497
2498 // Put the pieces together
2499 statement = intermediate.addSelection(condition, thenElse, loc);
2500 parseContext.popScope();
2501
2502 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002503}
2504
John Kessenichd02dc5d2016-07-01 00:04:11 -06002505// switch_statement
2506// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2507//
John Kessenich21472ae2016-06-04 11:46:33 -06002508bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2509{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002510 // SWITCH
2511 TSourceLoc loc = token.loc;
2512 if (! acceptTokenClass(EHTokSwitch))
2513 return false;
2514
2515 // LEFT_PAREN expression RIGHT_PAREN
2516 parseContext.pushScope();
2517 TIntermTyped* switchExpression;
2518 if (! acceptParenExpression(switchExpression)) {
2519 parseContext.popScope();
2520 return false;
2521 }
2522
2523 // compound_statement
2524 parseContext.pushSwitchSequence(new TIntermSequence);
2525 bool statementOkay = acceptCompoundStatement(statement);
2526 if (statementOkay)
2527 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2528
2529 parseContext.popSwitchSequence();
2530 parseContext.popScope();
2531
2532 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002533}
2534
John Kessenich119f8f62016-06-05 15:44:07 -06002535// iteration_statement
2536// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2537// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2538// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2539//
2540// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002541bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2542{
John Kessenich119f8f62016-06-05 15:44:07 -06002543 TSourceLoc loc = token.loc;
2544 TIntermTyped* condition = nullptr;
2545
2546 EHlslTokenClass loop = peek();
2547 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2548
2549 // WHILE or DO or FOR
2550 advanceToken();
2551
2552 switch (loop) {
2553 case EHTokWhile:
2554 // so that something declared in the condition is scoped to the lifetime
2555 // of the while sub-statement
2556 parseContext.pushScope();
2557 parseContext.nestLooping();
2558
2559 // LEFT_PAREN condition RIGHT_PAREN
2560 if (! acceptParenExpression(condition))
2561 return false;
2562
2563 // statement
2564 if (! acceptScopedStatement(statement)) {
2565 expected("while sub-statement");
2566 return false;
2567 }
2568
2569 parseContext.unnestLooping();
2570 parseContext.popScope();
2571
2572 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2573
2574 return true;
2575
2576 case EHTokDo:
2577 parseContext.nestLooping();
2578
2579 if (! acceptTokenClass(EHTokLeftBrace))
2580 expected("{");
2581
2582 // statement
2583 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2584 expected("do sub-statement");
2585 return false;
2586 }
2587
2588 if (! acceptTokenClass(EHTokRightBrace))
2589 expected("}");
2590
2591 // WHILE
2592 if (! acceptTokenClass(EHTokWhile)) {
2593 expected("while");
2594 return false;
2595 }
2596
2597 // LEFT_PAREN condition RIGHT_PAREN
2598 TIntermTyped* condition;
2599 if (! acceptParenExpression(condition))
2600 return false;
2601
2602 if (! acceptTokenClass(EHTokSemicolon))
2603 expected(";");
2604
2605 parseContext.unnestLooping();
2606
2607 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2608
2609 return true;
2610
2611 case EHTokFor:
2612 {
2613 // LEFT_PAREN
2614 if (! acceptTokenClass(EHTokLeftParen))
2615 expected("(");
2616
2617 // so that something declared in the condition is scoped to the lifetime
2618 // of the for sub-statement
2619 parseContext.pushScope();
2620
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002621 // initializer
2622 TIntermNode* initNode = nullptr;
2623 if (! acceptControlDeclaration(initNode)) {
2624 TIntermTyped* initExpr = nullptr;
2625 acceptExpression(initExpr);
2626 initNode = initExpr;
2627 }
2628 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002629 if (! acceptTokenClass(EHTokSemicolon))
2630 expected(";");
2631
2632 parseContext.nestLooping();
2633
2634 // condition SEMI_COLON
2635 acceptExpression(condition);
2636 if (! acceptTokenClass(EHTokSemicolon))
2637 expected(";");
2638
2639 // iterator SEMI_COLON
2640 TIntermTyped* iterator = nullptr;
2641 acceptExpression(iterator);
2642 if (! acceptTokenClass(EHTokRightParen))
2643 expected(")");
2644
2645 // statement
2646 if (! acceptScopedStatement(statement)) {
2647 expected("for sub-statement");
2648 return false;
2649 }
2650
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002651 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002652
2653 parseContext.popScope();
2654 parseContext.unnestLooping();
2655
2656 return true;
2657 }
2658
2659 default:
2660 return false;
2661 }
John Kessenich21472ae2016-06-04 11:46:33 -06002662}
2663
2664// jump_statement
2665// : CONTINUE SEMICOLON
2666// | BREAK SEMICOLON
2667// | DISCARD SEMICOLON
2668// | RETURN SEMICOLON
2669// | RETURN expression SEMICOLON
2670//
2671bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2672{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002673 EHlslTokenClass jump = peek();
2674 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002675 case EHTokContinue:
2676 case EHTokBreak:
2677 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002678 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002679 advanceToken();
2680 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002681 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002682 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002683 return false;
2684 }
John Kessenich21472ae2016-06-04 11:46:33 -06002685
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002686 switch (jump) {
2687 case EHTokContinue:
2688 statement = intermediate.addBranch(EOpContinue, token.loc);
2689 break;
2690 case EHTokBreak:
2691 statement = intermediate.addBranch(EOpBreak, token.loc);
2692 break;
2693 case EHTokDiscard:
2694 statement = intermediate.addBranch(EOpKill, token.loc);
2695 break;
2696
2697 case EHTokReturn:
2698 {
2699 // expression
2700 TIntermTyped* node;
2701 if (acceptExpression(node)) {
2702 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002703 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002704 } else
2705 statement = intermediate.addBranch(EOpReturn, token.loc);
2706 break;
2707 }
2708
2709 default:
2710 assert(0);
2711 return false;
2712 }
2713
2714 // SEMICOLON
2715 if (! acceptTokenClass(EHTokSemicolon))
2716 expected(";");
2717
2718 return true;
2719}
John Kessenich21472ae2016-06-04 11:46:33 -06002720
John Kessenichd02dc5d2016-07-01 00:04:11 -06002721// case_label
2722// : CASE expression COLON
2723//
John Kessenich21472ae2016-06-04 11:46:33 -06002724bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2725{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002726 TSourceLoc loc = token.loc;
2727 if (! acceptTokenClass(EHTokCase))
2728 return false;
2729
2730 TIntermTyped* expression;
2731 if (! acceptExpression(expression)) {
2732 expected("case expression");
2733 return false;
2734 }
2735
2736 if (! acceptTokenClass(EHTokColon)) {
2737 expected(":");
2738 return false;
2739 }
2740
2741 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2742
2743 return true;
2744}
2745
2746// default_label
2747// : DEFAULT COLON
2748//
2749bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2750{
2751 TSourceLoc loc = token.loc;
2752 if (! acceptTokenClass(EHTokDefault))
2753 return false;
2754
2755 if (! acceptTokenClass(EHTokColon)) {
2756 expected(":");
2757 return false;
2758 }
2759
2760 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2761
2762 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002763}
2764
John Kessenich19b92ff2016-06-19 11:50:34 -06002765// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06002766// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
2767// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002768//
2769void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2770{
2771 arraySizes = nullptr;
2772
steve-lunarg7b211a32016-10-13 12:26:18 -06002773 // Early-out if there aren't any array dimensions
2774 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06002775 return;
2776
steve-lunarg7b211a32016-10-13 12:26:18 -06002777 // 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 -06002778 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06002779
2780 // Collect each array dimension.
2781 while (acceptTokenClass(EHTokLeftBracket)) {
2782 TSourceLoc loc = token.loc;
2783 TIntermTyped* sizeExpr = nullptr;
2784
2785 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
2786 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
2787
2788 if (! acceptTokenClass(EHTokRightBracket)) {
2789 expected("]");
2790 return;
2791 }
2792
2793 if (hasArraySize) {
2794 TArraySize arraySize;
2795 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2796 arraySizes->addInnerSize(arraySize);
2797 } else {
2798 arraySizes->addInnerSize(0); // sized by initializers.
2799 }
steve-lunarg265c0612016-09-27 10:57:35 -06002800 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002801}
2802
John Kessenich630dd7d2016-06-12 23:52:12 -06002803// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002804// : COLON semantic // optional
2805// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2806// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002807// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002808// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002809//
John Kessenich7735b942016-09-05 12:40:06 -06002810void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002811{
John Kessenich630dd7d2016-06-12 23:52:12 -06002812 do {
2813 // COLON
2814 if (acceptTokenClass(EHTokColon)) {
2815 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002816 if (peekTokenClass(EHTokLayout))
2817 acceptLayoutQualifierList(qualifier);
2818 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002819 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002820 if (! acceptTokenClass(EHTokLeftParen)) {
2821 expected("(");
2822 return;
2823 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002824 HlslToken locationToken;
2825 if (! acceptIdentifier(locationToken)) {
2826 expected("c[subcomponent][.component]");
2827 return;
2828 }
2829 HlslToken componentToken;
2830 if (acceptTokenClass(EHTokDot)) {
2831 if (! acceptIdentifier(componentToken)) {
2832 expected("component");
2833 return;
2834 }
2835 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002836 if (! acceptTokenClass(EHTokRightParen)) {
2837 expected(")");
2838 break;
2839 }
John Kessenich7735b942016-09-05 12:40:06 -06002840 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002841 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002842 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002843 return;
2844 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002845 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2846 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002847 if (! acceptTokenClass(EHTokLeftParen)) {
2848 expected("(");
2849 return;
2850 }
John Kessenichb38f0712016-07-30 10:29:54 -06002851 HlslToken registerDesc; // for Type#
2852 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002853 if (! acceptIdentifier(registerDesc)) {
2854 expected("register number description");
2855 return;
2856 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002857 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2858 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002859 // Then we didn't really see the registerDesc yet, it was
2860 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002861 profile = registerDesc;
2862 if (! acceptIdentifier(registerDesc)) {
2863 expected("register number description");
2864 return;
2865 }
2866 }
John Kessenichb38f0712016-07-30 10:29:54 -06002867 int subComponent = 0;
2868 if (acceptTokenClass(EHTokLeftBracket)) {
2869 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2870 if (! peekTokenClass(EHTokIntConstant)) {
2871 expected("literal integer");
2872 return;
2873 }
2874 subComponent = token.i;
2875 advanceToken();
2876 if (! acceptTokenClass(EHTokRightBracket)) {
2877 expected("]");
2878 break;
2879 }
2880 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002881 // (COMMA SPACEN)opt
2882 HlslToken spaceDesc;
2883 if (acceptTokenClass(EHTokComma)) {
2884 if (! acceptIdentifier(spaceDesc)) {
2885 expected ("space identifier");
2886 return;
2887 }
2888 }
2889 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002890 if (! acceptTokenClass(EHTokRightParen)) {
2891 expected(")");
2892 break;
2893 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002894 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002895 } else {
2896 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002897 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002898 }
John Kessenicha1e2d492016-09-20 13:22:58 -06002899 } else if (peekTokenClass(EHTokLeftAngle))
2900 acceptAnnotations(qualifier);
2901 else
John Kessenich630dd7d2016-06-12 23:52:12 -06002902 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002903
John Kessenich630dd7d2016-06-12 23:52:12 -06002904 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002905}
2906
John Kesseniche01a9bc2016-03-12 20:11:22 -07002907} // end namespace glslang