blob: b2715eda84ce33eedf9d538b32fbe675774c9e42 [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"
steve-lunarg1868b142016-10-20 13:07:10 -060056#include "hlslAttributes.h"
John Kesseniche01a9bc2016-03-12 20:11:22 -070057
58namespace glslang {
59
60// Root entry point to this recursive decent parser.
61// Return true if compilation unit was successfully accepted.
62bool HlslGrammar::parse()
63{
64 advanceToken();
65 return acceptCompilationUnit();
66}
67
68void HlslGrammar::expected(const char* syntax)
69{
70 parseContext.error(token.loc, "Expected", syntax, "");
71}
72
LoopDawg4886f692016-06-29 10:58:58 -060073void HlslGrammar::unimplemented(const char* error)
74{
75 parseContext.error(token.loc, "Unimplemented", error, "");
76}
77
John Kessenichaecd4972016-03-14 10:46:34 -060078// Only process the next token if it is an identifier.
79// Return true if it was an identifier.
80bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
81{
82 if (peekTokenClass(EHTokIdentifier)) {
83 idToken = token;
84 advanceToken();
85 return true;
86 }
87
88 return false;
89}
90
John Kesseniche01a9bc2016-03-12 20:11:22 -070091// compilationUnit
92// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -060093// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -070094//
95bool HlslGrammar::acceptCompilationUnit()
96{
John Kessenichd016be12016-03-13 11:24:20 -060097 TIntermNode* unitNode = nullptr;
98
John Kessenich9c86c6a2016-05-03 22:49:24 -060099 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600100 // HLSL allows semicolons between global declarations, e.g, between functions.
101 if (acceptTokenClass(EHTokSemicolon))
102 continue;
103
John Kessenichd016be12016-03-13 11:24:20 -0600104 // externalDeclaration
105 TIntermNode* declarationNode;
106 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700107 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600108
109 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600110 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700111 }
112
John Kessenichd016be12016-03-13 11:24:20 -0600113 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600114 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600115
John Kesseniche01a9bc2016-03-12 20:11:22 -0700116 return true;
117}
118
LoopDawg4886f692016-06-29 10:58:58 -0600119// sampler_state
120// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
121//
122// sampler_state_assignment
123// : sampler_state_identifier EQUAL value SEMICOLON
124//
125// sampler_state_identifier
126// : ADDRESSU
127// | ADDRESSV
128// | ADDRESSW
129// | BORDERCOLOR
130// | FILTER
131// | MAXANISOTROPY
132// | MAXLOD
133// | MINLOD
134// | MIPLODBIAS
135//
136bool HlslGrammar::acceptSamplerState()
137{
138 // TODO: this should be genericized to accept a list of valid tokens and
139 // return token/value pairs. Presently it is specific to texture values.
140
141 if (! acceptTokenClass(EHTokLeftBrace))
142 return true;
143
144 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
145
146 do {
147 // read state name
148 HlslToken state;
149 if (! acceptIdentifier(state))
150 break; // end of list
151
152 // FXC accepts any case
153 TString stateName = *state.string;
154 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
155
156 if (! acceptTokenClass(EHTokAssign)) {
157 expected("assign");
158 return false;
159 }
160
161 if (stateName == "minlod" || stateName == "maxlod") {
162 if (! peekTokenClass(EHTokIntConstant)) {
163 expected("integer");
164 return false;
165 }
166
167 TIntermTyped* lod = nullptr;
168 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
169 return false;
170 } else if (stateName == "maxanisotropy") {
171 if (! peekTokenClass(EHTokIntConstant)) {
172 expected("integer");
173 return false;
174 }
175
176 TIntermTyped* maxAnisotropy = nullptr;
177 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
178 return false;
179 } else if (stateName == "filter") {
180 HlslToken filterMode;
181 if (! acceptIdentifier(filterMode)) {
182 expected("filter mode");
183 return false;
184 }
185 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
186 HlslToken addrMode;
187 if (! acceptIdentifier(addrMode)) {
188 expected("texture address mode");
189 return false;
190 }
191 } else if (stateName == "miplodbias") {
192 TIntermTyped* lodBias = nullptr;
193 if (! acceptLiteral(lodBias)) {
194 expected("lod bias");
195 return false;
196 }
197 } else if (stateName == "bordercolor") {
198 return false;
199 } else {
200 expected("texture state");
201 return false;
202 }
203
204 // SEMICOLON
205 if (! acceptTokenClass(EHTokSemicolon)) {
206 expected("semicolon");
207 return false;
208 }
209 } while (true);
210
211 if (! acceptTokenClass(EHTokRightBrace))
212 return false;
213
214 return true;
215}
216
217// sampler_declaration_dx9
218// : SAMPLER identifier EQUAL sampler_type sampler_state
219//
John Kesseniche4821e42016-07-16 10:19:43 -0600220bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600221{
222 if (! acceptTokenClass(EHTokSampler))
223 return false;
224
225 // TODO: remove this when DX9 style declarations are implemented.
226 unimplemented("Direct3D 9 sampler declaration");
227
228 // read sampler name
229 HlslToken name;
230 if (! acceptIdentifier(name)) {
231 expected("sampler name");
232 return false;
233 }
234
235 if (! acceptTokenClass(EHTokAssign)) {
236 expected("=");
237 return false;
238 }
239
240 return false;
241}
242
243
John Kesseniche01a9bc2016-03-12 20:11:22 -0700244// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600245// : sampler_declaration_dx9 post_decls SEMICOLON
246// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600247// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600248// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600249// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700250//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600251// declarator_list
252// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600253//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600254// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600255// : identifier array_specifier post_decls
256// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600257// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600258//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600259// Parsing has to go pretty far in to know whether it's a variable, prototype, or
260// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600261// as above. (The 'identifier' in the first item in init_declarator list is the
262// same as 'identifier' for function declarations.)
263//
264// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600265// or a function body.
266//
267bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700268{
John Kessenichd016be12016-03-13 11:24:20 -0600269 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600270 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600271
steve-lunarg1868b142016-10-20 13:07:10 -0600272 // attributes
273 TAttributeMap attributes;
274 acceptAttributes(attributes);
275
John Kessenich5e69ec62016-07-05 00:02:40 -0600276 // typedef
277 bool typedefDecl = acceptTokenClass(EHTokTypedef);
278
John Kesseniche82061d2016-09-27 14:38:57 -0600279 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600280
281 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600282 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
283 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
284 // HLSL shaders, this will have to be a master level switch
285 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
286 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400287
John Kesseniche82061d2016-09-27 14:38:57 -0600288 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400289 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600290
291 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600292 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700293 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600294
John Kessenich87142c72016-03-12 20:24:24 -0700295 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600296 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600297 while (acceptIdentifier(idToken)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600298 // function_parameters
John Kesseniche82061d2016-09-27 14:38:57 -0600299 TFunction& function = *new TFunction(idToken.string, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600300 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600301 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600302 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600303
John Kessenichd5ed0b62016-07-04 17:32:45 -0600304 // compound_statement (function body definition) or just a prototype?
305 if (peekTokenClass(EHTokLeftBrace)) {
306 if (list)
307 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600308 if (typedefDecl)
309 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
steve-lunarg1868b142016-10-20 13:07:10 -0600310 return acceptFunctionDefinition(function, node, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600311 } else {
312 if (typedefDecl)
313 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600314 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600315 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600316 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600317 // A variable declaration. Fix the storage qualifier if it's a global.
318 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
319 declaredType.getQualifier().storage = EvqUniform;
320
John Kesseniche82061d2016-09-27 14:38:57 -0600321 // We can handle multiple variables per type declaration, so
322 // the number of types can expand when arrayness is different.
323 TType variableType;
324 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600325
John Kesseniche82061d2016-09-27 14:38:57 -0600326 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600327 TArraySizes* arraySizes = nullptr;
328 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600329
John Kesseniche82061d2016-09-27 14:38:57 -0600330 // Fix arrayness in the variableType
331 if (declaredType.isImplicitlySizedArray()) {
332 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
333 // of different sizes, for this case sharing the shallow copy of arrayness
334 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
335 variableType.newArraySizes(declaredType.getArraySizes());
336 }
337 if (arraySizes || variableType.isArray()) {
338 // In the most general case, arrayness is potentially coming both from the
339 // declared type and from the variable: "int[] a[];" or just one or the other.
340 // Merge it all to the variableType, so all arrayness is part of the variableType.
341 parseContext.arrayDimMerge(variableType, arraySizes);
342 }
343
LoopDawg4886f692016-06-29 10:58:58 -0600344 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600345 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600346 if (! acceptSamplerState())
347 return false;
348 }
349
John Kessenichd5ed0b62016-07-04 17:32:45 -0600350 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600351 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600352
353 // EQUAL assignment_expression
354 TIntermTyped* expressionNode = nullptr;
355 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600356 if (typedefDecl)
357 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600358 if (! acceptAssignmentExpression(expressionNode)) {
359 expected("initializer");
360 return false;
361 }
362 }
363
John Kessenich6dbc0a72016-09-27 19:13:05 -0600364 // Hand off the actual declaration
365
366 // TODO: things scoped within an annotation need their own name space;
367 // TODO: strings are not yet handled.
368 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
369 if (typedefDecl)
370 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
371 else if (variableType.getBasicType() == EbtBlock)
372 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
373 else {
John Kessenichf571d0c2016-10-01 12:35:01 -0600374 if (variableType.getQualifier().storage == EvqUniform && ! variableType.isOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600375 // this isn't really an individual variable, but a member of the $Global buffer
376 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
377 } else {
378 // Declare the variable and add any initializer code to the AST.
379 // The top-level node is always made into an aggregate, as that's
380 // historically how the AST has been.
381 node = intermediate.growAggregate(node,
382 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
383 expressionNode),
384 idToken.loc);
385 }
386 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600387 }
John Kessenich5f934b02016-03-13 17:58:25 -0600388 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600389
390 if (acceptTokenClass(EHTokComma)) {
391 list = true;
392 continue;
393 }
394 };
395
396 // The top-level node is a sequence.
397 if (node != nullptr)
398 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700399
John Kessenich078d7f22016-03-14 10:02:11 -0600400 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600401 if (! acceptTokenClass(EHTokSemicolon)) {
402 expected(";");
403 return false;
404 }
405
John Kesseniche01a9bc2016-03-12 20:11:22 -0700406 return true;
407}
408
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600409// control_declaration
410// : fully_specified_type identifier EQUAL expression
411//
412bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
413{
414 node = nullptr;
415
416 // fully_specified_type
417 TType type;
418 if (! acceptFullySpecifiedType(type))
419 return false;
420
421 // identifier
422 HlslToken idToken;
423 if (! acceptIdentifier(idToken)) {
424 expected("identifier");
425 return false;
426 }
427
428 // EQUAL
429 TIntermTyped* expressionNode = nullptr;
430 if (! acceptTokenClass(EHTokAssign)) {
431 expected("=");
432 return false;
433 }
434
435 // expression
436 if (! acceptExpression(expressionNode)) {
437 expected("initializer");
438 return false;
439 }
440
John Kesseniche82061d2016-09-27 14:38:57 -0600441 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600442
443 return true;
444}
445
John Kessenich87142c72016-03-12 20:24:24 -0700446// fully_specified_type
447// : type_specifier
448// | type_qualifier type_specifier
449//
450bool HlslGrammar::acceptFullySpecifiedType(TType& type)
451{
452 // type_qualifier
453 TQualifier qualifier;
454 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600455 if (! acceptQualifier(qualifier))
456 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600457 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700458
459 // type_specifier
460 if (! acceptType(type))
461 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600462 if (type.getBasicType() == EbtBlock) {
463 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600464 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600465 // further, it can create an anonymous instance of the block
466 if (peekTokenClass(EHTokSemicolon))
467 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600468 } else {
469 // Some qualifiers are set when parsing the type. Merge those with
470 // whatever comes from acceptQualifier.
471 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700472
steve-lunargbb0183f2016-10-04 16:58:14 -0600473 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600474 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700475
476 if (type.getQualifier().storage == EvqVaryingOut)
477 qualifier.storage = type.getQualifier().storage;
478
479 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600480 }
John Kessenich87142c72016-03-12 20:24:24 -0700481
482 return true;
483}
484
John Kessenich630dd7d2016-06-12 23:52:12 -0600485// type_qualifier
486// : qualifier qualifier ...
487//
488// Zero or more of these, so this can't return false.
489//
John Kessenichb9e39122016-08-17 10:22:08 -0600490bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700491{
John Kessenich630dd7d2016-06-12 23:52:12 -0600492 do {
493 switch (peek()) {
494 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600495 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600496 break;
497 case EHTokExtern:
498 // TODO: no meaning in glslang?
499 break;
500 case EHTokShared:
501 // TODO: hint
502 break;
503 case EHTokGroupShared:
504 qualifier.storage = EvqShared;
505 break;
506 case EHTokUniform:
507 qualifier.storage = EvqUniform;
508 break;
509 case EHTokConst:
510 qualifier.storage = EvqConst;
511 break;
512 case EHTokVolatile:
513 qualifier.volatil = true;
514 break;
515 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600516 qualifier.smooth = true;
517 break;
518 case EHTokCentroid:
519 qualifier.centroid = true;
520 break;
521 case EHTokNointerpolation:
522 qualifier.flat = true;
523 break;
524 case EHTokNoperspective:
525 qualifier.nopersp = true;
526 break;
527 case EHTokSample:
528 qualifier.sample = true;
529 break;
530 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600531 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600532 break;
533 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600534 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600535 break;
536 case EHTokPrecise:
537 qualifier.noContraction = true;
538 break;
LoopDawg9249c702016-07-12 20:44:32 -0600539 case EHTokIn:
540 qualifier.storage = EvqIn;
541 break;
542 case EHTokOut:
543 qualifier.storage = EvqOut;
544 break;
545 case EHTokInOut:
546 qualifier.storage = EvqInOut;
547 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600548 case EHTokLayout:
549 if (! acceptLayoutQualifierList(qualifier))
550 return false;
551 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700552
553 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
554 // for output variables.
555 case EHTokPoint:
556 qualifier.storage = EvqIn;
557 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
558 return false;
559 break;
560 case EHTokLine:
561 qualifier.storage = EvqIn;
562 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
563 return false;
564 break;
565 case EHTokTriangle:
566 qualifier.storage = EvqIn;
567 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
568 return false;
569 break;
570 case EHTokLineAdj:
571 qualifier.storage = EvqIn;
572 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
573 return false;
574 break;
575 case EHTokTriangleAdj:
576 qualifier.storage = EvqIn;
577 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
578 return false;
579 break;
580
John Kessenich630dd7d2016-06-12 23:52:12 -0600581 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600582 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600583 }
584 advanceToken();
585 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700586}
587
John Kessenichb9e39122016-08-17 10:22:08 -0600588// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600589// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600590//
591// layout_qualifier
592// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600593// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600594//
595// Zero or more of these, so this can't return false.
596//
597bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
598{
599 if (! acceptTokenClass(EHTokLayout))
600 return false;
601
602 // LEFT_PAREN
603 if (! acceptTokenClass(EHTokLeftParen))
604 return false;
605
606 do {
607 // identifier
608 HlslToken idToken;
609 if (! acceptIdentifier(idToken))
610 break;
611
612 // EQUAL expression
613 if (acceptTokenClass(EHTokAssign)) {
614 TIntermTyped* expr;
615 if (! acceptConditionalExpression(expr)) {
616 expected("expression");
617 return false;
618 }
619 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
620 } else
621 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
622
623 // COMMA
624 if (! acceptTokenClass(EHTokComma))
625 break;
626 } while (true);
627
628 // RIGHT_PAREN
629 if (! acceptTokenClass(EHTokRightParen)) {
630 expected(")");
631 return false;
632 }
633
634 return true;
635}
636
LoopDawg6daaa4f2016-06-23 19:13:48 -0600637// template_type
638// : FLOAT
639// | DOUBLE
640// | INT
641// | DWORD
642// | UINT
643// | BOOL
644//
steve-lunargf49cdf42016-11-17 15:04:20 -0700645bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600646{
647 switch (peek()) {
648 case EHTokFloat:
649 basicType = EbtFloat;
650 break;
651 case EHTokDouble:
652 basicType = EbtDouble;
653 break;
654 case EHTokInt:
655 case EHTokDword:
656 basicType = EbtInt;
657 break;
658 case EHTokUint:
659 basicType = EbtUint;
660 break;
661 case EHTokBool:
662 basicType = EbtBool;
663 break;
664 default:
665 return false;
666 }
667
668 advanceToken();
669
670 return true;
671}
672
673// vector_template_type
674// : VECTOR
675// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
676//
677bool HlslGrammar::acceptVectorTemplateType(TType& type)
678{
679 if (! acceptTokenClass(EHTokVector))
680 return false;
681
682 if (! acceptTokenClass(EHTokLeftAngle)) {
683 // in HLSL, 'vector' alone means float4.
684 new(&type) TType(EbtFloat, EvqTemporary, 4);
685 return true;
686 }
687
688 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700689 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600690 expected("scalar type");
691 return false;
692 }
693
694 // COMMA
695 if (! acceptTokenClass(EHTokComma)) {
696 expected(",");
697 return false;
698 }
699
700 // integer
701 if (! peekTokenClass(EHTokIntConstant)) {
702 expected("literal integer");
703 return false;
704 }
705
706 TIntermTyped* vecSize;
707 if (! acceptLiteral(vecSize))
708 return false;
709
710 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
711
712 new(&type) TType(basicType, EvqTemporary, vecSizeI);
713
714 if (vecSizeI == 1)
715 type.makeVector();
716
717 if (!acceptTokenClass(EHTokRightAngle)) {
718 expected("right angle bracket");
719 return false;
720 }
721
722 return true;
723}
724
725// matrix_template_type
726// : MATRIX
727// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
728//
729bool HlslGrammar::acceptMatrixTemplateType(TType& type)
730{
731 if (! acceptTokenClass(EHTokMatrix))
732 return false;
733
734 if (! acceptTokenClass(EHTokLeftAngle)) {
735 // in HLSL, 'matrix' alone means float4x4.
736 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
737 return true;
738 }
739
740 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700741 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600742 expected("scalar type");
743 return false;
744 }
745
746 // COMMA
747 if (! acceptTokenClass(EHTokComma)) {
748 expected(",");
749 return false;
750 }
751
752 // integer rows
753 if (! peekTokenClass(EHTokIntConstant)) {
754 expected("literal integer");
755 return false;
756 }
757
758 TIntermTyped* rows;
759 if (! acceptLiteral(rows))
760 return false;
761
762 // COMMA
763 if (! acceptTokenClass(EHTokComma)) {
764 expected(",");
765 return false;
766 }
767
768 // integer cols
769 if (! peekTokenClass(EHTokIntConstant)) {
770 expected("literal integer");
771 return false;
772 }
773
774 TIntermTyped* cols;
775 if (! acceptLiteral(cols))
776 return false;
777
778 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600779 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
780 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600781
782 if (!acceptTokenClass(EHTokRightAngle)) {
783 expected("right angle bracket");
784 return false;
785 }
786
787 return true;
788}
789
steve-lunargf49cdf42016-11-17 15:04:20 -0700790// layout_geometry
791// : LINESTREAM
792// | POINTSTREAM
793// | TRIANGLESTREAM
794//
795bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
796{
797 // read geometry type
798 const EHlslTokenClass geometryType = peek();
799
800 switch (geometryType) {
801 case EHTokPointStream: geometry = ElgPoints; break;
802 case EHTokLineStream: geometry = ElgLineStrip; break;
803 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
804 default:
805 return false; // not a layout geometry
806 }
807
808 advanceToken(); // consume the layout keyword
809 return true;
810}
811
812// stream_out_template_type
813// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
814//
815bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
816{
817 geometry = ElgNone;
818
819 if (! acceptOutputPrimitiveGeometry(geometry))
820 return false;
821
822 if (! acceptTokenClass(EHTokLeftAngle))
823 return false;
824
825 if (! acceptType(type)) {
826 expected("stream output type");
827 return false;
828 }
829
830 type.getQualifier().storage = EvqVaryingOut;
831
832 if (! acceptTokenClass(EHTokRightAngle)) {
833 expected("right angle bracket");
834 return false;
835 }
836
837 return true;
838}
839
John Kessenicha1e2d492016-09-20 13:22:58 -0600840// annotations
841// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600842//
John Kessenicha1e2d492016-09-20 13:22:58 -0600843bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600844{
John Kessenicha1e2d492016-09-20 13:22:58 -0600845 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600846 return false;
847
John Kessenicha1e2d492016-09-20 13:22:58 -0600848 // note that we are nesting a name space
849 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600850
851 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
852 do {
853 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
854 while (acceptTokenClass(EHTokSemicolon))
855 ;
856
857 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600858 break;
John Kessenich86f71382016-09-19 20:23:18 -0600859
860 // declaration
861 TIntermNode* node;
862 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600863 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600864 return false;
865 }
866 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600867
868 parseContext.unnestAnnotations();
869 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600870}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600871
LoopDawg4886f692016-06-29 10:58:58 -0600872// sampler_type
873// : SAMPLER
874// | SAMPLER1D
875// | SAMPLER2D
876// | SAMPLER3D
877// | SAMPLERCUBE
878// | SAMPLERSTATE
879// | SAMPLERCOMPARISONSTATE
880bool HlslGrammar::acceptSamplerType(TType& type)
881{
882 // read sampler type
883 const EHlslTokenClass samplerType = peek();
884
LoopDawga78b0292016-07-19 14:28:05 -0600885 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600886 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600887
LoopDawga78b0292016-07-19 14:28:05 -0600888 bool isShadow = false;
889
LoopDawg4886f692016-06-29 10:58:58 -0600890 switch (samplerType) {
891 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600892 case EHTokSampler1d: /*dim = Esd1D*/; break;
893 case EHTokSampler2d: /*dim = Esd2D*/; break;
894 case EHTokSampler3d: /*dim = Esd3D*/; break;
895 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600896 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600897 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600898 default:
899 return false; // not a sampler declaration
900 }
901
902 advanceToken(); // consume the sampler type keyword
903
904 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600905
906 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600907 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600908
909 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
910
911 return true;
912}
913
914// texture_type
915// | BUFFER
916// | TEXTURE1D
917// | TEXTURE1DARRAY
918// | TEXTURE2D
919// | TEXTURE2DARRAY
920// | TEXTURE3D
921// | TEXTURECUBE
922// | TEXTURECUBEARRAY
923// | TEXTURE2DMS
924// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600925// | RWBUFFER
926// | RWTEXTURE1D
927// | RWTEXTURE1DARRAY
928// | RWTEXTURE2D
929// | RWTEXTURE2DARRAY
930// | RWTEXTURE3D
931
LoopDawg4886f692016-06-29 10:58:58 -0600932bool HlslGrammar::acceptTextureType(TType& type)
933{
934 const EHlslTokenClass textureType = peek();
935
936 TSamplerDim dim = EsdNone;
937 bool array = false;
938 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600939 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600940
941 switch (textureType) {
942 case EHTokBuffer: dim = EsdBuffer; break;
943 case EHTokTexture1d: dim = Esd1D; break;
944 case EHTokTexture1darray: dim = Esd1D; array = true; break;
945 case EHTokTexture2d: dim = Esd2D; break;
946 case EHTokTexture2darray: dim = Esd2D; array = true; break;
947 case EHTokTexture3d: dim = Esd3D; break;
948 case EHTokTextureCube: dim = EsdCube; break;
949 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
950 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
951 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -0600952 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
953 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
954 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
955 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
956 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
957 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600958 default:
959 return false; // not a texture declaration
960 }
961
962 advanceToken(); // consume the texture object keyword
963
964 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
965
966 TIntermTyped* msCount = nullptr;
967
steve-lunargbb0183f2016-10-04 16:58:14 -0600968 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -0600969 if (acceptTokenClass(EHTokLeftAngle)) {
970 if (! acceptType(txType)) {
971 expected("scalar or vector type");
972 return false;
973 }
974
975 const TBasicType basicRetType = txType.getBasicType() ;
976
977 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
978 unimplemented("basic type in texture");
979 return false;
980 }
981
steve-lunargd53f7172016-07-27 15:46:48 -0600982 // Buffers can handle small mats if they fit in 4 components
983 if (dim == EsdBuffer && txType.isMatrix()) {
984 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
985 expected("components < 4 in matrix buffer type");
986 return false;
987 }
988
989 // TODO: except we don't handle it yet...
990 unimplemented("matrix type in buffer");
991 return false;
992 }
993
LoopDawg4886f692016-06-29 10:58:58 -0600994 if (!txType.isScalar() && !txType.isVector()) {
995 expected("scalar or vector type");
996 return false;
997 }
998
LoopDawg4886f692016-06-29 10:58:58 -0600999 if (ms && acceptTokenClass(EHTokComma)) {
1000 // read sample count for multisample types, if given
1001 if (! peekTokenClass(EHTokIntConstant)) {
1002 expected("multisample count");
1003 return false;
1004 }
1005
1006 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1007 return false;
1008 }
1009
1010 if (! acceptTokenClass(EHTokRightAngle)) {
1011 expected("right angle bracket");
1012 return false;
1013 }
1014 } else if (ms) {
1015 expected("texture type for multisample");
1016 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001017 } else if (image) {
1018 expected("type for RWTexture/RWBuffer");
1019 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001020 }
1021
1022 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001023 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001024
1025 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001026 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001027
steve-lunarg4f2da272016-10-10 15:24:57 -06001028 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1029 if (image || dim == EsdBuffer)
1030 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001031
1032 // Non-image Buffers are combined
1033 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001034 sampler.set(txType.getBasicType(), dim, array);
1035 } else {
1036 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001037 if (image) {
1038 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1039 } else {
1040 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1041 }
steve-lunargd53f7172016-07-27 15:46:48 -06001042 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001043
1044 // Remember the declared vector size.
1045 sampler.vectorSize = txType.getVectorSize();
LoopDawg4886f692016-06-29 10:58:58 -06001046
1047 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001048 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001049
1050 return true;
1051}
1052
1053
John Kessenich87142c72016-03-12 20:24:24 -07001054// If token is for a type, update 'type' with the type information,
1055// and return true and advance.
1056// Otherwise, return false, and don't advance
1057bool HlslGrammar::acceptType(TType& type)
1058{
steve-lunarg3226b082016-10-26 19:18:55 -06001059 // Basic types for min* types, broken out here in case of future
1060 // changes, e.g, to use native halfs.
1061 static const TBasicType min16float_bt = EbtFloat;
1062 static const TBasicType min10float_bt = EbtFloat;
1063 static const TBasicType min16int_bt = EbtInt;
1064 static const TBasicType min12int_bt = EbtInt;
1065 static const TBasicType min16uint_bt = EbtUint;
1066
John Kessenich9c86c6a2016-05-03 22:49:24 -06001067 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001068 case EHTokVector:
1069 return acceptVectorTemplateType(type);
1070 break;
1071
1072 case EHTokMatrix:
1073 return acceptMatrixTemplateType(type);
1074 break;
1075
steve-lunargf49cdf42016-11-17 15:04:20 -07001076 case EHTokPointStream: // fall through
1077 case EHTokLineStream: // ...
1078 case EHTokTriangleStream: // ...
1079 {
1080 TLayoutGeometry geometry;
1081 if (! acceptStreamOutTemplateType(type, geometry))
1082 return false;
1083
1084 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1085 return false;
1086
1087 return true;
1088 }
1089
LoopDawg4886f692016-06-29 10:58:58 -06001090 case EHTokSampler: // fall through
1091 case EHTokSampler1d: // ...
1092 case EHTokSampler2d: // ...
1093 case EHTokSampler3d: // ...
1094 case EHTokSamplerCube: // ...
1095 case EHTokSamplerState: // ...
1096 case EHTokSamplerComparisonState: // ...
1097 return acceptSamplerType(type);
1098 break;
1099
1100 case EHTokBuffer: // fall through
1101 case EHTokTexture1d: // ...
1102 case EHTokTexture1darray: // ...
1103 case EHTokTexture2d: // ...
1104 case EHTokTexture2darray: // ...
1105 case EHTokTexture3d: // ...
1106 case EHTokTextureCube: // ...
1107 case EHTokTextureCubearray: // ...
1108 case EHTokTexture2DMS: // ...
1109 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001110 case EHTokRWTexture1d: // ...
1111 case EHTokRWTexture1darray: // ...
1112 case EHTokRWTexture2d: // ...
1113 case EHTokRWTexture2darray: // ...
1114 case EHTokRWTexture3d: // ...
1115 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001116 return acceptTextureType(type);
1117 break;
1118
John Kesseniche6e74942016-06-11 16:43:14 -06001119 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001120 case EHTokCBuffer:
1121 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001122 return acceptStruct(type);
1123 break;
1124
1125 case EHTokIdentifier:
1126 // An identifier could be for a user-defined type.
1127 // Note we cache the symbol table lookup, to save for a later rule
1128 // when this is not a type.
1129 token.symbol = parseContext.symbolTable.find(*token.string);
1130 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1131 type.shallowCopy(token.symbol->getType());
1132 advanceToken();
1133 return true;
1134 } else
1135 return false;
1136
John Kessenich71351de2016-06-08 12:50:56 -06001137 case EHTokVoid:
1138 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001139 break;
John Kessenich71351de2016-06-08 12:50:56 -06001140
John Kessenicha1e2d492016-09-20 13:22:58 -06001141 case EHTokString:
1142 new(&type) TType(EbtString);
1143 break;
1144
John Kessenich87142c72016-03-12 20:24:24 -07001145 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001146 new(&type) TType(EbtFloat);
1147 break;
John Kessenich87142c72016-03-12 20:24:24 -07001148 case EHTokFloat1:
1149 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001150 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001151 break;
John Kessenich87142c72016-03-12 20:24:24 -07001152 case EHTokFloat2:
1153 new(&type) TType(EbtFloat, EvqTemporary, 2);
1154 break;
1155 case EHTokFloat3:
1156 new(&type) TType(EbtFloat, EvqTemporary, 3);
1157 break;
1158 case EHTokFloat4:
1159 new(&type) TType(EbtFloat, EvqTemporary, 4);
1160 break;
1161
John Kessenich71351de2016-06-08 12:50:56 -06001162 case EHTokDouble:
1163 new(&type) TType(EbtDouble);
1164 break;
1165 case EHTokDouble1:
1166 new(&type) TType(EbtDouble);
1167 type.makeVector();
1168 break;
1169 case EHTokDouble2:
1170 new(&type) TType(EbtDouble, EvqTemporary, 2);
1171 break;
1172 case EHTokDouble3:
1173 new(&type) TType(EbtDouble, EvqTemporary, 3);
1174 break;
1175 case EHTokDouble4:
1176 new(&type) TType(EbtDouble, EvqTemporary, 4);
1177 break;
1178
1179 case EHTokInt:
1180 case EHTokDword:
1181 new(&type) TType(EbtInt);
1182 break;
1183 case EHTokInt1:
1184 new(&type) TType(EbtInt);
1185 type.makeVector();
1186 break;
John Kessenich87142c72016-03-12 20:24:24 -07001187 case EHTokInt2:
1188 new(&type) TType(EbtInt, EvqTemporary, 2);
1189 break;
1190 case EHTokInt3:
1191 new(&type) TType(EbtInt, EvqTemporary, 3);
1192 break;
1193 case EHTokInt4:
1194 new(&type) TType(EbtInt, EvqTemporary, 4);
1195 break;
1196
John Kessenich71351de2016-06-08 12:50:56 -06001197 case EHTokUint:
1198 new(&type) TType(EbtUint);
1199 break;
1200 case EHTokUint1:
1201 new(&type) TType(EbtUint);
1202 type.makeVector();
1203 break;
1204 case EHTokUint2:
1205 new(&type) TType(EbtUint, EvqTemporary, 2);
1206 break;
1207 case EHTokUint3:
1208 new(&type) TType(EbtUint, EvqTemporary, 3);
1209 break;
1210 case EHTokUint4:
1211 new(&type) TType(EbtUint, EvqTemporary, 4);
1212 break;
1213
LoopDawg6daaa4f2016-06-23 19:13:48 -06001214
John Kessenich71351de2016-06-08 12:50:56 -06001215 case EHTokBool:
1216 new(&type) TType(EbtBool);
1217 break;
1218 case EHTokBool1:
1219 new(&type) TType(EbtBool);
1220 type.makeVector();
1221 break;
John Kessenich87142c72016-03-12 20:24:24 -07001222 case EHTokBool2:
1223 new(&type) TType(EbtBool, EvqTemporary, 2);
1224 break;
1225 case EHTokBool3:
1226 new(&type) TType(EbtBool, EvqTemporary, 3);
1227 break;
1228 case EHTokBool4:
1229 new(&type) TType(EbtBool, EvqTemporary, 4);
1230 break;
1231
steve-lunarg3226b082016-10-26 19:18:55 -06001232 case EHTokMin16float:
1233 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1234 break;
1235 case EHTokMin16float1:
1236 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1237 type.makeVector();
1238 break;
1239 case EHTokMin16float2:
1240 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1241 break;
1242 case EHTokMin16float3:
1243 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1244 break;
1245 case EHTokMin16float4:
1246 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1247 break;
1248
1249 case EHTokMin10float:
1250 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1251 break;
1252 case EHTokMin10float1:
1253 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1254 type.makeVector();
1255 break;
1256 case EHTokMin10float2:
1257 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1258 break;
1259 case EHTokMin10float3:
1260 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1261 break;
1262 case EHTokMin10float4:
1263 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1264 break;
1265
1266 case EHTokMin16int:
1267 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1268 break;
1269 case EHTokMin16int1:
1270 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1271 type.makeVector();
1272 break;
1273 case EHTokMin16int2:
1274 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1275 break;
1276 case EHTokMin16int3:
1277 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1278 break;
1279 case EHTokMin16int4:
1280 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1281 break;
1282
1283 case EHTokMin12int:
1284 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1285 break;
1286 case EHTokMin12int1:
1287 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1288 type.makeVector();
1289 break;
1290 case EHTokMin12int2:
1291 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1292 break;
1293 case EHTokMin12int3:
1294 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1295 break;
1296 case EHTokMin12int4:
1297 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1298 break;
1299
1300 case EHTokMin16uint:
1301 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1302 break;
1303 case EHTokMin16uint1:
1304 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1305 type.makeVector();
1306 break;
1307 case EHTokMin16uint2:
1308 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1309 break;
1310 case EHTokMin16uint3:
1311 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1312 break;
1313 case EHTokMin16uint4:
1314 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1315 break;
1316
John Kessenich0133c122016-05-20 12:17:26 -06001317 case EHTokInt1x1:
1318 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1319 break;
1320 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001321 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001322 break;
1323 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001324 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001325 break;
1326 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001327 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001328 break;
1329 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001330 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001331 break;
1332 case EHTokInt2x2:
1333 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1334 break;
1335 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001336 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001337 break;
1338 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001339 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001340 break;
1341 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001342 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001343 break;
1344 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001345 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001346 break;
1347 case EHTokInt3x3:
1348 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1349 break;
1350 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001351 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001352 break;
1353 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001354 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001355 break;
1356 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001357 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001358 break;
1359 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001360 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001361 break;
1362 case EHTokInt4x4:
1363 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1364 break;
1365
John Kessenich71351de2016-06-08 12:50:56 -06001366 case EHTokUint1x1:
1367 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1368 break;
1369 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001370 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001371 break;
1372 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001373 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001374 break;
1375 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001376 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001377 break;
1378 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001379 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001380 break;
1381 case EHTokUint2x2:
1382 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1383 break;
1384 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001385 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001386 break;
1387 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001388 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001389 break;
1390 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001391 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001392 break;
1393 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001394 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001395 break;
1396 case EHTokUint3x3:
1397 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1398 break;
1399 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001400 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001401 break;
1402 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001403 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001404 break;
1405 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001406 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001407 break;
1408 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001409 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001410 break;
1411 case EHTokUint4x4:
1412 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1413 break;
1414
1415 case EHTokBool1x1:
1416 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1417 break;
1418 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001419 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001420 break;
1421 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001422 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001423 break;
1424 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001425 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001426 break;
1427 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001428 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001429 break;
1430 case EHTokBool2x2:
1431 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1432 break;
1433 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001434 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001435 break;
1436 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001437 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001438 break;
1439 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001440 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001441 break;
1442 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001443 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001444 break;
1445 case EHTokBool3x3:
1446 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1447 break;
1448 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001449 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001450 break;
1451 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001452 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001453 break;
1454 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001455 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001456 break;
1457 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001458 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001459 break;
1460 case EHTokBool4x4:
1461 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1462 break;
1463
John Kessenich0133c122016-05-20 12:17:26 -06001464 case EHTokFloat1x1:
1465 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1466 break;
1467 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001468 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001469 break;
1470 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001471 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001472 break;
1473 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001474 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001475 break;
1476 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001477 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001478 break;
John Kessenich87142c72016-03-12 20:24:24 -07001479 case EHTokFloat2x2:
1480 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1481 break;
1482 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001483 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001484 break;
1485 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001486 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001487 break;
John Kessenich0133c122016-05-20 12:17:26 -06001488 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001489 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001490 break;
John Kessenich87142c72016-03-12 20:24:24 -07001491 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001492 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001493 break;
1494 case EHTokFloat3x3:
1495 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1496 break;
1497 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001498 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001499 break;
John Kessenich0133c122016-05-20 12:17:26 -06001500 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001501 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001502 break;
John Kessenich87142c72016-03-12 20:24:24 -07001503 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001504 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001505 break;
1506 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001507 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001508 break;
1509 case EHTokFloat4x4:
1510 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1511 break;
1512
John Kessenich0133c122016-05-20 12:17:26 -06001513 case EHTokDouble1x1:
1514 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1515 break;
1516 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001517 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001518 break;
1519 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001520 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001521 break;
1522 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001523 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001524 break;
1525 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001526 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001527 break;
1528 case EHTokDouble2x2:
1529 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1530 break;
1531 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001532 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001533 break;
1534 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001535 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001536 break;
1537 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001538 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001539 break;
1540 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001541 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001542 break;
1543 case EHTokDouble3x3:
1544 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1545 break;
1546 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001547 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001548 break;
1549 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001550 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001551 break;
1552 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001553 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001554 break;
1555 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001556 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001557 break;
1558 case EHTokDouble4x4:
1559 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1560 break;
1561
John Kessenich87142c72016-03-12 20:24:24 -07001562 default:
1563 return false;
1564 }
1565
1566 advanceToken();
1567
1568 return true;
1569}
1570
John Kesseniche6e74942016-06-11 16:43:14 -06001571// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001572// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1573// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1574//
1575// struct_type
1576// : STRUCT
1577// | CBUFFER
1578// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001579//
1580bool HlslGrammar::acceptStruct(TType& type)
1581{
John Kessenichb804de62016-09-05 12:19:18 -06001582 // This storage qualifier will tell us whether it's an AST
1583 // block type or just a generic structure type.
1584 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001585
1586 // CBUFFER
1587 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001588 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001589 // TBUFFER
1590 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001591 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001592 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001593 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001594 return false;
1595
1596 // IDENTIFIER
1597 TString structName = "";
1598 if (peekTokenClass(EHTokIdentifier)) {
1599 structName = *token.string;
1600 advanceToken();
1601 }
1602
John Kessenich3d157c52016-07-25 16:05:33 -06001603 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001604 TQualifier postDeclQualifier;
1605 postDeclQualifier.clear();
1606 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001607
John Kesseniche6e74942016-06-11 16:43:14 -06001608 // LEFT_BRACE
1609 if (! acceptTokenClass(EHTokLeftBrace)) {
1610 expected("{");
1611 return false;
1612 }
1613
1614 // struct_declaration_list
1615 TTypeList* typeList;
1616 if (! acceptStructDeclarationList(typeList)) {
1617 expected("struct member declarations");
1618 return false;
1619 }
1620
1621 // RIGHT_BRACE
1622 if (! acceptTokenClass(EHTokRightBrace)) {
1623 expected("}");
1624 return false;
1625 }
1626
1627 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001628 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001629 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001630 else {
John Kessenich7735b942016-09-05 12:40:06 -06001631 postDeclQualifier.storage = storageQualifier;
1632 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001633 }
John Kesseniche6e74942016-06-11 16:43:14 -06001634
John Kessenich3d157c52016-07-25 16:05:33 -06001635 // If it was named, which means the type can be reused later, add
1636 // it to the symbol table. (Unless it's a block, in which
1637 // case the name is not a type.)
1638 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001639 TVariable* userTypeDef = new TVariable(&structName, type, true);
1640 if (! parseContext.symbolTable.insert(*userTypeDef))
1641 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1642 }
1643
1644 return true;
1645}
1646
1647// struct_declaration_list
1648// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1649//
1650// struct_declaration
1651// : fully_specified_type struct_declarator COMMA struct_declarator ...
1652//
1653// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001654// : IDENTIFIER post_decls
1655// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001656//
1657bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1658{
1659 typeList = new TTypeList();
1660
1661 do {
1662 // success on seeing the RIGHT_BRACE coming up
1663 if (peekTokenClass(EHTokRightBrace))
1664 return true;
1665
1666 // struct_declaration
1667
1668 // fully_specified_type
1669 TType memberType;
1670 if (! acceptFullySpecifiedType(memberType)) {
1671 expected("member type");
1672 return false;
1673 }
1674
1675 // struct_declarator COMMA struct_declarator ...
1676 do {
1677 // peek IDENTIFIER
1678 if (! peekTokenClass(EHTokIdentifier)) {
1679 expected("member name");
1680 return false;
1681 }
1682
1683 // add it to the list of members
1684 TTypeLoc member = { new TType(EbtVoid), token.loc };
1685 member.type->shallowCopy(memberType);
1686 member.type->setFieldName(*token.string);
1687 typeList->push_back(member);
1688
1689 // accept IDENTIFIER
1690 advanceToken();
1691
1692 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001693 TArraySizes* arraySizes = nullptr;
1694 acceptArraySpecifier(arraySizes);
1695 if (arraySizes)
1696 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001697
John Kessenich7735b942016-09-05 12:40:06 -06001698 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001699
John Kesseniche6e74942016-06-11 16:43:14 -06001700 // success on seeing the SEMICOLON coming up
1701 if (peekTokenClass(EHTokSemicolon))
1702 break;
1703
1704 // COMMA
1705 if (! acceptTokenClass(EHTokComma)) {
1706 expected(",");
1707 return false;
1708 }
1709
1710 } while (true);
1711
1712 // SEMI_COLON
1713 if (! acceptTokenClass(EHTokSemicolon)) {
1714 expected(";");
1715 return false;
1716 }
1717
1718 } while (true);
1719}
1720
John Kessenich5f934b02016-03-13 17:58:25 -06001721// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001722// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001723// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001724//
1725bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1726{
John Kessenich078d7f22016-03-14 10:02:11 -06001727 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001728 if (! acceptTokenClass(EHTokLeftParen))
1729 return false;
1730
John Kessenich71351de2016-06-08 12:50:56 -06001731 // VOID RIGHT_PAREN
1732 if (! acceptTokenClass(EHTokVoid)) {
1733 do {
1734 // parameter_declaration
1735 if (! acceptParameterDeclaration(function))
1736 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001737
John Kessenich71351de2016-06-08 12:50:56 -06001738 // COMMA
1739 if (! acceptTokenClass(EHTokComma))
1740 break;
1741 } while (true);
1742 }
John Kessenich5f934b02016-03-13 17:58:25 -06001743
John Kessenich078d7f22016-03-14 10:02:11 -06001744 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001745 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001746 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001747 return false;
1748 }
1749
1750 return true;
1751}
1752
1753// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001754// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001755// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001756//
1757bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1758{
1759 // fully_specified_type
1760 TType* type = new TType;
1761 if (! acceptFullySpecifiedType(*type))
1762 return false;
1763
1764 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001765 HlslToken idToken;
1766 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001767
John Kessenich19b92ff2016-06-19 11:50:34 -06001768 // array_specifier
1769 TArraySizes* arraySizes = nullptr;
1770 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001771 if (arraySizes) {
1772 if (arraySizes->isImplicit()) {
1773 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1774 return false;
1775 }
1776
John Kessenich19b92ff2016-06-19 11:50:34 -06001777 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001778 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001779
1780 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001781 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001782
John Kessenich5aa59e22016-06-17 15:50:47 -06001783 parseContext.paramFix(*type);
1784
John Kessenichaecd4972016-03-14 10:46:34 -06001785 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001786 function.addParameter(param);
1787
1788 return true;
1789}
1790
1791// Do the work to create the function definition in addition to
1792// parsing the body (compound_statement).
steve-lunarg1868b142016-10-20 13:07:10 -06001793bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001794{
John Kessenicha3051662016-09-02 19:13:36 -06001795 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001796 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001797
John Kessenich077e0522016-06-09 02:02:17 -06001798 // This does a pushScope()
steve-lunarg1868b142016-10-20 13:07:10 -06001799 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06001800
1801 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001802 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001803 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001804 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001805 return true;
1806 }
1807
1808 return false;
1809}
1810
John Kessenich0d2b6de2016-06-05 11:23:11 -06001811// Accept an expression with parenthesis around it, where
1812// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001813// syntactically required ones like in "if ( expression )".
1814//
1815// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001816//
1817// Note this one is not set up to be speculative; as it gives
1818// errors if not found.
1819//
1820bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1821{
1822 // LEFT_PAREN
1823 if (! acceptTokenClass(EHTokLeftParen))
1824 expected("(");
1825
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001826 bool decl = false;
1827 TIntermNode* declNode = nullptr;
1828 decl = acceptControlDeclaration(declNode);
1829 if (decl) {
1830 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1831 expected("initialized declaration");
1832 return false;
1833 } else
1834 expression = declNode->getAsTyped();
1835 } else {
1836 // no declaration
1837 if (! acceptExpression(expression)) {
1838 expected("expression");
1839 return false;
1840 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001841 }
1842
1843 // RIGHT_PAREN
1844 if (! acceptTokenClass(EHTokRightParen))
1845 expected(")");
1846
1847 return true;
1848}
1849
John Kessenich34fb0362016-05-03 23:17:20 -06001850// The top-level full expression recognizer.
1851//
John Kessenich87142c72016-03-12 20:24:24 -07001852// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001853// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001854//
1855bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1856{
LoopDawgef764a22016-06-03 09:17:51 -06001857 node = nullptr;
1858
John Kessenich34fb0362016-05-03 23:17:20 -06001859 // assignment_expression
1860 if (! acceptAssignmentExpression(node))
1861 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001862
John Kessenich34fb0362016-05-03 23:17:20 -06001863 if (! peekTokenClass(EHTokComma))
1864 return true;
1865
1866 do {
1867 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001868 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001869 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001870
John Kessenich34fb0362016-05-03 23:17:20 -06001871 // ... assignment_expression
1872 TIntermTyped* rightNode = nullptr;
1873 if (! acceptAssignmentExpression(rightNode)) {
1874 expected("assignment expression");
1875 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001876 }
1877
John Kessenich34fb0362016-05-03 23:17:20 -06001878 node = intermediate.addComma(node, rightNode, loc);
1879
1880 if (! peekTokenClass(EHTokComma))
1881 return true;
1882 } while (true);
1883}
1884
John Kessenich07354242016-07-01 19:58:06 -06001885// initializer
1886// : LEFT_BRACE initializer_list RIGHT_BRACE
1887//
1888// initializer_list
1889// : assignment_expression COMMA assignment_expression COMMA ...
1890//
1891bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1892{
1893 // LEFT_BRACE
1894 if (! acceptTokenClass(EHTokLeftBrace))
1895 return false;
1896
1897 // initializer_list
1898 TSourceLoc loc = token.loc;
1899 node = nullptr;
1900 do {
1901 // assignment_expression
1902 TIntermTyped* expr;
1903 if (! acceptAssignmentExpression(expr)) {
1904 expected("assignment expression in initializer list");
1905 return false;
1906 }
1907 node = intermediate.growAggregate(node, expr, loc);
1908
1909 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001910 if (acceptTokenClass(EHTokComma)) {
1911 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1912 return true;
John Kessenich07354242016-07-01 19:58:06 -06001913 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001914 }
John Kessenich07354242016-07-01 19:58:06 -06001915
1916 // RIGHT_BRACE
1917 if (acceptTokenClass(EHTokRightBrace))
1918 return true;
1919
1920 expected(", or }");
1921 return false;
1922 } while (true);
1923}
1924
John Kessenich34fb0362016-05-03 23:17:20 -06001925// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001926// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001927//
1928// a op (b op (c op d))
1929//
1930// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001931// : initializer
1932// | conditional_expression
1933// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001934//
1935bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1936{
John Kessenich07354242016-07-01 19:58:06 -06001937 // initializer
1938 if (peekTokenClass(EHTokLeftBrace)) {
1939 if (acceptInitializer(node))
1940 return true;
1941
1942 expected("initializer");
1943 return false;
1944 }
1945
John Kessenich00957f82016-07-27 10:39:57 -06001946 // conditional_expression
1947 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001948 return false;
1949
John Kessenich07354242016-07-01 19:58:06 -06001950 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001951 TOperator assignOp = HlslOpMap::assignment(peek());
1952 if (assignOp == EOpNull)
1953 return true;
1954
John Kessenich00957f82016-07-27 10:39:57 -06001955 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001956 TSourceLoc loc = token.loc;
1957 advanceToken();
1958
John Kessenich00957f82016-07-27 10:39:57 -06001959 // conditional_expression assign_op conditional_expression ...
1960 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001961 // gets the right-to-left associativity.
1962 TIntermTyped* rightNode = nullptr;
1963 if (! acceptAssignmentExpression(rightNode)) {
1964 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001965 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001966 }
1967
John Kessenichd21baed2016-09-16 03:05:12 -06001968 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06001969 node = parseContext.handleLvalue(loc, "assign", node);
1970
John Kessenichfea226b2016-07-28 17:53:56 -06001971 if (node == nullptr) {
1972 parseContext.error(loc, "could not create assignment", "", "");
1973 return false;
1974 }
John Kessenich34fb0362016-05-03 23:17:20 -06001975
1976 if (! peekTokenClass(EHTokComma))
1977 return true;
1978
1979 return true;
1980}
1981
John Kessenich00957f82016-07-27 10:39:57 -06001982// Accept a conditional expression, which associates right-to-left,
1983// accomplished by the "true" expression calling down to lower
1984// precedence levels than this level.
1985//
1986// conditional_expression
1987// : binary_expression
1988// | binary_expression QUESTION expression COLON assignment_expression
1989//
1990bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1991{
1992 // binary_expression
1993 if (! acceptBinaryExpression(node, PlLogicalOr))
1994 return false;
1995
1996 if (! acceptTokenClass(EHTokQuestion))
1997 return true;
1998
1999 TIntermTyped* trueNode = nullptr;
2000 if (! acceptExpression(trueNode)) {
2001 expected("expression after ?");
2002 return false;
2003 }
2004 TSourceLoc loc = token.loc;
2005
2006 if (! acceptTokenClass(EHTokColon)) {
2007 expected(":");
2008 return false;
2009 }
2010
2011 TIntermTyped* falseNode = nullptr;
2012 if (! acceptAssignmentExpression(falseNode)) {
2013 expected("expression after :");
2014 return false;
2015 }
2016
2017 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2018
2019 return true;
2020}
2021
John Kessenich34fb0362016-05-03 23:17:20 -06002022// Accept a binary expression, for binary operations that
2023// associate left-to-right. This is, it is implicit, for example
2024//
2025// ((a op b) op c) op d
2026//
2027// binary_expression
2028// : expression op expression op expression ...
2029//
2030// where 'expression' is the next higher level in precedence.
2031//
2032bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2033{
2034 if (precedenceLevel > PlMul)
2035 return acceptUnaryExpression(node);
2036
2037 // assignment_expression
2038 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2039 return false;
2040
John Kessenich34fb0362016-05-03 23:17:20 -06002041 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002042 TOperator op = HlslOpMap::binary(peek());
2043 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2044 if (tokenLevel < precedenceLevel)
2045 return true;
2046
John Kessenich34fb0362016-05-03 23:17:20 -06002047 // ... op
2048 TSourceLoc loc = token.loc;
2049 advanceToken();
2050
2051 // ... expression
2052 TIntermTyped* rightNode = nullptr;
2053 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2054 expected("expression");
2055 return false;
2056 }
2057
2058 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002059 if (node == nullptr) {
2060 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2061 return false;
2062 }
John Kessenich34fb0362016-05-03 23:17:20 -06002063 } while (true);
2064}
2065
2066// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002067// : (type) unary_expression
2068// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002069// | - unary_expression
2070// | ! unary_expression
2071// | ~ unary_expression
2072// | ++ unary_expression
2073// | -- unary_expression
2074// | postfix_expression
2075//
2076bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2077{
John Kessenich1cc1a282016-06-03 16:55:49 -06002078 // (type) unary_expression
2079 // Have to look two steps ahead, because this could be, e.g., a
2080 // postfix_expression instead, since that also starts with at "(".
2081 if (acceptTokenClass(EHTokLeftParen)) {
2082 TType castType;
2083 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002084 if (acceptTokenClass(EHTokRightParen)) {
2085 // We've matched "(type)" now, get the expression to cast
2086 TSourceLoc loc = token.loc;
2087 if (! acceptUnaryExpression(node))
2088 return false;
2089
2090 // Hook it up like a constructor
2091 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2092 if (constructorFunction == nullptr) {
2093 expected("type that can be constructed");
2094 return false;
2095 }
2096 TIntermTyped* arguments = nullptr;
2097 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2098 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2099
2100 return true;
2101 } else {
2102 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2103 // the '(int' part. We must back up twice.
2104 recedeToken();
2105 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002106 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002107 } else {
2108 // This isn't a type cast, but it still started "(", so if it is a
2109 // unary expression, it can only be a postfix_expression, so try that.
2110 // Back it up first.
2111 recedeToken();
2112 return acceptPostfixExpression(node);
2113 }
2114 }
2115
2116 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002117 TOperator unaryOp = HlslOpMap::preUnary(peek());
2118
John Kessenich1cc1a282016-06-03 16:55:49 -06002119 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002120 if (unaryOp == EOpNull)
2121 return acceptPostfixExpression(node);
2122
2123 // op unary_expression
2124 TSourceLoc loc = token.loc;
2125 advanceToken();
2126 if (! acceptUnaryExpression(node))
2127 return false;
2128
2129 // + is a no-op
2130 if (unaryOp == EOpAdd)
2131 return true;
2132
2133 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002134
2135 // These unary ops require lvalues
2136 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2137 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002138
2139 return node != nullptr;
2140}
2141
2142// postfix_expression
2143// : LEFT_PAREN expression RIGHT_PAREN
2144// | literal
2145// | constructor
2146// | identifier
2147// | function_call
2148// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2149// | postfix_expression DOT IDENTIFIER
2150// | postfix_expression INC_OP
2151// | postfix_expression DEC_OP
2152//
2153bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2154{
2155 // Not implemented as self-recursive:
2156 // The logical "right recursion" is done with an loop at the end
2157
2158 // idToken will pick up either a variable or a function name in a function call
2159 HlslToken idToken;
2160
John Kessenich21472ae2016-06-04 11:46:33 -06002161 // Find something before the postfix operations, as they can't operate
2162 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002163 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002164 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002165 if (! acceptExpression(node)) {
2166 expected("expression");
2167 return false;
2168 }
2169 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002170 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002171 return false;
2172 }
John Kessenich34fb0362016-05-03 23:17:20 -06002173 } else if (acceptLiteral(node)) {
2174 // literal (nothing else to do yet), go on to the
2175 } else if (acceptConstructor(node)) {
2176 // constructor (nothing else to do yet)
2177 } else if (acceptIdentifier(idToken)) {
2178 // identifier or function_call name
2179 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002180 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002181 } else if (acceptFunctionCall(idToken, node)) {
2182 // function_call (nothing else to do yet)
2183 } else {
2184 expected("function call arguments");
2185 return false;
2186 }
John Kessenich21472ae2016-06-04 11:46:33 -06002187 } else {
2188 // nothing found, can't post operate
2189 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002190 }
2191
John Kessenich21472ae2016-06-04 11:46:33 -06002192 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002193 do {
2194 TSourceLoc loc = token.loc;
2195 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002196
John Kessenich34fb0362016-05-03 23:17:20 -06002197 // Consume only a valid post-unary operator, otherwise we are done.
2198 switch (postOp) {
2199 case EOpIndexDirectStruct:
2200 case EOpIndexIndirect:
2201 case EOpPostIncrement:
2202 case EOpPostDecrement:
2203 advanceToken();
2204 break;
2205 default:
2206 return true;
2207 }
John Kessenich87142c72016-03-12 20:24:24 -07002208
John Kessenich34fb0362016-05-03 23:17:20 -06002209 // We have a valid post-unary operator, process it.
2210 switch (postOp) {
2211 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002212 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002213 // DOT IDENTIFIER
2214 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002215 HlslToken field;
2216 if (! acceptIdentifier(field)) {
2217 expected("swizzle or member");
2218 return false;
2219 }
LoopDawg4886f692016-06-29 10:58:58 -06002220
2221 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002222 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002223
2224 // In the event of a method node, we look for an open paren and accept the function call.
2225 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
2226 if (! acceptFunctionCall(field, node, base)) {
2227 expected("function parameters");
2228 return false;
2229 }
2230 }
2231
John Kessenich34fb0362016-05-03 23:17:20 -06002232 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002233 }
John Kessenich34fb0362016-05-03 23:17:20 -06002234 case EOpIndexIndirect:
2235 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002236 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002237 TIntermTyped* indexNode = nullptr;
2238 if (! acceptExpression(indexNode) ||
2239 ! peekTokenClass(EHTokRightBracket)) {
2240 expected("expression followed by ']'");
2241 return false;
2242 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002243 advanceToken();
2244 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2245 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002246 }
2247 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002248 // INC_OP
2249 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002250 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002251 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002252 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002253 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002254 break;
2255 default:
2256 assert(0);
2257 break;
2258 }
2259 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002260}
2261
John Kessenichd016be12016-03-13 11:24:20 -06002262// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002263// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002264//
2265bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2266{
2267 // type
2268 TType type;
2269 if (acceptType(type)) {
2270 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2271 if (constructorFunction == nullptr)
2272 return false;
2273
2274 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002275 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002276 if (! acceptArguments(constructorFunction, arguments)) {
2277 expected("constructor arguments");
2278 return false;
2279 }
2280
2281 // hook it up
2282 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2283
2284 return true;
2285 }
2286
2287 return false;
2288}
2289
John Kessenich34fb0362016-05-03 23:17:20 -06002290// The function_call identifier was already recognized, and passed in as idToken.
2291//
2292// function_call
2293// : [idToken] arguments
2294//
LoopDawg4886f692016-06-29 10:58:58 -06002295bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002296{
John Kessenich4678ca92016-05-13 09:33:42 -06002297 // arguments
2298 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2299 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002300
2301 // methods have an implicit first argument of the calling object.
2302 if (base != nullptr)
2303 parseContext.handleFunctionArgument(function, arguments, base);
2304
John Kessenich4678ca92016-05-13 09:33:42 -06002305 if (! acceptArguments(function, arguments))
2306 return false;
2307
2308 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2309
2310 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002311}
2312
John Kessenich87142c72016-03-12 20:24:24 -07002313// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002314// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002315//
John Kessenichd016be12016-03-13 11:24:20 -06002316// The arguments are pushed onto the 'function' argument list and
2317// onto the 'arguments' aggregate.
2318//
John Kessenich4678ca92016-05-13 09:33:42 -06002319bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002320{
John Kessenich078d7f22016-03-14 10:02:11 -06002321 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002322 if (! acceptTokenClass(EHTokLeftParen))
2323 return false;
2324
2325 do {
John Kessenichd016be12016-03-13 11:24:20 -06002326 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002327 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002328 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002329 break;
John Kessenichd016be12016-03-13 11:24:20 -06002330
2331 // hook it up
2332 parseContext.handleFunctionArgument(function, arguments, arg);
2333
John Kessenich078d7f22016-03-14 10:02:11 -06002334 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002335 if (! acceptTokenClass(EHTokComma))
2336 break;
2337 } while (true);
2338
John Kessenich078d7f22016-03-14 10:02:11 -06002339 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002340 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002341 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002342 return false;
2343 }
2344
2345 return true;
2346}
2347
2348bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2349{
2350 switch (token.tokenClass) {
2351 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002352 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002353 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002354 case EHTokUintConstant:
2355 node = intermediate.addConstantUnion(token.u, token.loc, true);
2356 break;
John Kessenich87142c72016-03-12 20:24:24 -07002357 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002358 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002359 break;
2360 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002361 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002362 break;
2363 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002364 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002365 break;
John Kessenich86f71382016-09-19 20:23:18 -06002366 case EHTokStringConstant:
2367 node = nullptr;
2368 break;
John Kessenich87142c72016-03-12 20:24:24 -07002369
2370 default:
2371 return false;
2372 }
2373
2374 advanceToken();
2375
2376 return true;
2377}
2378
John Kessenich5f934b02016-03-13 17:58:25 -06002379// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002380// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002381//
John Kessenich21472ae2016-06-04 11:46:33 -06002382bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002383{
John Kessenich21472ae2016-06-04 11:46:33 -06002384 TIntermAggregate* compoundStatement = nullptr;
2385
John Kessenich34fb0362016-05-03 23:17:20 -06002386 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002387 if (! acceptTokenClass(EHTokLeftBrace))
2388 return false;
2389
2390 // statement statement ...
2391 TIntermNode* statement = nullptr;
2392 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002393 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2394 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2395 branch->getFlowOp() == EOpDefault)) {
2396 // hook up individual subsequences within a switch statement
2397 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2398 compoundStatement = nullptr;
2399 } else {
2400 // hook it up to the growing compound statement
2401 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2402 }
John Kessenich5f934b02016-03-13 17:58:25 -06002403 }
John Kessenich34fb0362016-05-03 23:17:20 -06002404 if (compoundStatement)
2405 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002406
John Kessenich21472ae2016-06-04 11:46:33 -06002407 retStatement = compoundStatement;
2408
John Kessenich34fb0362016-05-03 23:17:20 -06002409 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002410 return acceptTokenClass(EHTokRightBrace);
2411}
2412
John Kessenich0d2b6de2016-06-05 11:23:11 -06002413bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2414{
2415 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002416 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002417 parseContext.popScope();
2418
2419 return result;
2420}
2421
John Kessenich077e0522016-06-09 02:02:17 -06002422bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002423{
John Kessenich077e0522016-06-09 02:02:17 -06002424 parseContext.pushScope();
2425 bool result = acceptCompoundStatement(statement);
2426 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002427
2428 return result;
2429}
2430
John Kessenich5f934b02016-03-13 17:58:25 -06002431// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002432// : attributes attributed_statement
2433//
2434// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002435// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002436// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002437// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002438// | declaration_statement
2439// | selection_statement
2440// | switch_statement
2441// | case_label
2442// | iteration_statement
2443// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002444//
2445bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2446{
John Kessenich21472ae2016-06-04 11:46:33 -06002447 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002448
John Kessenich21472ae2016-06-04 11:46:33 -06002449 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002450 TAttributeMap attributes;
2451 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002452
John Kessenich21472ae2016-06-04 11:46:33 -06002453 // attributed_statement
2454 switch (peek()) {
2455 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002456 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002457
John Kessenich21472ae2016-06-04 11:46:33 -06002458 case EHTokIf:
2459 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002460
John Kessenich21472ae2016-06-04 11:46:33 -06002461 case EHTokSwitch:
2462 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002463
John Kessenich21472ae2016-06-04 11:46:33 -06002464 case EHTokFor:
2465 case EHTokDo:
2466 case EHTokWhile:
2467 return acceptIterationStatement(statement);
2468
2469 case EHTokContinue:
2470 case EHTokBreak:
2471 case EHTokDiscard:
2472 case EHTokReturn:
2473 return acceptJumpStatement(statement);
2474
2475 case EHTokCase:
2476 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002477 case EHTokDefault:
2478 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002479
2480 case EHTokSemicolon:
2481 return acceptTokenClass(EHTokSemicolon);
2482
2483 case EHTokRightBrace:
2484 // Performance: not strictly necessary, but stops a bunch of hunting early,
2485 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002486 return false;
2487
John Kessenich21472ae2016-06-04 11:46:33 -06002488 default:
2489 {
2490 // declaration
2491 if (acceptDeclaration(statement))
2492 return true;
2493
2494 // expression
2495 TIntermTyped* node;
2496 if (acceptExpression(node))
2497 statement = node;
2498 else
2499 return false;
2500
2501 // SEMICOLON (following an expression)
2502 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002503 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002504 return false;
2505 }
2506 }
2507 }
2508
John Kessenich5f934b02016-03-13 17:58:25 -06002509 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002510}
2511
John Kessenich21472ae2016-06-04 11:46:33 -06002512// attributes
2513// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2514//
2515// attribute:
2516// : UNROLL
2517// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2518// | FASTOPT
2519// | ALLOW_UAV_CONDITION
2520// | BRANCH
2521// | FLATTEN
2522// | FORCECASE
2523// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002524// | DOMAIN
2525// | EARLYDEPTHSTENCIL
2526// | INSTANCE
2527// | MAXTESSFACTOR
2528// | OUTPUTCONTROLPOINTS
2529// | OUTPUTTOPOLOGY
2530// | PARTITIONING
2531// | PATCHCONSTANTFUNC
2532// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002533//
steve-lunarg1868b142016-10-20 13:07:10 -06002534void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002535{
steve-lunarg1868b142016-10-20 13:07:10 -06002536 // For now, accept the [ XXX(X) ] syntax, but drop all but
2537 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002538 // TODO: subset to correct set? Pass on?
2539 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002540 HlslToken idToken;
2541
John Kessenich0d2b6de2016-06-05 11:23:11 -06002542 // LEFT_BRACKET?
2543 if (! acceptTokenClass(EHTokLeftBracket))
2544 return;
2545
2546 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002547 if (acceptIdentifier(idToken)) {
2548 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002549 } else if (! peekTokenClass(EHTokRightBracket)) {
2550 expected("identifier");
2551 advanceToken();
2552 }
2553
steve-lunarga22f7db2016-11-11 08:17:44 -07002554 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002555
2556 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002557 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002558 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002559
John Kessenich0d2b6de2016-06-05 11:23:11 -06002560 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002561 bool expectingExpression = false;
steve-lunarg1868b142016-10-20 13:07:10 -06002562
steve-lunarga22f7db2016-11-11 08:17:44 -07002563 while (acceptAssignmentExpression(node)) {
2564 expectingExpression = false;
2565 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002566 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002567 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002568 }
2569
steve-lunarga22f7db2016-11-11 08:17:44 -07002570 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002571 if (! acceptTokenClass(EHTokRightParen))
2572 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002573
2574 // Error for partial or missing expression
2575 if (expectingExpression || expressions->getSequence().empty())
2576 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002577 }
2578
2579 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002580 if (!acceptTokenClass(EHTokRightBracket)) {
2581 expected("]");
2582 return;
2583 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002584
steve-lunarg1868b142016-10-20 13:07:10 -06002585 // Add any values we found into the attribute map. This accepts
2586 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002587 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002588 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002589}
2590
John Kessenich0d2b6de2016-06-05 11:23:11 -06002591// selection_statement
2592// : IF LEFT_PAREN expression RIGHT_PAREN statement
2593// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2594//
John Kessenich21472ae2016-06-04 11:46:33 -06002595bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2596{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002597 TSourceLoc loc = token.loc;
2598
2599 // IF
2600 if (! acceptTokenClass(EHTokIf))
2601 return false;
2602
2603 // so that something declared in the condition is scoped to the lifetimes
2604 // of the then-else statements
2605 parseContext.pushScope();
2606
2607 // LEFT_PAREN expression RIGHT_PAREN
2608 TIntermTyped* condition;
2609 if (! acceptParenExpression(condition))
2610 return false;
2611
2612 // create the child statements
2613 TIntermNodePair thenElse = { nullptr, nullptr };
2614
2615 // then statement
2616 if (! acceptScopedStatement(thenElse.node1)) {
2617 expected("then statement");
2618 return false;
2619 }
2620
2621 // ELSE
2622 if (acceptTokenClass(EHTokElse)) {
2623 // else statement
2624 if (! acceptScopedStatement(thenElse.node2)) {
2625 expected("else statement");
2626 return false;
2627 }
2628 }
2629
2630 // Put the pieces together
2631 statement = intermediate.addSelection(condition, thenElse, loc);
2632 parseContext.popScope();
2633
2634 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002635}
2636
John Kessenichd02dc5d2016-07-01 00:04:11 -06002637// switch_statement
2638// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2639//
John Kessenich21472ae2016-06-04 11:46:33 -06002640bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2641{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002642 // SWITCH
2643 TSourceLoc loc = token.loc;
2644 if (! acceptTokenClass(EHTokSwitch))
2645 return false;
2646
2647 // LEFT_PAREN expression RIGHT_PAREN
2648 parseContext.pushScope();
2649 TIntermTyped* switchExpression;
2650 if (! acceptParenExpression(switchExpression)) {
2651 parseContext.popScope();
2652 return false;
2653 }
2654
2655 // compound_statement
2656 parseContext.pushSwitchSequence(new TIntermSequence);
2657 bool statementOkay = acceptCompoundStatement(statement);
2658 if (statementOkay)
2659 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2660
2661 parseContext.popSwitchSequence();
2662 parseContext.popScope();
2663
2664 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002665}
2666
John Kessenich119f8f62016-06-05 15:44:07 -06002667// iteration_statement
2668// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2669// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2670// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2671//
2672// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002673bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2674{
John Kessenich119f8f62016-06-05 15:44:07 -06002675 TSourceLoc loc = token.loc;
2676 TIntermTyped* condition = nullptr;
2677
2678 EHlslTokenClass loop = peek();
2679 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2680
2681 // WHILE or DO or FOR
2682 advanceToken();
2683
2684 switch (loop) {
2685 case EHTokWhile:
2686 // so that something declared in the condition is scoped to the lifetime
2687 // of the while sub-statement
2688 parseContext.pushScope();
2689 parseContext.nestLooping();
2690
2691 // LEFT_PAREN condition RIGHT_PAREN
2692 if (! acceptParenExpression(condition))
2693 return false;
2694
2695 // statement
2696 if (! acceptScopedStatement(statement)) {
2697 expected("while sub-statement");
2698 return false;
2699 }
2700
2701 parseContext.unnestLooping();
2702 parseContext.popScope();
2703
2704 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2705
2706 return true;
2707
2708 case EHTokDo:
2709 parseContext.nestLooping();
2710
2711 if (! acceptTokenClass(EHTokLeftBrace))
2712 expected("{");
2713
2714 // statement
2715 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2716 expected("do sub-statement");
2717 return false;
2718 }
2719
2720 if (! acceptTokenClass(EHTokRightBrace))
2721 expected("}");
2722
2723 // WHILE
2724 if (! acceptTokenClass(EHTokWhile)) {
2725 expected("while");
2726 return false;
2727 }
2728
2729 // LEFT_PAREN condition RIGHT_PAREN
2730 TIntermTyped* condition;
2731 if (! acceptParenExpression(condition))
2732 return false;
2733
2734 if (! acceptTokenClass(EHTokSemicolon))
2735 expected(";");
2736
2737 parseContext.unnestLooping();
2738
2739 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2740
2741 return true;
2742
2743 case EHTokFor:
2744 {
2745 // LEFT_PAREN
2746 if (! acceptTokenClass(EHTokLeftParen))
2747 expected("(");
2748
2749 // so that something declared in the condition is scoped to the lifetime
2750 // of the for sub-statement
2751 parseContext.pushScope();
2752
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002753 // initializer
2754 TIntermNode* initNode = nullptr;
2755 if (! acceptControlDeclaration(initNode)) {
2756 TIntermTyped* initExpr = nullptr;
2757 acceptExpression(initExpr);
2758 initNode = initExpr;
2759 }
2760 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002761 if (! acceptTokenClass(EHTokSemicolon))
2762 expected(";");
2763
2764 parseContext.nestLooping();
2765
2766 // condition SEMI_COLON
2767 acceptExpression(condition);
2768 if (! acceptTokenClass(EHTokSemicolon))
2769 expected(";");
2770
2771 // iterator SEMI_COLON
2772 TIntermTyped* iterator = nullptr;
2773 acceptExpression(iterator);
2774 if (! acceptTokenClass(EHTokRightParen))
2775 expected(")");
2776
2777 // statement
2778 if (! acceptScopedStatement(statement)) {
2779 expected("for sub-statement");
2780 return false;
2781 }
2782
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002783 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002784
2785 parseContext.popScope();
2786 parseContext.unnestLooping();
2787
2788 return true;
2789 }
2790
2791 default:
2792 return false;
2793 }
John Kessenich21472ae2016-06-04 11:46:33 -06002794}
2795
2796// jump_statement
2797// : CONTINUE SEMICOLON
2798// | BREAK SEMICOLON
2799// | DISCARD SEMICOLON
2800// | RETURN SEMICOLON
2801// | RETURN expression SEMICOLON
2802//
2803bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2804{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002805 EHlslTokenClass jump = peek();
2806 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002807 case EHTokContinue:
2808 case EHTokBreak:
2809 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002810 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002811 advanceToken();
2812 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002813 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002814 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002815 return false;
2816 }
John Kessenich21472ae2016-06-04 11:46:33 -06002817
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002818 switch (jump) {
2819 case EHTokContinue:
2820 statement = intermediate.addBranch(EOpContinue, token.loc);
2821 break;
2822 case EHTokBreak:
2823 statement = intermediate.addBranch(EOpBreak, token.loc);
2824 break;
2825 case EHTokDiscard:
2826 statement = intermediate.addBranch(EOpKill, token.loc);
2827 break;
2828
2829 case EHTokReturn:
2830 {
2831 // expression
2832 TIntermTyped* node;
2833 if (acceptExpression(node)) {
2834 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002835 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002836 } else
2837 statement = intermediate.addBranch(EOpReturn, token.loc);
2838 break;
2839 }
2840
2841 default:
2842 assert(0);
2843 return false;
2844 }
2845
2846 // SEMICOLON
2847 if (! acceptTokenClass(EHTokSemicolon))
2848 expected(";");
2849
2850 return true;
2851}
John Kessenich21472ae2016-06-04 11:46:33 -06002852
John Kessenichd02dc5d2016-07-01 00:04:11 -06002853// case_label
2854// : CASE expression COLON
2855//
John Kessenich21472ae2016-06-04 11:46:33 -06002856bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2857{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002858 TSourceLoc loc = token.loc;
2859 if (! acceptTokenClass(EHTokCase))
2860 return false;
2861
2862 TIntermTyped* expression;
2863 if (! acceptExpression(expression)) {
2864 expected("case expression");
2865 return false;
2866 }
2867
2868 if (! acceptTokenClass(EHTokColon)) {
2869 expected(":");
2870 return false;
2871 }
2872
2873 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2874
2875 return true;
2876}
2877
2878// default_label
2879// : DEFAULT COLON
2880//
2881bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2882{
2883 TSourceLoc loc = token.loc;
2884 if (! acceptTokenClass(EHTokDefault))
2885 return false;
2886
2887 if (! acceptTokenClass(EHTokColon)) {
2888 expected(":");
2889 return false;
2890 }
2891
2892 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2893
2894 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002895}
2896
John Kessenich19b92ff2016-06-19 11:50:34 -06002897// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06002898// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
2899// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002900//
2901void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2902{
2903 arraySizes = nullptr;
2904
steve-lunarg7b211a32016-10-13 12:26:18 -06002905 // Early-out if there aren't any array dimensions
2906 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06002907 return;
2908
steve-lunarg7b211a32016-10-13 12:26:18 -06002909 // 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 -06002910 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06002911
2912 // Collect each array dimension.
2913 while (acceptTokenClass(EHTokLeftBracket)) {
2914 TSourceLoc loc = token.loc;
2915 TIntermTyped* sizeExpr = nullptr;
2916
2917 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
2918 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
2919
2920 if (! acceptTokenClass(EHTokRightBracket)) {
2921 expected("]");
2922 return;
2923 }
2924
2925 if (hasArraySize) {
2926 TArraySize arraySize;
2927 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2928 arraySizes->addInnerSize(arraySize);
2929 } else {
2930 arraySizes->addInnerSize(0); // sized by initializers.
2931 }
steve-lunarg265c0612016-09-27 10:57:35 -06002932 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002933}
2934
John Kessenich630dd7d2016-06-12 23:52:12 -06002935// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002936// : COLON semantic // optional
2937// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2938// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002939// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002940// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002941//
John Kessenich7735b942016-09-05 12:40:06 -06002942void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002943{
John Kessenich630dd7d2016-06-12 23:52:12 -06002944 do {
2945 // COLON
2946 if (acceptTokenClass(EHTokColon)) {
2947 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002948 if (peekTokenClass(EHTokLayout))
2949 acceptLayoutQualifierList(qualifier);
2950 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002951 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002952 if (! acceptTokenClass(EHTokLeftParen)) {
2953 expected("(");
2954 return;
2955 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002956 HlslToken locationToken;
2957 if (! acceptIdentifier(locationToken)) {
2958 expected("c[subcomponent][.component]");
2959 return;
2960 }
2961 HlslToken componentToken;
2962 if (acceptTokenClass(EHTokDot)) {
2963 if (! acceptIdentifier(componentToken)) {
2964 expected("component");
2965 return;
2966 }
2967 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002968 if (! acceptTokenClass(EHTokRightParen)) {
2969 expected(")");
2970 break;
2971 }
John Kessenich7735b942016-09-05 12:40:06 -06002972 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002973 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002974 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002975 return;
2976 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002977 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2978 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002979 if (! acceptTokenClass(EHTokLeftParen)) {
2980 expected("(");
2981 return;
2982 }
John Kessenichb38f0712016-07-30 10:29:54 -06002983 HlslToken registerDesc; // for Type#
2984 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002985 if (! acceptIdentifier(registerDesc)) {
2986 expected("register number description");
2987 return;
2988 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002989 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2990 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002991 // Then we didn't really see the registerDesc yet, it was
2992 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002993 profile = registerDesc;
2994 if (! acceptIdentifier(registerDesc)) {
2995 expected("register number description");
2996 return;
2997 }
2998 }
John Kessenichb38f0712016-07-30 10:29:54 -06002999 int subComponent = 0;
3000 if (acceptTokenClass(EHTokLeftBracket)) {
3001 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3002 if (! peekTokenClass(EHTokIntConstant)) {
3003 expected("literal integer");
3004 return;
3005 }
3006 subComponent = token.i;
3007 advanceToken();
3008 if (! acceptTokenClass(EHTokRightBracket)) {
3009 expected("]");
3010 break;
3011 }
3012 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003013 // (COMMA SPACEN)opt
3014 HlslToken spaceDesc;
3015 if (acceptTokenClass(EHTokComma)) {
3016 if (! acceptIdentifier(spaceDesc)) {
3017 expected ("space identifier");
3018 return;
3019 }
3020 }
3021 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003022 if (! acceptTokenClass(EHTokRightParen)) {
3023 expected(")");
3024 break;
3025 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003026 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003027 } else {
3028 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003029 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003030 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003031 } else if (peekTokenClass(EHTokLeftAngle))
3032 acceptAnnotations(qualifier);
3033 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003034 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003035
John Kessenich630dd7d2016-06-12 23:52:12 -06003036 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003037}
3038
John Kesseniche01a9bc2016-03-12 20:11:22 -07003039} // end namespace glslang