blob: b874aa8c9cb433008747a115cb14b8111e7660b7 [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
steve-lunarg75fd2232016-11-16 13:22:11 -070088 // Even though "sample" is a keyword (for interpolation modifiers), it IS still accepted as
89 // an identifier. This appears to be a solitary exception: other interp modifier keywords such
90 // as "linear" or "centroid" NOT valid identifiers. This code special cases "sample",
91 // so e.g, "int sample;" is accepted.
92 if (peekTokenClass(EHTokSample)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -070093 token.string = NewPoolTString("sample");
94 token.tokenClass = EHTokIdentifier;
95 token.symbol = nullptr;
96
97 idToken = token;
steve-lunarg75fd2232016-11-16 13:22:11 -070098 advanceToken();
99 return true;
100 }
101
John Kessenichaecd4972016-03-14 10:46:34 -0600102 return false;
103}
104
John Kesseniche01a9bc2016-03-12 20:11:22 -0700105// compilationUnit
106// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600107// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700108//
109bool HlslGrammar::acceptCompilationUnit()
110{
John Kessenichd016be12016-03-13 11:24:20 -0600111 TIntermNode* unitNode = nullptr;
112
John Kessenich9c86c6a2016-05-03 22:49:24 -0600113 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600114 // HLSL allows semicolons between global declarations, e.g, between functions.
115 if (acceptTokenClass(EHTokSemicolon))
116 continue;
117
John Kessenichd016be12016-03-13 11:24:20 -0600118 // externalDeclaration
119 TIntermNode* declarationNode;
120 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700121 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600122
123 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600124 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700125 }
126
John Kessenichd016be12016-03-13 11:24:20 -0600127 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600128 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600129
John Kesseniche01a9bc2016-03-12 20:11:22 -0700130 return true;
131}
132
LoopDawg4886f692016-06-29 10:58:58 -0600133// sampler_state
134// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
135//
136// sampler_state_assignment
137// : sampler_state_identifier EQUAL value SEMICOLON
138//
139// sampler_state_identifier
140// : ADDRESSU
141// | ADDRESSV
142// | ADDRESSW
143// | BORDERCOLOR
144// | FILTER
145// | MAXANISOTROPY
146// | MAXLOD
147// | MINLOD
148// | MIPLODBIAS
149//
150bool HlslGrammar::acceptSamplerState()
151{
152 // TODO: this should be genericized to accept a list of valid tokens and
153 // return token/value pairs. Presently it is specific to texture values.
154
155 if (! acceptTokenClass(EHTokLeftBrace))
156 return true;
157
158 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
159
160 do {
161 // read state name
162 HlslToken state;
163 if (! acceptIdentifier(state))
164 break; // end of list
165
166 // FXC accepts any case
167 TString stateName = *state.string;
168 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
169
170 if (! acceptTokenClass(EHTokAssign)) {
171 expected("assign");
172 return false;
173 }
174
175 if (stateName == "minlod" || stateName == "maxlod") {
176 if (! peekTokenClass(EHTokIntConstant)) {
177 expected("integer");
178 return false;
179 }
180
181 TIntermTyped* lod = nullptr;
182 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
183 return false;
184 } else if (stateName == "maxanisotropy") {
185 if (! peekTokenClass(EHTokIntConstant)) {
186 expected("integer");
187 return false;
188 }
189
190 TIntermTyped* maxAnisotropy = nullptr;
191 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
192 return false;
193 } else if (stateName == "filter") {
194 HlslToken filterMode;
195 if (! acceptIdentifier(filterMode)) {
196 expected("filter mode");
197 return false;
198 }
199 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
200 HlslToken addrMode;
201 if (! acceptIdentifier(addrMode)) {
202 expected("texture address mode");
203 return false;
204 }
205 } else if (stateName == "miplodbias") {
206 TIntermTyped* lodBias = nullptr;
207 if (! acceptLiteral(lodBias)) {
208 expected("lod bias");
209 return false;
210 }
211 } else if (stateName == "bordercolor") {
212 return false;
213 } else {
214 expected("texture state");
215 return false;
216 }
217
218 // SEMICOLON
219 if (! acceptTokenClass(EHTokSemicolon)) {
220 expected("semicolon");
221 return false;
222 }
223 } while (true);
224
225 if (! acceptTokenClass(EHTokRightBrace))
226 return false;
227
228 return true;
229}
230
231// sampler_declaration_dx9
232// : SAMPLER identifier EQUAL sampler_type sampler_state
233//
John Kesseniche4821e42016-07-16 10:19:43 -0600234bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600235{
236 if (! acceptTokenClass(EHTokSampler))
237 return false;
238
239 // TODO: remove this when DX9 style declarations are implemented.
240 unimplemented("Direct3D 9 sampler declaration");
241
242 // read sampler name
243 HlslToken name;
244 if (! acceptIdentifier(name)) {
245 expected("sampler name");
246 return false;
247 }
248
249 if (! acceptTokenClass(EHTokAssign)) {
250 expected("=");
251 return false;
252 }
253
254 return false;
255}
256
257
John Kesseniche01a9bc2016-03-12 20:11:22 -0700258// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600259// : sampler_declaration_dx9 post_decls SEMICOLON
260// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600261// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600262// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600263// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700264//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600265// declarator_list
266// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600267//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600268// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600269// : identifier array_specifier post_decls
270// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600271// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600272//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600273// Parsing has to go pretty far in to know whether it's a variable, prototype, or
274// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600275// as above. (The 'identifier' in the first item in init_declarator list is the
276// same as 'identifier' for function declarations.)
277//
278// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600279// or a function body.
280//
281bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700282{
John Kessenichd016be12016-03-13 11:24:20 -0600283 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600284 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600285
steve-lunarg1868b142016-10-20 13:07:10 -0600286 // attributes
287 TAttributeMap attributes;
288 acceptAttributes(attributes);
289
John Kessenich5e69ec62016-07-05 00:02:40 -0600290 // typedef
291 bool typedefDecl = acceptTokenClass(EHTokTypedef);
292
John Kesseniche82061d2016-09-27 14:38:57 -0600293 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600294
295 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600296 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
297 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
298 // HLSL shaders, this will have to be a master level switch
299 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
300 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400301
John Kesseniche82061d2016-09-27 14:38:57 -0600302 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400303 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600304
305 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600306 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700307 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600308
John Kessenich87142c72016-03-12 20:24:24 -0700309 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600310 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600311 while (acceptIdentifier(idToken)) {
steve-lunargf1e0c872016-10-31 15:13:43 -0600312 TString* fnName = idToken.string;
313
314 // Potentially rename shader entry point function. No-op most of the time.
315 parseContext.renameShaderFunction(fnName);
316
John Kessenich5f934b02016-03-13 17:58:25 -0600317 // function_parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600318 TFunction& function = *new TFunction(fnName, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600319 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600320 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600321 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600322
John Kessenichd5ed0b62016-07-04 17:32:45 -0600323 // compound_statement (function body definition) or just a prototype?
324 if (peekTokenClass(EHTokLeftBrace)) {
325 if (list)
326 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600327 if (typedefDecl)
328 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
steve-lunarg1868b142016-10-20 13:07:10 -0600329 return acceptFunctionDefinition(function, node, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600330 } else {
331 if (typedefDecl)
332 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600333 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600334 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600335 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600336 // A variable declaration. Fix the storage qualifier if it's a global.
337 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
338 declaredType.getQualifier().storage = EvqUniform;
339
John Kesseniche82061d2016-09-27 14:38:57 -0600340 // We can handle multiple variables per type declaration, so
341 // the number of types can expand when arrayness is different.
342 TType variableType;
343 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600344
John Kesseniche82061d2016-09-27 14:38:57 -0600345 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600346 TArraySizes* arraySizes = nullptr;
347 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600348
John Kesseniche82061d2016-09-27 14:38:57 -0600349 // Fix arrayness in the variableType
350 if (declaredType.isImplicitlySizedArray()) {
351 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
352 // of different sizes, for this case sharing the shallow copy of arrayness
353 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
354 variableType.newArraySizes(declaredType.getArraySizes());
355 }
356 if (arraySizes || variableType.isArray()) {
357 // In the most general case, arrayness is potentially coming both from the
358 // declared type and from the variable: "int[] a[];" or just one or the other.
359 // Merge it all to the variableType, so all arrayness is part of the variableType.
360 parseContext.arrayDimMerge(variableType, arraySizes);
361 }
362
LoopDawg4886f692016-06-29 10:58:58 -0600363 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600364 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600365 if (! acceptSamplerState())
366 return false;
367 }
368
John Kessenichd5ed0b62016-07-04 17:32:45 -0600369 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600370 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600371
372 // EQUAL assignment_expression
373 TIntermTyped* expressionNode = nullptr;
374 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600375 if (typedefDecl)
376 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600377 if (! acceptAssignmentExpression(expressionNode)) {
378 expected("initializer");
379 return false;
380 }
381 }
382
John Kessenich6dbc0a72016-09-27 19:13:05 -0600383 // Hand off the actual declaration
384
385 // TODO: things scoped within an annotation need their own name space;
386 // TODO: strings are not yet handled.
387 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
388 if (typedefDecl)
389 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
390 else if (variableType.getBasicType() == EbtBlock)
391 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
392 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700393 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600394 // this isn't really an individual variable, but a member of the $Global buffer
395 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
396 } else {
397 // Declare the variable and add any initializer code to the AST.
398 // The top-level node is always made into an aggregate, as that's
399 // historically how the AST has been.
400 node = intermediate.growAggregate(node,
401 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
402 expressionNode),
403 idToken.loc);
404 }
405 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600406 }
John Kessenich5f934b02016-03-13 17:58:25 -0600407 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600408
409 if (acceptTokenClass(EHTokComma)) {
410 list = true;
411 continue;
412 }
413 };
414
415 // The top-level node is a sequence.
416 if (node != nullptr)
417 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700418
John Kessenich078d7f22016-03-14 10:02:11 -0600419 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600420 if (! acceptTokenClass(EHTokSemicolon)) {
421 expected(";");
422 return false;
423 }
424
John Kesseniche01a9bc2016-03-12 20:11:22 -0700425 return true;
426}
427
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600428// control_declaration
429// : fully_specified_type identifier EQUAL expression
430//
431bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
432{
433 node = nullptr;
434
435 // fully_specified_type
436 TType type;
437 if (! acceptFullySpecifiedType(type))
438 return false;
439
440 // identifier
441 HlslToken idToken;
442 if (! acceptIdentifier(idToken)) {
443 expected("identifier");
444 return false;
445 }
446
447 // EQUAL
448 TIntermTyped* expressionNode = nullptr;
449 if (! acceptTokenClass(EHTokAssign)) {
450 expected("=");
451 return false;
452 }
453
454 // expression
455 if (! acceptExpression(expressionNode)) {
456 expected("initializer");
457 return false;
458 }
459
John Kesseniche82061d2016-09-27 14:38:57 -0600460 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600461
462 return true;
463}
464
John Kessenich87142c72016-03-12 20:24:24 -0700465// fully_specified_type
466// : type_specifier
467// | type_qualifier type_specifier
468//
469bool HlslGrammar::acceptFullySpecifiedType(TType& type)
470{
471 // type_qualifier
472 TQualifier qualifier;
473 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600474 if (! acceptQualifier(qualifier))
475 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600476 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700477
478 // type_specifier
steve-lunarga64ed3e2016-12-18 17:51:14 -0700479 if (! acceptType(type)) {
480 // If this is not a type, we may have inadvertently gone down a wrong path
481 // py parsing "sample", which can be treated like either an identifier or a
482 // qualifier. Back it out, if we did.
483 if (qualifier.sample)
484 recedeToken();
485
John Kessenich87142c72016-03-12 20:24:24 -0700486 return false;
steve-lunarga64ed3e2016-12-18 17:51:14 -0700487 }
John Kessenich3d157c52016-07-25 16:05:33 -0600488 if (type.getBasicType() == EbtBlock) {
489 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600490 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600491 // further, it can create an anonymous instance of the block
492 if (peekTokenClass(EHTokSemicolon))
493 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600494 } else {
495 // Some qualifiers are set when parsing the type. Merge those with
496 // whatever comes from acceptQualifier.
497 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700498
steve-lunargbb0183f2016-10-04 16:58:14 -0600499 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600500 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700501
502 if (type.getQualifier().storage == EvqVaryingOut)
503 qualifier.storage = type.getQualifier().storage;
504
505 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600506 }
John Kessenich87142c72016-03-12 20:24:24 -0700507
508 return true;
509}
510
John Kessenich630dd7d2016-06-12 23:52:12 -0600511// type_qualifier
512// : qualifier qualifier ...
513//
514// Zero or more of these, so this can't return false.
515//
John Kessenichb9e39122016-08-17 10:22:08 -0600516bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700517{
John Kessenich630dd7d2016-06-12 23:52:12 -0600518 do {
519 switch (peek()) {
520 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600521 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600522 break;
523 case EHTokExtern:
524 // TODO: no meaning in glslang?
525 break;
526 case EHTokShared:
527 // TODO: hint
528 break;
529 case EHTokGroupShared:
530 qualifier.storage = EvqShared;
531 break;
532 case EHTokUniform:
533 qualifier.storage = EvqUniform;
534 break;
535 case EHTokConst:
536 qualifier.storage = EvqConst;
537 break;
538 case EHTokVolatile:
539 qualifier.volatil = true;
540 break;
541 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600542 qualifier.smooth = true;
543 break;
544 case EHTokCentroid:
545 qualifier.centroid = true;
546 break;
547 case EHTokNointerpolation:
548 qualifier.flat = true;
549 break;
550 case EHTokNoperspective:
551 qualifier.nopersp = true;
552 break;
553 case EHTokSample:
554 qualifier.sample = true;
555 break;
556 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600557 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600558 break;
559 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600560 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600561 break;
562 case EHTokPrecise:
563 qualifier.noContraction = true;
564 break;
LoopDawg9249c702016-07-12 20:44:32 -0600565 case EHTokIn:
566 qualifier.storage = EvqIn;
567 break;
568 case EHTokOut:
569 qualifier.storage = EvqOut;
570 break;
571 case EHTokInOut:
572 qualifier.storage = EvqInOut;
573 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600574 case EHTokLayout:
575 if (! acceptLayoutQualifierList(qualifier))
576 return false;
577 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700578
579 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
580 // for output variables.
581 case EHTokPoint:
582 qualifier.storage = EvqIn;
583 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
584 return false;
585 break;
586 case EHTokLine:
587 qualifier.storage = EvqIn;
588 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
589 return false;
590 break;
591 case EHTokTriangle:
592 qualifier.storage = EvqIn;
593 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
594 return false;
595 break;
596 case EHTokLineAdj:
597 qualifier.storage = EvqIn;
598 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
599 return false;
600 break;
601 case EHTokTriangleAdj:
602 qualifier.storage = EvqIn;
603 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
604 return false;
605 break;
606
John Kessenich630dd7d2016-06-12 23:52:12 -0600607 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600608 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600609 }
610 advanceToken();
611 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700612}
613
John Kessenichb9e39122016-08-17 10:22:08 -0600614// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600615// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600616//
617// layout_qualifier
618// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600619// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600620//
621// Zero or more of these, so this can't return false.
622//
623bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
624{
625 if (! acceptTokenClass(EHTokLayout))
626 return false;
627
628 // LEFT_PAREN
629 if (! acceptTokenClass(EHTokLeftParen))
630 return false;
631
632 do {
633 // identifier
634 HlslToken idToken;
635 if (! acceptIdentifier(idToken))
636 break;
637
638 // EQUAL expression
639 if (acceptTokenClass(EHTokAssign)) {
640 TIntermTyped* expr;
641 if (! acceptConditionalExpression(expr)) {
642 expected("expression");
643 return false;
644 }
645 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
646 } else
647 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
648
649 // COMMA
650 if (! acceptTokenClass(EHTokComma))
651 break;
652 } while (true);
653
654 // RIGHT_PAREN
655 if (! acceptTokenClass(EHTokRightParen)) {
656 expected(")");
657 return false;
658 }
659
660 return true;
661}
662
LoopDawg6daaa4f2016-06-23 19:13:48 -0600663// template_type
664// : FLOAT
665// | DOUBLE
666// | INT
667// | DWORD
668// | UINT
669// | BOOL
670//
steve-lunargf49cdf42016-11-17 15:04:20 -0700671bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600672{
673 switch (peek()) {
674 case EHTokFloat:
675 basicType = EbtFloat;
676 break;
677 case EHTokDouble:
678 basicType = EbtDouble;
679 break;
680 case EHTokInt:
681 case EHTokDword:
682 basicType = EbtInt;
683 break;
684 case EHTokUint:
685 basicType = EbtUint;
686 break;
687 case EHTokBool:
688 basicType = EbtBool;
689 break;
690 default:
691 return false;
692 }
693
694 advanceToken();
695
696 return true;
697}
698
699// vector_template_type
700// : VECTOR
701// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
702//
703bool HlslGrammar::acceptVectorTemplateType(TType& type)
704{
705 if (! acceptTokenClass(EHTokVector))
706 return false;
707
708 if (! acceptTokenClass(EHTokLeftAngle)) {
709 // in HLSL, 'vector' alone means float4.
710 new(&type) TType(EbtFloat, EvqTemporary, 4);
711 return true;
712 }
713
714 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700715 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600716 expected("scalar type");
717 return false;
718 }
719
720 // COMMA
721 if (! acceptTokenClass(EHTokComma)) {
722 expected(",");
723 return false;
724 }
725
726 // integer
727 if (! peekTokenClass(EHTokIntConstant)) {
728 expected("literal integer");
729 return false;
730 }
731
732 TIntermTyped* vecSize;
733 if (! acceptLiteral(vecSize))
734 return false;
735
736 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
737
738 new(&type) TType(basicType, EvqTemporary, vecSizeI);
739
740 if (vecSizeI == 1)
741 type.makeVector();
742
743 if (!acceptTokenClass(EHTokRightAngle)) {
744 expected("right angle bracket");
745 return false;
746 }
747
748 return true;
749}
750
751// matrix_template_type
752// : MATRIX
753// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
754//
755bool HlslGrammar::acceptMatrixTemplateType(TType& type)
756{
757 if (! acceptTokenClass(EHTokMatrix))
758 return false;
759
760 if (! acceptTokenClass(EHTokLeftAngle)) {
761 // in HLSL, 'matrix' alone means float4x4.
762 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
763 return true;
764 }
765
766 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700767 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600768 expected("scalar type");
769 return false;
770 }
771
772 // COMMA
773 if (! acceptTokenClass(EHTokComma)) {
774 expected(",");
775 return false;
776 }
777
778 // integer rows
779 if (! peekTokenClass(EHTokIntConstant)) {
780 expected("literal integer");
781 return false;
782 }
783
784 TIntermTyped* rows;
785 if (! acceptLiteral(rows))
786 return false;
787
788 // COMMA
789 if (! acceptTokenClass(EHTokComma)) {
790 expected(",");
791 return false;
792 }
793
794 // integer cols
795 if (! peekTokenClass(EHTokIntConstant)) {
796 expected("literal integer");
797 return false;
798 }
799
800 TIntermTyped* cols;
801 if (! acceptLiteral(cols))
802 return false;
803
804 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600805 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
806 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600807
808 if (!acceptTokenClass(EHTokRightAngle)) {
809 expected("right angle bracket");
810 return false;
811 }
812
813 return true;
814}
815
steve-lunargf49cdf42016-11-17 15:04:20 -0700816// layout_geometry
817// : LINESTREAM
818// | POINTSTREAM
819// | TRIANGLESTREAM
820//
821bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
822{
823 // read geometry type
824 const EHlslTokenClass geometryType = peek();
825
826 switch (geometryType) {
827 case EHTokPointStream: geometry = ElgPoints; break;
828 case EHTokLineStream: geometry = ElgLineStrip; break;
829 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
830 default:
831 return false; // not a layout geometry
832 }
833
834 advanceToken(); // consume the layout keyword
835 return true;
836}
837
838// stream_out_template_type
839// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
840//
841bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
842{
843 geometry = ElgNone;
844
845 if (! acceptOutputPrimitiveGeometry(geometry))
846 return false;
847
848 if (! acceptTokenClass(EHTokLeftAngle))
849 return false;
850
851 if (! acceptType(type)) {
852 expected("stream output type");
853 return false;
854 }
855
856 type.getQualifier().storage = EvqVaryingOut;
857
858 if (! acceptTokenClass(EHTokRightAngle)) {
859 expected("right angle bracket");
860 return false;
861 }
862
863 return true;
864}
865
John Kessenicha1e2d492016-09-20 13:22:58 -0600866// annotations
867// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600868//
John Kessenicha1e2d492016-09-20 13:22:58 -0600869bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600870{
John Kessenicha1e2d492016-09-20 13:22:58 -0600871 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600872 return false;
873
John Kessenicha1e2d492016-09-20 13:22:58 -0600874 // note that we are nesting a name space
875 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600876
877 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
878 do {
879 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
880 while (acceptTokenClass(EHTokSemicolon))
881 ;
882
883 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600884 break;
John Kessenich86f71382016-09-19 20:23:18 -0600885
886 // declaration
887 TIntermNode* node;
888 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600889 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600890 return false;
891 }
892 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600893
894 parseContext.unnestAnnotations();
895 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600896}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600897
LoopDawg4886f692016-06-29 10:58:58 -0600898// sampler_type
899// : SAMPLER
900// | SAMPLER1D
901// | SAMPLER2D
902// | SAMPLER3D
903// | SAMPLERCUBE
904// | SAMPLERSTATE
905// | SAMPLERCOMPARISONSTATE
906bool HlslGrammar::acceptSamplerType(TType& type)
907{
908 // read sampler type
909 const EHlslTokenClass samplerType = peek();
910
LoopDawga78b0292016-07-19 14:28:05 -0600911 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600912 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600913
LoopDawga78b0292016-07-19 14:28:05 -0600914 bool isShadow = false;
915
LoopDawg4886f692016-06-29 10:58:58 -0600916 switch (samplerType) {
917 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600918 case EHTokSampler1d: /*dim = Esd1D*/; break;
919 case EHTokSampler2d: /*dim = Esd2D*/; break;
920 case EHTokSampler3d: /*dim = Esd3D*/; break;
921 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600922 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600923 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600924 default:
925 return false; // not a sampler declaration
926 }
927
928 advanceToken(); // consume the sampler type keyword
929
930 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600931
932 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600933 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600934
935 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
936
937 return true;
938}
939
940// texture_type
941// | BUFFER
942// | TEXTURE1D
943// | TEXTURE1DARRAY
944// | TEXTURE2D
945// | TEXTURE2DARRAY
946// | TEXTURE3D
947// | TEXTURECUBE
948// | TEXTURECUBEARRAY
949// | TEXTURE2DMS
950// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600951// | RWBUFFER
952// | RWTEXTURE1D
953// | RWTEXTURE1DARRAY
954// | RWTEXTURE2D
955// | RWTEXTURE2DARRAY
956// | RWTEXTURE3D
957
LoopDawg4886f692016-06-29 10:58:58 -0600958bool HlslGrammar::acceptTextureType(TType& type)
959{
960 const EHlslTokenClass textureType = peek();
961
962 TSamplerDim dim = EsdNone;
963 bool array = false;
964 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600965 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600966
967 switch (textureType) {
968 case EHTokBuffer: dim = EsdBuffer; break;
969 case EHTokTexture1d: dim = Esd1D; break;
970 case EHTokTexture1darray: dim = Esd1D; array = true; break;
971 case EHTokTexture2d: dim = Esd2D; break;
972 case EHTokTexture2darray: dim = Esd2D; array = true; break;
973 case EHTokTexture3d: dim = Esd3D; break;
974 case EHTokTextureCube: dim = EsdCube; break;
975 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
976 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
977 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -0600978 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
979 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
980 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
981 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
982 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
983 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600984 default:
985 return false; // not a texture declaration
986 }
987
988 advanceToken(); // consume the texture object keyword
989
990 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
991
992 TIntermTyped* msCount = nullptr;
993
steve-lunargbb0183f2016-10-04 16:58:14 -0600994 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -0600995 if (acceptTokenClass(EHTokLeftAngle)) {
996 if (! acceptType(txType)) {
997 expected("scalar or vector type");
998 return false;
999 }
1000
1001 const TBasicType basicRetType = txType.getBasicType() ;
1002
1003 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
1004 unimplemented("basic type in texture");
1005 return false;
1006 }
1007
steve-lunargd53f7172016-07-27 15:46:48 -06001008 // Buffers can handle small mats if they fit in 4 components
1009 if (dim == EsdBuffer && txType.isMatrix()) {
1010 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1011 expected("components < 4 in matrix buffer type");
1012 return false;
1013 }
1014
1015 // TODO: except we don't handle it yet...
1016 unimplemented("matrix type in buffer");
1017 return false;
1018 }
1019
LoopDawg4886f692016-06-29 10:58:58 -06001020 if (!txType.isScalar() && !txType.isVector()) {
1021 expected("scalar or vector type");
1022 return false;
1023 }
1024
LoopDawg4886f692016-06-29 10:58:58 -06001025 if (ms && acceptTokenClass(EHTokComma)) {
1026 // read sample count for multisample types, if given
1027 if (! peekTokenClass(EHTokIntConstant)) {
1028 expected("multisample count");
1029 return false;
1030 }
1031
1032 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1033 return false;
1034 }
1035
1036 if (! acceptTokenClass(EHTokRightAngle)) {
1037 expected("right angle bracket");
1038 return false;
1039 }
1040 } else if (ms) {
1041 expected("texture type for multisample");
1042 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001043 } else if (image) {
1044 expected("type for RWTexture/RWBuffer");
1045 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001046 }
1047
1048 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001049 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001050
1051 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001052 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001053
steve-lunarg4f2da272016-10-10 15:24:57 -06001054 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1055 if (image || dim == EsdBuffer)
1056 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001057
1058 // Non-image Buffers are combined
1059 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001060 sampler.set(txType.getBasicType(), dim, array);
1061 } else {
1062 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001063 if (image) {
1064 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1065 } else {
1066 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1067 }
steve-lunargd53f7172016-07-27 15:46:48 -06001068 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001069
1070 // Remember the declared vector size.
1071 sampler.vectorSize = txType.getVectorSize();
LoopDawg4886f692016-06-29 10:58:58 -06001072
1073 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001074 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001075
1076 return true;
1077}
1078
1079
John Kessenich87142c72016-03-12 20:24:24 -07001080// If token is for a type, update 'type' with the type information,
1081// and return true and advance.
1082// Otherwise, return false, and don't advance
1083bool HlslGrammar::acceptType(TType& type)
1084{
steve-lunarg3226b082016-10-26 19:18:55 -06001085 // Basic types for min* types, broken out here in case of future
1086 // changes, e.g, to use native halfs.
1087 static const TBasicType min16float_bt = EbtFloat;
1088 static const TBasicType min10float_bt = EbtFloat;
1089 static const TBasicType min16int_bt = EbtInt;
1090 static const TBasicType min12int_bt = EbtInt;
1091 static const TBasicType min16uint_bt = EbtUint;
1092
John Kessenich9c86c6a2016-05-03 22:49:24 -06001093 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001094 case EHTokVector:
1095 return acceptVectorTemplateType(type);
1096 break;
1097
1098 case EHTokMatrix:
1099 return acceptMatrixTemplateType(type);
1100 break;
1101
steve-lunargf49cdf42016-11-17 15:04:20 -07001102 case EHTokPointStream: // fall through
1103 case EHTokLineStream: // ...
1104 case EHTokTriangleStream: // ...
1105 {
1106 TLayoutGeometry geometry;
1107 if (! acceptStreamOutTemplateType(type, geometry))
1108 return false;
1109
1110 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1111 return false;
1112
1113 return true;
1114 }
1115
LoopDawg4886f692016-06-29 10:58:58 -06001116 case EHTokSampler: // fall through
1117 case EHTokSampler1d: // ...
1118 case EHTokSampler2d: // ...
1119 case EHTokSampler3d: // ...
1120 case EHTokSamplerCube: // ...
1121 case EHTokSamplerState: // ...
1122 case EHTokSamplerComparisonState: // ...
1123 return acceptSamplerType(type);
1124 break;
1125
1126 case EHTokBuffer: // fall through
1127 case EHTokTexture1d: // ...
1128 case EHTokTexture1darray: // ...
1129 case EHTokTexture2d: // ...
1130 case EHTokTexture2darray: // ...
1131 case EHTokTexture3d: // ...
1132 case EHTokTextureCube: // ...
1133 case EHTokTextureCubearray: // ...
1134 case EHTokTexture2DMS: // ...
1135 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001136 case EHTokRWTexture1d: // ...
1137 case EHTokRWTexture1darray: // ...
1138 case EHTokRWTexture2d: // ...
1139 case EHTokRWTexture2darray: // ...
1140 case EHTokRWTexture3d: // ...
1141 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001142 return acceptTextureType(type);
1143 break;
1144
John Kesseniche6e74942016-06-11 16:43:14 -06001145 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001146 case EHTokCBuffer:
1147 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001148 return acceptStruct(type);
1149 break;
1150
1151 case EHTokIdentifier:
1152 // An identifier could be for a user-defined type.
1153 // Note we cache the symbol table lookup, to save for a later rule
1154 // when this is not a type.
1155 token.symbol = parseContext.symbolTable.find(*token.string);
1156 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1157 type.shallowCopy(token.symbol->getType());
1158 advanceToken();
1159 return true;
1160 } else
1161 return false;
1162
John Kessenich71351de2016-06-08 12:50:56 -06001163 case EHTokVoid:
1164 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001165 break;
John Kessenich71351de2016-06-08 12:50:56 -06001166
John Kessenicha1e2d492016-09-20 13:22:58 -06001167 case EHTokString:
1168 new(&type) TType(EbtString);
1169 break;
1170
John Kessenich87142c72016-03-12 20:24:24 -07001171 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001172 new(&type) TType(EbtFloat);
1173 break;
John Kessenich87142c72016-03-12 20:24:24 -07001174 case EHTokFloat1:
1175 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001176 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001177 break;
John Kessenich87142c72016-03-12 20:24:24 -07001178 case EHTokFloat2:
1179 new(&type) TType(EbtFloat, EvqTemporary, 2);
1180 break;
1181 case EHTokFloat3:
1182 new(&type) TType(EbtFloat, EvqTemporary, 3);
1183 break;
1184 case EHTokFloat4:
1185 new(&type) TType(EbtFloat, EvqTemporary, 4);
1186 break;
1187
John Kessenich71351de2016-06-08 12:50:56 -06001188 case EHTokDouble:
1189 new(&type) TType(EbtDouble);
1190 break;
1191 case EHTokDouble1:
1192 new(&type) TType(EbtDouble);
1193 type.makeVector();
1194 break;
1195 case EHTokDouble2:
1196 new(&type) TType(EbtDouble, EvqTemporary, 2);
1197 break;
1198 case EHTokDouble3:
1199 new(&type) TType(EbtDouble, EvqTemporary, 3);
1200 break;
1201 case EHTokDouble4:
1202 new(&type) TType(EbtDouble, EvqTemporary, 4);
1203 break;
1204
1205 case EHTokInt:
1206 case EHTokDword:
1207 new(&type) TType(EbtInt);
1208 break;
1209 case EHTokInt1:
1210 new(&type) TType(EbtInt);
1211 type.makeVector();
1212 break;
John Kessenich87142c72016-03-12 20:24:24 -07001213 case EHTokInt2:
1214 new(&type) TType(EbtInt, EvqTemporary, 2);
1215 break;
1216 case EHTokInt3:
1217 new(&type) TType(EbtInt, EvqTemporary, 3);
1218 break;
1219 case EHTokInt4:
1220 new(&type) TType(EbtInt, EvqTemporary, 4);
1221 break;
1222
John Kessenich71351de2016-06-08 12:50:56 -06001223 case EHTokUint:
1224 new(&type) TType(EbtUint);
1225 break;
1226 case EHTokUint1:
1227 new(&type) TType(EbtUint);
1228 type.makeVector();
1229 break;
1230 case EHTokUint2:
1231 new(&type) TType(EbtUint, EvqTemporary, 2);
1232 break;
1233 case EHTokUint3:
1234 new(&type) TType(EbtUint, EvqTemporary, 3);
1235 break;
1236 case EHTokUint4:
1237 new(&type) TType(EbtUint, EvqTemporary, 4);
1238 break;
1239
LoopDawg6daaa4f2016-06-23 19:13:48 -06001240
John Kessenich71351de2016-06-08 12:50:56 -06001241 case EHTokBool:
1242 new(&type) TType(EbtBool);
1243 break;
1244 case EHTokBool1:
1245 new(&type) TType(EbtBool);
1246 type.makeVector();
1247 break;
John Kessenich87142c72016-03-12 20:24:24 -07001248 case EHTokBool2:
1249 new(&type) TType(EbtBool, EvqTemporary, 2);
1250 break;
1251 case EHTokBool3:
1252 new(&type) TType(EbtBool, EvqTemporary, 3);
1253 break;
1254 case EHTokBool4:
1255 new(&type) TType(EbtBool, EvqTemporary, 4);
1256 break;
1257
steve-lunarg3226b082016-10-26 19:18:55 -06001258 case EHTokMin16float:
1259 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1260 break;
1261 case EHTokMin16float1:
1262 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1263 type.makeVector();
1264 break;
1265 case EHTokMin16float2:
1266 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1267 break;
1268 case EHTokMin16float3:
1269 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1270 break;
1271 case EHTokMin16float4:
1272 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1273 break;
1274
1275 case EHTokMin10float:
1276 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1277 break;
1278 case EHTokMin10float1:
1279 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1280 type.makeVector();
1281 break;
1282 case EHTokMin10float2:
1283 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1284 break;
1285 case EHTokMin10float3:
1286 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1287 break;
1288 case EHTokMin10float4:
1289 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1290 break;
1291
1292 case EHTokMin16int:
1293 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1294 break;
1295 case EHTokMin16int1:
1296 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1297 type.makeVector();
1298 break;
1299 case EHTokMin16int2:
1300 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1301 break;
1302 case EHTokMin16int3:
1303 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1304 break;
1305 case EHTokMin16int4:
1306 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1307 break;
1308
1309 case EHTokMin12int:
1310 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1311 break;
1312 case EHTokMin12int1:
1313 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1314 type.makeVector();
1315 break;
1316 case EHTokMin12int2:
1317 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1318 break;
1319 case EHTokMin12int3:
1320 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1321 break;
1322 case EHTokMin12int4:
1323 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1324 break;
1325
1326 case EHTokMin16uint:
1327 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1328 break;
1329 case EHTokMin16uint1:
1330 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1331 type.makeVector();
1332 break;
1333 case EHTokMin16uint2:
1334 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1335 break;
1336 case EHTokMin16uint3:
1337 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1338 break;
1339 case EHTokMin16uint4:
1340 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1341 break;
1342
John Kessenich0133c122016-05-20 12:17:26 -06001343 case EHTokInt1x1:
1344 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1345 break;
1346 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001347 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001348 break;
1349 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001350 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001351 break;
1352 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001353 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001354 break;
1355 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001356 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001357 break;
1358 case EHTokInt2x2:
1359 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1360 break;
1361 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001362 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001363 break;
1364 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001365 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001366 break;
1367 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001368 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001369 break;
1370 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001371 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001372 break;
1373 case EHTokInt3x3:
1374 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1375 break;
1376 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001377 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001378 break;
1379 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001380 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001381 break;
1382 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001383 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001384 break;
1385 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001386 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001387 break;
1388 case EHTokInt4x4:
1389 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1390 break;
1391
John Kessenich71351de2016-06-08 12:50:56 -06001392 case EHTokUint1x1:
1393 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1394 break;
1395 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001396 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001397 break;
1398 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001399 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001400 break;
1401 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001402 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001403 break;
1404 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001405 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001406 break;
1407 case EHTokUint2x2:
1408 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1409 break;
1410 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001411 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001412 break;
1413 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001414 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001415 break;
1416 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001417 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001418 break;
1419 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001420 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001421 break;
1422 case EHTokUint3x3:
1423 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1424 break;
1425 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001426 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001427 break;
1428 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001429 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001430 break;
1431 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001432 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001433 break;
1434 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001435 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001436 break;
1437 case EHTokUint4x4:
1438 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1439 break;
1440
1441 case EHTokBool1x1:
1442 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1443 break;
1444 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001445 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001446 break;
1447 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001448 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001449 break;
1450 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001451 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001452 break;
1453 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001454 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001455 break;
1456 case EHTokBool2x2:
1457 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1458 break;
1459 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001460 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001461 break;
1462 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001463 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001464 break;
1465 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001466 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001467 break;
1468 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001469 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001470 break;
1471 case EHTokBool3x3:
1472 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1473 break;
1474 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001475 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001476 break;
1477 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001478 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001479 break;
1480 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001481 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001482 break;
1483 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001484 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001485 break;
1486 case EHTokBool4x4:
1487 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1488 break;
1489
John Kessenich0133c122016-05-20 12:17:26 -06001490 case EHTokFloat1x1:
1491 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1492 break;
1493 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001494 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001495 break;
1496 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001497 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001498 break;
1499 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001500 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001501 break;
1502 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001503 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001504 break;
John Kessenich87142c72016-03-12 20:24:24 -07001505 case EHTokFloat2x2:
1506 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1507 break;
1508 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001509 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001510 break;
1511 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001512 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001513 break;
John Kessenich0133c122016-05-20 12:17:26 -06001514 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001515 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001516 break;
John Kessenich87142c72016-03-12 20:24:24 -07001517 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001518 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001519 break;
1520 case EHTokFloat3x3:
1521 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1522 break;
1523 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001524 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001525 break;
John Kessenich0133c122016-05-20 12:17:26 -06001526 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001527 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001528 break;
John Kessenich87142c72016-03-12 20:24:24 -07001529 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001530 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001531 break;
1532 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001533 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001534 break;
1535 case EHTokFloat4x4:
1536 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1537 break;
1538
John Kessenich0133c122016-05-20 12:17:26 -06001539 case EHTokDouble1x1:
1540 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1541 break;
1542 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001543 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001544 break;
1545 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001546 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001547 break;
1548 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001549 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001550 break;
1551 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001552 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001553 break;
1554 case EHTokDouble2x2:
1555 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1556 break;
1557 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001558 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001559 break;
1560 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001561 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001562 break;
1563 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001564 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001565 break;
1566 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001567 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001568 break;
1569 case EHTokDouble3x3:
1570 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1571 break;
1572 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001573 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001574 break;
1575 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001576 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001577 break;
1578 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001579 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001580 break;
1581 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001582 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001583 break;
1584 case EHTokDouble4x4:
1585 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1586 break;
1587
John Kessenich87142c72016-03-12 20:24:24 -07001588 default:
1589 return false;
1590 }
1591
1592 advanceToken();
1593
1594 return true;
1595}
1596
John Kesseniche6e74942016-06-11 16:43:14 -06001597// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001598// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1599// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1600//
1601// struct_type
1602// : STRUCT
1603// | CBUFFER
1604// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001605//
1606bool HlslGrammar::acceptStruct(TType& type)
1607{
John Kessenichb804de62016-09-05 12:19:18 -06001608 // This storage qualifier will tell us whether it's an AST
1609 // block type or just a generic structure type.
1610 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001611
1612 // CBUFFER
1613 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001614 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001615 // TBUFFER
1616 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001617 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001618 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001619 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001620 return false;
1621
1622 // IDENTIFIER
1623 TString structName = "";
1624 if (peekTokenClass(EHTokIdentifier)) {
1625 structName = *token.string;
1626 advanceToken();
1627 }
1628
John Kessenich3d157c52016-07-25 16:05:33 -06001629 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001630 TQualifier postDeclQualifier;
1631 postDeclQualifier.clear();
1632 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001633
John Kesseniche6e74942016-06-11 16:43:14 -06001634 // LEFT_BRACE
1635 if (! acceptTokenClass(EHTokLeftBrace)) {
1636 expected("{");
1637 return false;
1638 }
1639
1640 // struct_declaration_list
1641 TTypeList* typeList;
1642 if (! acceptStructDeclarationList(typeList)) {
1643 expected("struct member declarations");
1644 return false;
1645 }
1646
1647 // RIGHT_BRACE
1648 if (! acceptTokenClass(EHTokRightBrace)) {
1649 expected("}");
1650 return false;
1651 }
1652
1653 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001654 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001655 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001656 else {
John Kessenich7735b942016-09-05 12:40:06 -06001657 postDeclQualifier.storage = storageQualifier;
1658 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001659 }
John Kesseniche6e74942016-06-11 16:43:14 -06001660
John Kessenich3d157c52016-07-25 16:05:33 -06001661 // If it was named, which means the type can be reused later, add
1662 // it to the symbol table. (Unless it's a block, in which
1663 // case the name is not a type.)
1664 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001665 TVariable* userTypeDef = new TVariable(&structName, type, true);
1666 if (! parseContext.symbolTable.insert(*userTypeDef))
1667 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1668 }
1669
1670 return true;
1671}
1672
1673// struct_declaration_list
1674// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1675//
1676// struct_declaration
1677// : fully_specified_type struct_declarator COMMA struct_declarator ...
1678//
1679// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001680// : IDENTIFIER post_decls
1681// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001682//
1683bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1684{
1685 typeList = new TTypeList();
1686
1687 do {
1688 // success on seeing the RIGHT_BRACE coming up
1689 if (peekTokenClass(EHTokRightBrace))
1690 return true;
1691
1692 // struct_declaration
1693
1694 // fully_specified_type
1695 TType memberType;
1696 if (! acceptFullySpecifiedType(memberType)) {
1697 expected("member type");
1698 return false;
1699 }
1700
1701 // struct_declarator COMMA struct_declarator ...
1702 do {
1703 // peek IDENTIFIER
1704 if (! peekTokenClass(EHTokIdentifier)) {
1705 expected("member name");
1706 return false;
1707 }
1708
1709 // add it to the list of members
1710 TTypeLoc member = { new TType(EbtVoid), token.loc };
1711 member.type->shallowCopy(memberType);
1712 member.type->setFieldName(*token.string);
1713 typeList->push_back(member);
1714
1715 // accept IDENTIFIER
1716 advanceToken();
1717
1718 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001719 TArraySizes* arraySizes = nullptr;
1720 acceptArraySpecifier(arraySizes);
1721 if (arraySizes)
1722 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001723
John Kessenich7735b942016-09-05 12:40:06 -06001724 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001725
John Kesseniche6e74942016-06-11 16:43:14 -06001726 // success on seeing the SEMICOLON coming up
1727 if (peekTokenClass(EHTokSemicolon))
1728 break;
1729
1730 // COMMA
1731 if (! acceptTokenClass(EHTokComma)) {
1732 expected(",");
1733 return false;
1734 }
1735
1736 } while (true);
1737
1738 // SEMI_COLON
1739 if (! acceptTokenClass(EHTokSemicolon)) {
1740 expected(";");
1741 return false;
1742 }
1743
1744 } while (true);
1745}
1746
John Kessenich5f934b02016-03-13 17:58:25 -06001747// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001748// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001749// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001750//
1751bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1752{
John Kessenich078d7f22016-03-14 10:02:11 -06001753 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001754 if (! acceptTokenClass(EHTokLeftParen))
1755 return false;
1756
John Kessenich71351de2016-06-08 12:50:56 -06001757 // VOID RIGHT_PAREN
1758 if (! acceptTokenClass(EHTokVoid)) {
1759 do {
1760 // parameter_declaration
1761 if (! acceptParameterDeclaration(function))
1762 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001763
John Kessenich71351de2016-06-08 12:50:56 -06001764 // COMMA
1765 if (! acceptTokenClass(EHTokComma))
1766 break;
1767 } while (true);
1768 }
John Kessenich5f934b02016-03-13 17:58:25 -06001769
John Kessenich078d7f22016-03-14 10:02:11 -06001770 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001771 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001772 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001773 return false;
1774 }
1775
1776 return true;
1777}
1778
1779// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001780// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001781// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001782//
1783bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1784{
1785 // fully_specified_type
1786 TType* type = new TType;
1787 if (! acceptFullySpecifiedType(*type))
1788 return false;
1789
1790 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001791 HlslToken idToken;
1792 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001793
John Kessenich19b92ff2016-06-19 11:50:34 -06001794 // array_specifier
1795 TArraySizes* arraySizes = nullptr;
1796 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001797 if (arraySizes) {
1798 if (arraySizes->isImplicit()) {
1799 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1800 return false;
1801 }
1802
John Kessenich19b92ff2016-06-19 11:50:34 -06001803 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001804 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001805
1806 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001807 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001808
John Kessenich5aa59e22016-06-17 15:50:47 -06001809 parseContext.paramFix(*type);
1810
John Kessenichaecd4972016-03-14 10:46:34 -06001811 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001812 function.addParameter(param);
1813
1814 return true;
1815}
1816
1817// Do the work to create the function definition in addition to
1818// parsing the body (compound_statement).
steve-lunarg1868b142016-10-20 13:07:10 -06001819bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001820{
John Kessenicha3051662016-09-02 19:13:36 -06001821 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001822 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001823
John Kessenich077e0522016-06-09 02:02:17 -06001824 // This does a pushScope()
steve-lunarg1868b142016-10-20 13:07:10 -06001825 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06001826
1827 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001828 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001829 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001830 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001831 return true;
1832 }
1833
1834 return false;
1835}
1836
John Kessenich0d2b6de2016-06-05 11:23:11 -06001837// Accept an expression with parenthesis around it, where
1838// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001839// syntactically required ones like in "if ( expression )".
1840//
1841// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001842//
1843// Note this one is not set up to be speculative; as it gives
1844// errors if not found.
1845//
1846bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1847{
1848 // LEFT_PAREN
1849 if (! acceptTokenClass(EHTokLeftParen))
1850 expected("(");
1851
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001852 bool decl = false;
1853 TIntermNode* declNode = nullptr;
1854 decl = acceptControlDeclaration(declNode);
1855 if (decl) {
1856 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1857 expected("initialized declaration");
1858 return false;
1859 } else
1860 expression = declNode->getAsTyped();
1861 } else {
1862 // no declaration
1863 if (! acceptExpression(expression)) {
1864 expected("expression");
1865 return false;
1866 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001867 }
1868
1869 // RIGHT_PAREN
1870 if (! acceptTokenClass(EHTokRightParen))
1871 expected(")");
1872
1873 return true;
1874}
1875
John Kessenich34fb0362016-05-03 23:17:20 -06001876// The top-level full expression recognizer.
1877//
John Kessenich87142c72016-03-12 20:24:24 -07001878// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001879// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001880//
1881bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1882{
LoopDawgef764a22016-06-03 09:17:51 -06001883 node = nullptr;
1884
John Kessenich34fb0362016-05-03 23:17:20 -06001885 // assignment_expression
1886 if (! acceptAssignmentExpression(node))
1887 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001888
John Kessenich34fb0362016-05-03 23:17:20 -06001889 if (! peekTokenClass(EHTokComma))
1890 return true;
1891
1892 do {
1893 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001894 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001895 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001896
John Kessenich34fb0362016-05-03 23:17:20 -06001897 // ... assignment_expression
1898 TIntermTyped* rightNode = nullptr;
1899 if (! acceptAssignmentExpression(rightNode)) {
1900 expected("assignment expression");
1901 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001902 }
1903
John Kessenich34fb0362016-05-03 23:17:20 -06001904 node = intermediate.addComma(node, rightNode, loc);
1905
1906 if (! peekTokenClass(EHTokComma))
1907 return true;
1908 } while (true);
1909}
1910
John Kessenich07354242016-07-01 19:58:06 -06001911// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07001912// : LEFT_BRACE RIGHT_BRACE
1913// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001914//
1915// initializer_list
1916// : assignment_expression COMMA assignment_expression COMMA ...
1917//
1918bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1919{
1920 // LEFT_BRACE
1921 if (! acceptTokenClass(EHTokLeftBrace))
1922 return false;
1923
John Kessenich98ad4852016-11-27 17:39:07 -07001924 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001925 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07001926 if (acceptTokenClass(EHTokRightBrace)) {
1927 // a zero-length initializer list
1928 node = intermediate.makeAggregate(loc);
1929 return true;
1930 }
1931
1932 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06001933 node = nullptr;
1934 do {
1935 // assignment_expression
1936 TIntermTyped* expr;
1937 if (! acceptAssignmentExpression(expr)) {
1938 expected("assignment expression in initializer list");
1939 return false;
1940 }
1941 node = intermediate.growAggregate(node, expr, loc);
1942
1943 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001944 if (acceptTokenClass(EHTokComma)) {
1945 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1946 return true;
John Kessenich07354242016-07-01 19:58:06 -06001947 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001948 }
John Kessenich07354242016-07-01 19:58:06 -06001949
1950 // RIGHT_BRACE
1951 if (acceptTokenClass(EHTokRightBrace))
1952 return true;
1953
1954 expected(", or }");
1955 return false;
1956 } while (true);
1957}
1958
John Kessenich34fb0362016-05-03 23:17:20 -06001959// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001960// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001961//
1962// a op (b op (c op d))
1963//
1964// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001965// : initializer
1966// | conditional_expression
1967// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001968//
1969bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1970{
John Kessenich07354242016-07-01 19:58:06 -06001971 // initializer
1972 if (peekTokenClass(EHTokLeftBrace)) {
1973 if (acceptInitializer(node))
1974 return true;
1975
1976 expected("initializer");
1977 return false;
1978 }
1979
John Kessenich00957f82016-07-27 10:39:57 -06001980 // conditional_expression
1981 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001982 return false;
1983
John Kessenich07354242016-07-01 19:58:06 -06001984 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001985 TOperator assignOp = HlslOpMap::assignment(peek());
1986 if (assignOp == EOpNull)
1987 return true;
1988
John Kessenich00957f82016-07-27 10:39:57 -06001989 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001990 TSourceLoc loc = token.loc;
1991 advanceToken();
1992
John Kessenich00957f82016-07-27 10:39:57 -06001993 // conditional_expression assign_op conditional_expression ...
1994 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001995 // gets the right-to-left associativity.
1996 TIntermTyped* rightNode = nullptr;
1997 if (! acceptAssignmentExpression(rightNode)) {
1998 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001999 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002000 }
2001
John Kessenichd21baed2016-09-16 03:05:12 -06002002 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06002003 node = parseContext.handleLvalue(loc, "assign", node);
2004
John Kessenichfea226b2016-07-28 17:53:56 -06002005 if (node == nullptr) {
2006 parseContext.error(loc, "could not create assignment", "", "");
2007 return false;
2008 }
John Kessenich34fb0362016-05-03 23:17:20 -06002009
2010 if (! peekTokenClass(EHTokComma))
2011 return true;
2012
2013 return true;
2014}
2015
John Kessenich00957f82016-07-27 10:39:57 -06002016// Accept a conditional expression, which associates right-to-left,
2017// accomplished by the "true" expression calling down to lower
2018// precedence levels than this level.
2019//
2020// conditional_expression
2021// : binary_expression
2022// | binary_expression QUESTION expression COLON assignment_expression
2023//
2024bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2025{
2026 // binary_expression
2027 if (! acceptBinaryExpression(node, PlLogicalOr))
2028 return false;
2029
2030 if (! acceptTokenClass(EHTokQuestion))
2031 return true;
2032
2033 TIntermTyped* trueNode = nullptr;
2034 if (! acceptExpression(trueNode)) {
2035 expected("expression after ?");
2036 return false;
2037 }
2038 TSourceLoc loc = token.loc;
2039
2040 if (! acceptTokenClass(EHTokColon)) {
2041 expected(":");
2042 return false;
2043 }
2044
2045 TIntermTyped* falseNode = nullptr;
2046 if (! acceptAssignmentExpression(falseNode)) {
2047 expected("expression after :");
2048 return false;
2049 }
2050
2051 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2052
2053 return true;
2054}
2055
John Kessenich34fb0362016-05-03 23:17:20 -06002056// Accept a binary expression, for binary operations that
2057// associate left-to-right. This is, it is implicit, for example
2058//
2059// ((a op b) op c) op d
2060//
2061// binary_expression
2062// : expression op expression op expression ...
2063//
2064// where 'expression' is the next higher level in precedence.
2065//
2066bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2067{
2068 if (precedenceLevel > PlMul)
2069 return acceptUnaryExpression(node);
2070
2071 // assignment_expression
2072 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2073 return false;
2074
John Kessenich34fb0362016-05-03 23:17:20 -06002075 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002076 TOperator op = HlslOpMap::binary(peek());
2077 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2078 if (tokenLevel < precedenceLevel)
2079 return true;
2080
John Kessenich34fb0362016-05-03 23:17:20 -06002081 // ... op
2082 TSourceLoc loc = token.loc;
2083 advanceToken();
2084
2085 // ... expression
2086 TIntermTyped* rightNode = nullptr;
2087 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2088 expected("expression");
2089 return false;
2090 }
2091
2092 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002093 if (node == nullptr) {
2094 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2095 return false;
2096 }
John Kessenich34fb0362016-05-03 23:17:20 -06002097 } while (true);
2098}
2099
2100// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002101// : (type) unary_expression
2102// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002103// | - unary_expression
2104// | ! unary_expression
2105// | ~ unary_expression
2106// | ++ unary_expression
2107// | -- unary_expression
2108// | postfix_expression
2109//
2110bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2111{
John Kessenich1cc1a282016-06-03 16:55:49 -06002112 // (type) unary_expression
2113 // Have to look two steps ahead, because this could be, e.g., a
2114 // postfix_expression instead, since that also starts with at "(".
2115 if (acceptTokenClass(EHTokLeftParen)) {
2116 TType castType;
2117 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002118 if (acceptTokenClass(EHTokRightParen)) {
2119 // We've matched "(type)" now, get the expression to cast
2120 TSourceLoc loc = token.loc;
2121 if (! acceptUnaryExpression(node))
2122 return false;
2123
2124 // Hook it up like a constructor
2125 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2126 if (constructorFunction == nullptr) {
2127 expected("type that can be constructed");
2128 return false;
2129 }
2130 TIntermTyped* arguments = nullptr;
2131 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2132 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2133
2134 return true;
2135 } else {
2136 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2137 // the '(int' part. We must back up twice.
2138 recedeToken();
2139 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002140 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002141 } else {
2142 // This isn't a type cast, but it still started "(", so if it is a
2143 // unary expression, it can only be a postfix_expression, so try that.
2144 // Back it up first.
2145 recedeToken();
2146 return acceptPostfixExpression(node);
2147 }
2148 }
2149
2150 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002151 TOperator unaryOp = HlslOpMap::preUnary(peek());
2152
John Kessenich1cc1a282016-06-03 16:55:49 -06002153 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002154 if (unaryOp == EOpNull)
2155 return acceptPostfixExpression(node);
2156
2157 // op unary_expression
2158 TSourceLoc loc = token.loc;
2159 advanceToken();
2160 if (! acceptUnaryExpression(node))
2161 return false;
2162
2163 // + is a no-op
2164 if (unaryOp == EOpAdd)
2165 return true;
2166
2167 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002168
2169 // These unary ops require lvalues
2170 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2171 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002172
2173 return node != nullptr;
2174}
2175
2176// postfix_expression
2177// : LEFT_PAREN expression RIGHT_PAREN
2178// | literal
2179// | constructor
2180// | identifier
2181// | function_call
2182// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2183// | postfix_expression DOT IDENTIFIER
2184// | postfix_expression INC_OP
2185// | postfix_expression DEC_OP
2186//
2187bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2188{
2189 // Not implemented as self-recursive:
2190 // The logical "right recursion" is done with an loop at the end
2191
2192 // idToken will pick up either a variable or a function name in a function call
2193 HlslToken idToken;
2194
John Kessenich21472ae2016-06-04 11:46:33 -06002195 // Find something before the postfix operations, as they can't operate
2196 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002197 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002198 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002199 if (! acceptExpression(node)) {
2200 expected("expression");
2201 return false;
2202 }
2203 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002204 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002205 return false;
2206 }
John Kessenich34fb0362016-05-03 23:17:20 -06002207 } else if (acceptLiteral(node)) {
2208 // literal (nothing else to do yet), go on to the
2209 } else if (acceptConstructor(node)) {
2210 // constructor (nothing else to do yet)
2211 } else if (acceptIdentifier(idToken)) {
2212 // identifier or function_call name
2213 if (! peekTokenClass(EHTokLeftParen)) {
steve-lunarga64ed3e2016-12-18 17:51:14 -07002214 node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002215 } else if (acceptFunctionCall(idToken, node)) {
2216 // function_call (nothing else to do yet)
2217 } else {
2218 expected("function call arguments");
2219 return false;
2220 }
John Kessenich21472ae2016-06-04 11:46:33 -06002221 } else {
2222 // nothing found, can't post operate
2223 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002224 }
2225
steve-lunarga2b01a02016-11-28 17:09:54 -07002226 // This is to guarantee we do this no matter how we get out of the stack frame.
2227 // This way there's no bug if an early return forgets to do it.
2228 struct tFinalize {
2229 tFinalize(HlslParseContext& p) : parseContext(p) { }
2230 ~tFinalize() { parseContext.finalizeFlattening(); }
2231 HlslParseContext& parseContext;
2232 } finalize(parseContext);
2233
2234 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2235 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2236 // level: hence the init and finalize. Even though in practice these must be
2237 // constants, they are parsed no matter what.
2238 parseContext.initFlattening();
2239
John Kessenich21472ae2016-06-04 11:46:33 -06002240 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002241 do {
2242 TSourceLoc loc = token.loc;
2243 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002244
John Kessenich34fb0362016-05-03 23:17:20 -06002245 // Consume only a valid post-unary operator, otherwise we are done.
2246 switch (postOp) {
2247 case EOpIndexDirectStruct:
2248 case EOpIndexIndirect:
2249 case EOpPostIncrement:
2250 case EOpPostDecrement:
2251 advanceToken();
2252 break;
2253 default:
2254 return true;
2255 }
John Kessenich87142c72016-03-12 20:24:24 -07002256
John Kessenich34fb0362016-05-03 23:17:20 -06002257 // We have a valid post-unary operator, process it.
2258 switch (postOp) {
2259 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002260 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002261 // DOT IDENTIFIER
2262 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002263 HlslToken field;
2264 if (! acceptIdentifier(field)) {
2265 expected("swizzle or member");
2266 return false;
2267 }
LoopDawg4886f692016-06-29 10:58:58 -06002268
2269 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002270 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002271
2272 // In the event of a method node, we look for an open paren and accept the function call.
steve-lunarga2b01a02016-11-28 17:09:54 -07002273 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002274 if (! acceptFunctionCall(field, node, base)) {
2275 expected("function parameters");
2276 return false;
2277 }
2278 }
2279
John Kessenich34fb0362016-05-03 23:17:20 -06002280 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002281 }
John Kessenich34fb0362016-05-03 23:17:20 -06002282 case EOpIndexIndirect:
2283 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002284 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002285 TIntermTyped* indexNode = nullptr;
2286 if (! acceptExpression(indexNode) ||
2287 ! peekTokenClass(EHTokRightBracket)) {
2288 expected("expression followed by ']'");
2289 return false;
2290 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002291 advanceToken();
2292 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2293 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002294 }
2295 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002296 // INC_OP
2297 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002298 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002299 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002300 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002301 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002302 break;
2303 default:
2304 assert(0);
2305 break;
2306 }
2307 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002308}
2309
John Kessenichd016be12016-03-13 11:24:20 -06002310// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002311// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002312//
2313bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2314{
2315 // type
2316 TType type;
2317 if (acceptType(type)) {
2318 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2319 if (constructorFunction == nullptr)
2320 return false;
2321
2322 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002323 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002324 if (! acceptArguments(constructorFunction, arguments)) {
2325 expected("constructor arguments");
2326 return false;
2327 }
2328
2329 // hook it up
2330 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2331
2332 return true;
2333 }
2334
2335 return false;
2336}
2337
John Kessenich34fb0362016-05-03 23:17:20 -06002338// The function_call identifier was already recognized, and passed in as idToken.
2339//
2340// function_call
2341// : [idToken] arguments
2342//
LoopDawg4886f692016-06-29 10:58:58 -06002343bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002344{
John Kessenich4678ca92016-05-13 09:33:42 -06002345 // arguments
2346 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2347 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002348
2349 // methods have an implicit first argument of the calling object.
2350 if (base != nullptr)
2351 parseContext.handleFunctionArgument(function, arguments, base);
2352
John Kessenich4678ca92016-05-13 09:33:42 -06002353 if (! acceptArguments(function, arguments))
2354 return false;
2355
2356 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2357
2358 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002359}
2360
John Kessenich87142c72016-03-12 20:24:24 -07002361// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002362// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002363//
John Kessenichd016be12016-03-13 11:24:20 -06002364// The arguments are pushed onto the 'function' argument list and
2365// onto the 'arguments' aggregate.
2366//
John Kessenich4678ca92016-05-13 09:33:42 -06002367bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002368{
John Kessenich078d7f22016-03-14 10:02:11 -06002369 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002370 if (! acceptTokenClass(EHTokLeftParen))
2371 return false;
2372
2373 do {
John Kessenichd016be12016-03-13 11:24:20 -06002374 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002375 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002376 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002377 break;
John Kessenichd016be12016-03-13 11:24:20 -06002378
2379 // hook it up
2380 parseContext.handleFunctionArgument(function, arguments, arg);
2381
John Kessenich078d7f22016-03-14 10:02:11 -06002382 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002383 if (! acceptTokenClass(EHTokComma))
2384 break;
2385 } while (true);
2386
John Kessenich078d7f22016-03-14 10:02:11 -06002387 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002388 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002389 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002390 return false;
2391 }
2392
2393 return true;
2394}
2395
2396bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2397{
2398 switch (token.tokenClass) {
2399 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002400 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002401 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002402 case EHTokUintConstant:
2403 node = intermediate.addConstantUnion(token.u, token.loc, true);
2404 break;
John Kessenich87142c72016-03-12 20:24:24 -07002405 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002406 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002407 break;
2408 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002409 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002410 break;
2411 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002412 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002413 break;
John Kessenich86f71382016-09-19 20:23:18 -06002414 case EHTokStringConstant:
2415 node = nullptr;
2416 break;
John Kessenich87142c72016-03-12 20:24:24 -07002417
2418 default:
2419 return false;
2420 }
2421
2422 advanceToken();
2423
2424 return true;
2425}
2426
John Kessenich5f934b02016-03-13 17:58:25 -06002427// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002428// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002429//
John Kessenich21472ae2016-06-04 11:46:33 -06002430bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002431{
John Kessenich21472ae2016-06-04 11:46:33 -06002432 TIntermAggregate* compoundStatement = nullptr;
2433
John Kessenich34fb0362016-05-03 23:17:20 -06002434 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002435 if (! acceptTokenClass(EHTokLeftBrace))
2436 return false;
2437
2438 // statement statement ...
2439 TIntermNode* statement = nullptr;
2440 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002441 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2442 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2443 branch->getFlowOp() == EOpDefault)) {
2444 // hook up individual subsequences within a switch statement
2445 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2446 compoundStatement = nullptr;
2447 } else {
2448 // hook it up to the growing compound statement
2449 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2450 }
John Kessenich5f934b02016-03-13 17:58:25 -06002451 }
John Kessenich34fb0362016-05-03 23:17:20 -06002452 if (compoundStatement)
2453 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002454
John Kessenich21472ae2016-06-04 11:46:33 -06002455 retStatement = compoundStatement;
2456
John Kessenich34fb0362016-05-03 23:17:20 -06002457 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002458 return acceptTokenClass(EHTokRightBrace);
2459}
2460
John Kessenich0d2b6de2016-06-05 11:23:11 -06002461bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2462{
2463 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002464 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002465 parseContext.popScope();
2466
2467 return result;
2468}
2469
John Kessenich077e0522016-06-09 02:02:17 -06002470bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002471{
John Kessenich077e0522016-06-09 02:02:17 -06002472 parseContext.pushScope();
2473 bool result = acceptCompoundStatement(statement);
2474 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002475
2476 return result;
2477}
2478
John Kessenich5f934b02016-03-13 17:58:25 -06002479// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002480// : attributes attributed_statement
2481//
2482// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002483// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002484// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002485// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002486// | declaration_statement
2487// | selection_statement
2488// | switch_statement
2489// | case_label
2490// | iteration_statement
2491// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002492//
2493bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2494{
John Kessenich21472ae2016-06-04 11:46:33 -06002495 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002496
John Kessenich21472ae2016-06-04 11:46:33 -06002497 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002498 TAttributeMap attributes;
2499 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002500
John Kessenich21472ae2016-06-04 11:46:33 -06002501 // attributed_statement
2502 switch (peek()) {
2503 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002504 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002505
John Kessenich21472ae2016-06-04 11:46:33 -06002506 case EHTokIf:
2507 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002508
John Kessenich21472ae2016-06-04 11:46:33 -06002509 case EHTokSwitch:
2510 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002511
John Kessenich21472ae2016-06-04 11:46:33 -06002512 case EHTokFor:
2513 case EHTokDo:
2514 case EHTokWhile:
2515 return acceptIterationStatement(statement);
2516
2517 case EHTokContinue:
2518 case EHTokBreak:
2519 case EHTokDiscard:
2520 case EHTokReturn:
2521 return acceptJumpStatement(statement);
2522
2523 case EHTokCase:
2524 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002525 case EHTokDefault:
2526 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002527
2528 case EHTokSemicolon:
2529 return acceptTokenClass(EHTokSemicolon);
2530
2531 case EHTokRightBrace:
2532 // Performance: not strictly necessary, but stops a bunch of hunting early,
2533 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002534 return false;
2535
John Kessenich21472ae2016-06-04 11:46:33 -06002536 default:
2537 {
2538 // declaration
2539 if (acceptDeclaration(statement))
2540 return true;
2541
2542 // expression
2543 TIntermTyped* node;
2544 if (acceptExpression(node))
2545 statement = node;
2546 else
2547 return false;
2548
2549 // SEMICOLON (following an expression)
2550 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002551 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002552 return false;
2553 }
2554 }
2555 }
2556
John Kessenich5f934b02016-03-13 17:58:25 -06002557 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002558}
2559
John Kessenich21472ae2016-06-04 11:46:33 -06002560// attributes
2561// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2562//
2563// attribute:
2564// : UNROLL
2565// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2566// | FASTOPT
2567// | ALLOW_UAV_CONDITION
2568// | BRANCH
2569// | FLATTEN
2570// | FORCECASE
2571// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002572// | DOMAIN
2573// | EARLYDEPTHSTENCIL
2574// | INSTANCE
2575// | MAXTESSFACTOR
2576// | OUTPUTCONTROLPOINTS
2577// | OUTPUTTOPOLOGY
2578// | PARTITIONING
2579// | PATCHCONSTANTFUNC
2580// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002581//
steve-lunarg1868b142016-10-20 13:07:10 -06002582void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002583{
steve-lunarg1868b142016-10-20 13:07:10 -06002584 // For now, accept the [ XXX(X) ] syntax, but drop all but
2585 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002586 // TODO: subset to correct set? Pass on?
2587 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002588 HlslToken idToken;
2589
John Kessenich0d2b6de2016-06-05 11:23:11 -06002590 // LEFT_BRACKET?
2591 if (! acceptTokenClass(EHTokLeftBracket))
2592 return;
2593
2594 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002595 if (acceptIdentifier(idToken)) {
2596 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002597 } else if (! peekTokenClass(EHTokRightBracket)) {
2598 expected("identifier");
2599 advanceToken();
2600 }
2601
steve-lunarga22f7db2016-11-11 08:17:44 -07002602 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002603
2604 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002605 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002606 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002607
John Kessenich0d2b6de2016-06-05 11:23:11 -06002608 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002609 bool expectingExpression = false;
steve-lunarg1868b142016-10-20 13:07:10 -06002610
steve-lunarga22f7db2016-11-11 08:17:44 -07002611 while (acceptAssignmentExpression(node)) {
2612 expectingExpression = false;
2613 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002614 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002615 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002616 }
2617
steve-lunarga22f7db2016-11-11 08:17:44 -07002618 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002619 if (! acceptTokenClass(EHTokRightParen))
2620 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002621
2622 // Error for partial or missing expression
2623 if (expectingExpression || expressions->getSequence().empty())
2624 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002625 }
2626
2627 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002628 if (!acceptTokenClass(EHTokRightBracket)) {
2629 expected("]");
2630 return;
2631 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002632
steve-lunarg1868b142016-10-20 13:07:10 -06002633 // Add any values we found into the attribute map. This accepts
2634 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002635 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002636 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002637}
2638
John Kessenich0d2b6de2016-06-05 11:23:11 -06002639// selection_statement
2640// : IF LEFT_PAREN expression RIGHT_PAREN statement
2641// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2642//
John Kessenich21472ae2016-06-04 11:46:33 -06002643bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2644{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002645 TSourceLoc loc = token.loc;
2646
2647 // IF
2648 if (! acceptTokenClass(EHTokIf))
2649 return false;
2650
2651 // so that something declared in the condition is scoped to the lifetimes
2652 // of the then-else statements
2653 parseContext.pushScope();
2654
2655 // LEFT_PAREN expression RIGHT_PAREN
2656 TIntermTyped* condition;
2657 if (! acceptParenExpression(condition))
2658 return false;
2659
2660 // create the child statements
2661 TIntermNodePair thenElse = { nullptr, nullptr };
2662
2663 // then statement
2664 if (! acceptScopedStatement(thenElse.node1)) {
2665 expected("then statement");
2666 return false;
2667 }
2668
2669 // ELSE
2670 if (acceptTokenClass(EHTokElse)) {
2671 // else statement
2672 if (! acceptScopedStatement(thenElse.node2)) {
2673 expected("else statement");
2674 return false;
2675 }
2676 }
2677
2678 // Put the pieces together
2679 statement = intermediate.addSelection(condition, thenElse, loc);
2680 parseContext.popScope();
2681
2682 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002683}
2684
John Kessenichd02dc5d2016-07-01 00:04:11 -06002685// switch_statement
2686// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2687//
John Kessenich21472ae2016-06-04 11:46:33 -06002688bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2689{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002690 // SWITCH
2691 TSourceLoc loc = token.loc;
2692 if (! acceptTokenClass(EHTokSwitch))
2693 return false;
2694
2695 // LEFT_PAREN expression RIGHT_PAREN
2696 parseContext.pushScope();
2697 TIntermTyped* switchExpression;
2698 if (! acceptParenExpression(switchExpression)) {
2699 parseContext.popScope();
2700 return false;
2701 }
2702
2703 // compound_statement
2704 parseContext.pushSwitchSequence(new TIntermSequence);
2705 bool statementOkay = acceptCompoundStatement(statement);
2706 if (statementOkay)
2707 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2708
2709 parseContext.popSwitchSequence();
2710 parseContext.popScope();
2711
2712 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002713}
2714
John Kessenich119f8f62016-06-05 15:44:07 -06002715// iteration_statement
2716// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2717// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2718// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2719//
2720// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002721bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2722{
John Kessenich119f8f62016-06-05 15:44:07 -06002723 TSourceLoc loc = token.loc;
2724 TIntermTyped* condition = nullptr;
2725
2726 EHlslTokenClass loop = peek();
2727 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2728
2729 // WHILE or DO or FOR
2730 advanceToken();
2731
2732 switch (loop) {
2733 case EHTokWhile:
2734 // so that something declared in the condition is scoped to the lifetime
2735 // of the while sub-statement
2736 parseContext.pushScope();
2737 parseContext.nestLooping();
2738
2739 // LEFT_PAREN condition RIGHT_PAREN
2740 if (! acceptParenExpression(condition))
2741 return false;
2742
2743 // statement
2744 if (! acceptScopedStatement(statement)) {
2745 expected("while sub-statement");
2746 return false;
2747 }
2748
2749 parseContext.unnestLooping();
2750 parseContext.popScope();
2751
2752 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2753
2754 return true;
2755
2756 case EHTokDo:
2757 parseContext.nestLooping();
2758
2759 if (! acceptTokenClass(EHTokLeftBrace))
2760 expected("{");
2761
2762 // statement
2763 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2764 expected("do sub-statement");
2765 return false;
2766 }
2767
2768 if (! acceptTokenClass(EHTokRightBrace))
2769 expected("}");
2770
2771 // WHILE
2772 if (! acceptTokenClass(EHTokWhile)) {
2773 expected("while");
2774 return false;
2775 }
2776
2777 // LEFT_PAREN condition RIGHT_PAREN
2778 TIntermTyped* condition;
2779 if (! acceptParenExpression(condition))
2780 return false;
2781
2782 if (! acceptTokenClass(EHTokSemicolon))
2783 expected(";");
2784
2785 parseContext.unnestLooping();
2786
2787 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2788
2789 return true;
2790
2791 case EHTokFor:
2792 {
2793 // LEFT_PAREN
2794 if (! acceptTokenClass(EHTokLeftParen))
2795 expected("(");
2796
2797 // so that something declared in the condition is scoped to the lifetime
2798 // of the for sub-statement
2799 parseContext.pushScope();
2800
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002801 // initializer
2802 TIntermNode* initNode = nullptr;
2803 if (! acceptControlDeclaration(initNode)) {
2804 TIntermTyped* initExpr = nullptr;
2805 acceptExpression(initExpr);
2806 initNode = initExpr;
2807 }
2808 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002809 if (! acceptTokenClass(EHTokSemicolon))
2810 expected(";");
2811
2812 parseContext.nestLooping();
2813
2814 // condition SEMI_COLON
2815 acceptExpression(condition);
2816 if (! acceptTokenClass(EHTokSemicolon))
2817 expected(";");
2818
2819 // iterator SEMI_COLON
2820 TIntermTyped* iterator = nullptr;
2821 acceptExpression(iterator);
2822 if (! acceptTokenClass(EHTokRightParen))
2823 expected(")");
2824
2825 // statement
2826 if (! acceptScopedStatement(statement)) {
2827 expected("for sub-statement");
2828 return false;
2829 }
2830
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002831 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002832
2833 parseContext.popScope();
2834 parseContext.unnestLooping();
2835
2836 return true;
2837 }
2838
2839 default:
2840 return false;
2841 }
John Kessenich21472ae2016-06-04 11:46:33 -06002842}
2843
2844// jump_statement
2845// : CONTINUE SEMICOLON
2846// | BREAK SEMICOLON
2847// | DISCARD SEMICOLON
2848// | RETURN SEMICOLON
2849// | RETURN expression SEMICOLON
2850//
2851bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2852{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002853 EHlslTokenClass jump = peek();
2854 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002855 case EHTokContinue:
2856 case EHTokBreak:
2857 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002858 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002859 advanceToken();
2860 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002861 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002862 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002863 return false;
2864 }
John Kessenich21472ae2016-06-04 11:46:33 -06002865
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002866 switch (jump) {
2867 case EHTokContinue:
2868 statement = intermediate.addBranch(EOpContinue, token.loc);
2869 break;
2870 case EHTokBreak:
2871 statement = intermediate.addBranch(EOpBreak, token.loc);
2872 break;
2873 case EHTokDiscard:
2874 statement = intermediate.addBranch(EOpKill, token.loc);
2875 break;
2876
2877 case EHTokReturn:
2878 {
2879 // expression
2880 TIntermTyped* node;
2881 if (acceptExpression(node)) {
2882 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002883 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002884 } else
2885 statement = intermediate.addBranch(EOpReturn, token.loc);
2886 break;
2887 }
2888
2889 default:
2890 assert(0);
2891 return false;
2892 }
2893
2894 // SEMICOLON
2895 if (! acceptTokenClass(EHTokSemicolon))
2896 expected(";");
2897
2898 return true;
2899}
John Kessenich21472ae2016-06-04 11:46:33 -06002900
John Kessenichd02dc5d2016-07-01 00:04:11 -06002901// case_label
2902// : CASE expression COLON
2903//
John Kessenich21472ae2016-06-04 11:46:33 -06002904bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2905{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002906 TSourceLoc loc = token.loc;
2907 if (! acceptTokenClass(EHTokCase))
2908 return false;
2909
2910 TIntermTyped* expression;
2911 if (! acceptExpression(expression)) {
2912 expected("case expression");
2913 return false;
2914 }
2915
2916 if (! acceptTokenClass(EHTokColon)) {
2917 expected(":");
2918 return false;
2919 }
2920
2921 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2922
2923 return true;
2924}
2925
2926// default_label
2927// : DEFAULT COLON
2928//
2929bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2930{
2931 TSourceLoc loc = token.loc;
2932 if (! acceptTokenClass(EHTokDefault))
2933 return false;
2934
2935 if (! acceptTokenClass(EHTokColon)) {
2936 expected(":");
2937 return false;
2938 }
2939
2940 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2941
2942 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002943}
2944
John Kessenich19b92ff2016-06-19 11:50:34 -06002945// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06002946// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
2947// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002948//
2949void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2950{
2951 arraySizes = nullptr;
2952
steve-lunarg7b211a32016-10-13 12:26:18 -06002953 // Early-out if there aren't any array dimensions
2954 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06002955 return;
2956
steve-lunarg7b211a32016-10-13 12:26:18 -06002957 // 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 -06002958 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06002959
2960 // Collect each array dimension.
2961 while (acceptTokenClass(EHTokLeftBracket)) {
2962 TSourceLoc loc = token.loc;
2963 TIntermTyped* sizeExpr = nullptr;
2964
2965 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
2966 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
2967
2968 if (! acceptTokenClass(EHTokRightBracket)) {
2969 expected("]");
2970 return;
2971 }
2972
2973 if (hasArraySize) {
2974 TArraySize arraySize;
2975 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2976 arraySizes->addInnerSize(arraySize);
2977 } else {
2978 arraySizes->addInnerSize(0); // sized by initializers.
2979 }
steve-lunarg265c0612016-09-27 10:57:35 -06002980 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002981}
2982
John Kessenich630dd7d2016-06-12 23:52:12 -06002983// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002984// : COLON semantic // optional
2985// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2986// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002987// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002988// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002989//
John Kessenich7735b942016-09-05 12:40:06 -06002990void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002991{
John Kessenich630dd7d2016-06-12 23:52:12 -06002992 do {
2993 // COLON
2994 if (acceptTokenClass(EHTokColon)) {
2995 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002996 if (peekTokenClass(EHTokLayout))
2997 acceptLayoutQualifierList(qualifier);
2998 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002999 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003000 if (! acceptTokenClass(EHTokLeftParen)) {
3001 expected("(");
3002 return;
3003 }
John Kessenich82d6baf2016-07-29 13:03:05 -06003004 HlslToken locationToken;
3005 if (! acceptIdentifier(locationToken)) {
3006 expected("c[subcomponent][.component]");
3007 return;
3008 }
3009 HlslToken componentToken;
3010 if (acceptTokenClass(EHTokDot)) {
3011 if (! acceptIdentifier(componentToken)) {
3012 expected("component");
3013 return;
3014 }
3015 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003016 if (! acceptTokenClass(EHTokRightParen)) {
3017 expected(")");
3018 break;
3019 }
John Kessenich7735b942016-09-05 12:40:06 -06003020 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003021 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003022 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06003023 return;
3024 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003025 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3026 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003027 if (! acceptTokenClass(EHTokLeftParen)) {
3028 expected("(");
3029 return;
3030 }
John Kessenichb38f0712016-07-30 10:29:54 -06003031 HlslToken registerDesc; // for Type#
3032 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003033 if (! acceptIdentifier(registerDesc)) {
3034 expected("register number description");
3035 return;
3036 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003037 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3038 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003039 // Then we didn't really see the registerDesc yet, it was
3040 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003041 profile = registerDesc;
3042 if (! acceptIdentifier(registerDesc)) {
3043 expected("register number description");
3044 return;
3045 }
3046 }
John Kessenichb38f0712016-07-30 10:29:54 -06003047 int subComponent = 0;
3048 if (acceptTokenClass(EHTokLeftBracket)) {
3049 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3050 if (! peekTokenClass(EHTokIntConstant)) {
3051 expected("literal integer");
3052 return;
3053 }
3054 subComponent = token.i;
3055 advanceToken();
3056 if (! acceptTokenClass(EHTokRightBracket)) {
3057 expected("]");
3058 break;
3059 }
3060 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003061 // (COMMA SPACEN)opt
3062 HlslToken spaceDesc;
3063 if (acceptTokenClass(EHTokComma)) {
3064 if (! acceptIdentifier(spaceDesc)) {
3065 expected ("space identifier");
3066 return;
3067 }
3068 }
3069 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003070 if (! acceptTokenClass(EHTokRightParen)) {
3071 expected(")");
3072 break;
3073 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003074 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003075 } else {
3076 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003077 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003078 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003079 } else if (peekTokenClass(EHTokLeftAngle))
3080 acceptAnnotations(qualifier);
3081 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003082 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003083
John Kessenich630dd7d2016-06-12 23:52:12 -06003084 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003085}
3086
John Kesseniche01a9bc2016-03-12 20:11:22 -07003087} // end namespace glslang