blob: e676e95e104410b567ee47657a9e5065ebe6466f [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)) {
93 idToken.string = NewPoolTString("sample");
94 idToken.tokenClass = EHTokIdentifier;
95 idToken.symbol = nullptr;
96 idToken.loc = token.loc;
97 advanceToken();
98 return true;
99 }
100
John Kessenichaecd4972016-03-14 10:46:34 -0600101 return false;
102}
103
John Kesseniche01a9bc2016-03-12 20:11:22 -0700104// compilationUnit
105// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -0600106// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -0700107//
108bool HlslGrammar::acceptCompilationUnit()
109{
John Kessenichd016be12016-03-13 11:24:20 -0600110 TIntermNode* unitNode = nullptr;
111
John Kessenich9c86c6a2016-05-03 22:49:24 -0600112 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -0600113 // HLSL allows semicolons between global declarations, e.g, between functions.
114 if (acceptTokenClass(EHTokSemicolon))
115 continue;
116
John Kessenichd016be12016-03-13 11:24:20 -0600117 // externalDeclaration
118 TIntermNode* declarationNode;
119 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700120 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600121
122 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600123 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700124 }
125
John Kessenichd016be12016-03-13 11:24:20 -0600126 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600127 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600128
John Kesseniche01a9bc2016-03-12 20:11:22 -0700129 return true;
130}
131
LoopDawg4886f692016-06-29 10:58:58 -0600132// sampler_state
133// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
134//
135// sampler_state_assignment
136// : sampler_state_identifier EQUAL value SEMICOLON
137//
138// sampler_state_identifier
139// : ADDRESSU
140// | ADDRESSV
141// | ADDRESSW
142// | BORDERCOLOR
143// | FILTER
144// | MAXANISOTROPY
145// | MAXLOD
146// | MINLOD
147// | MIPLODBIAS
148//
149bool HlslGrammar::acceptSamplerState()
150{
151 // TODO: this should be genericized to accept a list of valid tokens and
152 // return token/value pairs. Presently it is specific to texture values.
153
154 if (! acceptTokenClass(EHTokLeftBrace))
155 return true;
156
157 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
158
159 do {
160 // read state name
161 HlslToken state;
162 if (! acceptIdentifier(state))
163 break; // end of list
164
165 // FXC accepts any case
166 TString stateName = *state.string;
167 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
168
169 if (! acceptTokenClass(EHTokAssign)) {
170 expected("assign");
171 return false;
172 }
173
174 if (stateName == "minlod" || stateName == "maxlod") {
175 if (! peekTokenClass(EHTokIntConstant)) {
176 expected("integer");
177 return false;
178 }
179
180 TIntermTyped* lod = nullptr;
181 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
182 return false;
183 } else if (stateName == "maxanisotropy") {
184 if (! peekTokenClass(EHTokIntConstant)) {
185 expected("integer");
186 return false;
187 }
188
189 TIntermTyped* maxAnisotropy = nullptr;
190 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
191 return false;
192 } else if (stateName == "filter") {
193 HlslToken filterMode;
194 if (! acceptIdentifier(filterMode)) {
195 expected("filter mode");
196 return false;
197 }
198 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
199 HlslToken addrMode;
200 if (! acceptIdentifier(addrMode)) {
201 expected("texture address mode");
202 return false;
203 }
204 } else if (stateName == "miplodbias") {
205 TIntermTyped* lodBias = nullptr;
206 if (! acceptLiteral(lodBias)) {
207 expected("lod bias");
208 return false;
209 }
210 } else if (stateName == "bordercolor") {
211 return false;
212 } else {
213 expected("texture state");
214 return false;
215 }
216
217 // SEMICOLON
218 if (! acceptTokenClass(EHTokSemicolon)) {
219 expected("semicolon");
220 return false;
221 }
222 } while (true);
223
224 if (! acceptTokenClass(EHTokRightBrace))
225 return false;
226
227 return true;
228}
229
230// sampler_declaration_dx9
231// : SAMPLER identifier EQUAL sampler_type sampler_state
232//
John Kesseniche4821e42016-07-16 10:19:43 -0600233bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600234{
235 if (! acceptTokenClass(EHTokSampler))
236 return false;
237
238 // TODO: remove this when DX9 style declarations are implemented.
239 unimplemented("Direct3D 9 sampler declaration");
240
241 // read sampler name
242 HlslToken name;
243 if (! acceptIdentifier(name)) {
244 expected("sampler name");
245 return false;
246 }
247
248 if (! acceptTokenClass(EHTokAssign)) {
249 expected("=");
250 return false;
251 }
252
253 return false;
254}
255
256
John Kesseniche01a9bc2016-03-12 20:11:22 -0700257// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600258// : sampler_declaration_dx9 post_decls SEMICOLON
259// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600260// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600261// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600262// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700263//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600264// declarator_list
265// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600266//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600267// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600268// : identifier array_specifier post_decls
269// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600270// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600271//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600272// Parsing has to go pretty far in to know whether it's a variable, prototype, or
273// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600274// as above. (The 'identifier' in the first item in init_declarator list is the
275// same as 'identifier' for function declarations.)
276//
277// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600278// or a function body.
279//
280bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700281{
John Kessenichd016be12016-03-13 11:24:20 -0600282 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600283 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600284
steve-lunarg1868b142016-10-20 13:07:10 -0600285 // attributes
286 TAttributeMap attributes;
287 acceptAttributes(attributes);
288
John Kessenich5e69ec62016-07-05 00:02:40 -0600289 // typedef
290 bool typedefDecl = acceptTokenClass(EHTokTypedef);
291
John Kesseniche82061d2016-09-27 14:38:57 -0600292 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600293
294 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600295 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
296 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
297 // HLSL shaders, this will have to be a master level switch
298 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
299 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400300
John Kesseniche82061d2016-09-27 14:38:57 -0600301 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400302 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600303
304 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600305 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700306 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600307
John Kessenich87142c72016-03-12 20:24:24 -0700308 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600309 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600310 while (acceptIdentifier(idToken)) {
steve-lunargf1e0c872016-10-31 15:13:43 -0600311 TString* fnName = idToken.string;
312
313 // Potentially rename shader entry point function. No-op most of the time.
314 parseContext.renameShaderFunction(fnName);
315
John Kessenich5f934b02016-03-13 17:58:25 -0600316 // function_parameters
steve-lunargf1e0c872016-10-31 15:13:43 -0600317 TFunction& function = *new TFunction(fnName, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600318 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600319 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600320 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600321
John Kessenichd5ed0b62016-07-04 17:32:45 -0600322 // compound_statement (function body definition) or just a prototype?
323 if (peekTokenClass(EHTokLeftBrace)) {
324 if (list)
325 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600326 if (typedefDecl)
327 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
steve-lunarg1868b142016-10-20 13:07:10 -0600328 return acceptFunctionDefinition(function, node, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600329 } else {
330 if (typedefDecl)
331 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600332 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600333 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600334 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600335 // A variable declaration. Fix the storage qualifier if it's a global.
336 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
337 declaredType.getQualifier().storage = EvqUniform;
338
John Kesseniche82061d2016-09-27 14:38:57 -0600339 // We can handle multiple variables per type declaration, so
340 // the number of types can expand when arrayness is different.
341 TType variableType;
342 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600343
John Kesseniche82061d2016-09-27 14:38:57 -0600344 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600345 TArraySizes* arraySizes = nullptr;
346 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600347
John Kesseniche82061d2016-09-27 14:38:57 -0600348 // Fix arrayness in the variableType
349 if (declaredType.isImplicitlySizedArray()) {
350 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
351 // of different sizes, for this case sharing the shallow copy of arrayness
352 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
353 variableType.newArraySizes(declaredType.getArraySizes());
354 }
355 if (arraySizes || variableType.isArray()) {
356 // In the most general case, arrayness is potentially coming both from the
357 // declared type and from the variable: "int[] a[];" or just one or the other.
358 // Merge it all to the variableType, so all arrayness is part of the variableType.
359 parseContext.arrayDimMerge(variableType, arraySizes);
360 }
361
LoopDawg4886f692016-06-29 10:58:58 -0600362 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600363 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600364 if (! acceptSamplerState())
365 return false;
366 }
367
John Kessenichd5ed0b62016-07-04 17:32:45 -0600368 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600369 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600370
371 // EQUAL assignment_expression
372 TIntermTyped* expressionNode = nullptr;
373 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600374 if (typedefDecl)
375 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600376 if (! acceptAssignmentExpression(expressionNode)) {
377 expected("initializer");
378 return false;
379 }
380 }
381
John Kessenich6dbc0a72016-09-27 19:13:05 -0600382 // Hand off the actual declaration
383
384 // TODO: things scoped within an annotation need their own name space;
385 // TODO: strings are not yet handled.
386 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
387 if (typedefDecl)
388 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
389 else if (variableType.getBasicType() == EbtBlock)
390 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
391 else {
steve-lunarga2b01a02016-11-28 17:09:54 -0700392 if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600393 // this isn't really an individual variable, but a member of the $Global buffer
394 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
395 } else {
396 // Declare the variable and add any initializer code to the AST.
397 // The top-level node is always made into an aggregate, as that's
398 // historically how the AST has been.
399 node = intermediate.growAggregate(node,
400 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
401 expressionNode),
402 idToken.loc);
403 }
404 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600405 }
John Kessenich5f934b02016-03-13 17:58:25 -0600406 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600407
408 if (acceptTokenClass(EHTokComma)) {
409 list = true;
410 continue;
411 }
412 };
413
414 // The top-level node is a sequence.
415 if (node != nullptr)
416 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700417
John Kessenich078d7f22016-03-14 10:02:11 -0600418 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600419 if (! acceptTokenClass(EHTokSemicolon)) {
420 expected(";");
421 return false;
422 }
423
John Kesseniche01a9bc2016-03-12 20:11:22 -0700424 return true;
425}
426
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600427// control_declaration
428// : fully_specified_type identifier EQUAL expression
429//
430bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
431{
432 node = nullptr;
433
434 // fully_specified_type
435 TType type;
436 if (! acceptFullySpecifiedType(type))
437 return false;
438
439 // identifier
440 HlslToken idToken;
441 if (! acceptIdentifier(idToken)) {
442 expected("identifier");
443 return false;
444 }
445
446 // EQUAL
447 TIntermTyped* expressionNode = nullptr;
448 if (! acceptTokenClass(EHTokAssign)) {
449 expected("=");
450 return false;
451 }
452
453 // expression
454 if (! acceptExpression(expressionNode)) {
455 expected("initializer");
456 return false;
457 }
458
John Kesseniche82061d2016-09-27 14:38:57 -0600459 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600460
461 return true;
462}
463
John Kessenich87142c72016-03-12 20:24:24 -0700464// fully_specified_type
465// : type_specifier
466// | type_qualifier type_specifier
467//
468bool HlslGrammar::acceptFullySpecifiedType(TType& type)
469{
470 // type_qualifier
471 TQualifier qualifier;
472 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600473 if (! acceptQualifier(qualifier))
474 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600475 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700476
477 // type_specifier
478 if (! acceptType(type))
479 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600480 if (type.getBasicType() == EbtBlock) {
481 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600482 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600483 // further, it can create an anonymous instance of the block
484 if (peekTokenClass(EHTokSemicolon))
485 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600486 } else {
487 // Some qualifiers are set when parsing the type. Merge those with
488 // whatever comes from acceptQualifier.
489 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700490
steve-lunargbb0183f2016-10-04 16:58:14 -0600491 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600492 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700493
494 if (type.getQualifier().storage == EvqVaryingOut)
495 qualifier.storage = type.getQualifier().storage;
496
497 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600498 }
John Kessenich87142c72016-03-12 20:24:24 -0700499
500 return true;
501}
502
John Kessenich630dd7d2016-06-12 23:52:12 -0600503// type_qualifier
504// : qualifier qualifier ...
505//
506// Zero or more of these, so this can't return false.
507//
John Kessenichb9e39122016-08-17 10:22:08 -0600508bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700509{
John Kessenich630dd7d2016-06-12 23:52:12 -0600510 do {
511 switch (peek()) {
512 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600513 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600514 break;
515 case EHTokExtern:
516 // TODO: no meaning in glslang?
517 break;
518 case EHTokShared:
519 // TODO: hint
520 break;
521 case EHTokGroupShared:
522 qualifier.storage = EvqShared;
523 break;
524 case EHTokUniform:
525 qualifier.storage = EvqUniform;
526 break;
527 case EHTokConst:
528 qualifier.storage = EvqConst;
529 break;
530 case EHTokVolatile:
531 qualifier.volatil = true;
532 break;
533 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600534 qualifier.smooth = true;
535 break;
536 case EHTokCentroid:
537 qualifier.centroid = true;
538 break;
539 case EHTokNointerpolation:
540 qualifier.flat = true;
541 break;
542 case EHTokNoperspective:
543 qualifier.nopersp = true;
544 break;
545 case EHTokSample:
546 qualifier.sample = true;
547 break;
548 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600549 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600550 break;
551 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600552 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600553 break;
554 case EHTokPrecise:
555 qualifier.noContraction = true;
556 break;
LoopDawg9249c702016-07-12 20:44:32 -0600557 case EHTokIn:
558 qualifier.storage = EvqIn;
559 break;
560 case EHTokOut:
561 qualifier.storage = EvqOut;
562 break;
563 case EHTokInOut:
564 qualifier.storage = EvqInOut;
565 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600566 case EHTokLayout:
567 if (! acceptLayoutQualifierList(qualifier))
568 return false;
569 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700570
571 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
572 // for output variables.
573 case EHTokPoint:
574 qualifier.storage = EvqIn;
575 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
576 return false;
577 break;
578 case EHTokLine:
579 qualifier.storage = EvqIn;
580 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
581 return false;
582 break;
583 case EHTokTriangle:
584 qualifier.storage = EvqIn;
585 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
586 return false;
587 break;
588 case EHTokLineAdj:
589 qualifier.storage = EvqIn;
590 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
591 return false;
592 break;
593 case EHTokTriangleAdj:
594 qualifier.storage = EvqIn;
595 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
596 return false;
597 break;
598
John Kessenich630dd7d2016-06-12 23:52:12 -0600599 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600600 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600601 }
602 advanceToken();
603 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700604}
605
John Kessenichb9e39122016-08-17 10:22:08 -0600606// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600607// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600608//
609// layout_qualifier
610// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600611// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600612//
613// Zero or more of these, so this can't return false.
614//
615bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
616{
617 if (! acceptTokenClass(EHTokLayout))
618 return false;
619
620 // LEFT_PAREN
621 if (! acceptTokenClass(EHTokLeftParen))
622 return false;
623
624 do {
625 // identifier
626 HlslToken idToken;
627 if (! acceptIdentifier(idToken))
628 break;
629
630 // EQUAL expression
631 if (acceptTokenClass(EHTokAssign)) {
632 TIntermTyped* expr;
633 if (! acceptConditionalExpression(expr)) {
634 expected("expression");
635 return false;
636 }
637 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
638 } else
639 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
640
641 // COMMA
642 if (! acceptTokenClass(EHTokComma))
643 break;
644 } while (true);
645
646 // RIGHT_PAREN
647 if (! acceptTokenClass(EHTokRightParen)) {
648 expected(")");
649 return false;
650 }
651
652 return true;
653}
654
LoopDawg6daaa4f2016-06-23 19:13:48 -0600655// template_type
656// : FLOAT
657// | DOUBLE
658// | INT
659// | DWORD
660// | UINT
661// | BOOL
662//
steve-lunargf49cdf42016-11-17 15:04:20 -0700663bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600664{
665 switch (peek()) {
666 case EHTokFloat:
667 basicType = EbtFloat;
668 break;
669 case EHTokDouble:
670 basicType = EbtDouble;
671 break;
672 case EHTokInt:
673 case EHTokDword:
674 basicType = EbtInt;
675 break;
676 case EHTokUint:
677 basicType = EbtUint;
678 break;
679 case EHTokBool:
680 basicType = EbtBool;
681 break;
682 default:
683 return false;
684 }
685
686 advanceToken();
687
688 return true;
689}
690
691// vector_template_type
692// : VECTOR
693// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
694//
695bool HlslGrammar::acceptVectorTemplateType(TType& type)
696{
697 if (! acceptTokenClass(EHTokVector))
698 return false;
699
700 if (! acceptTokenClass(EHTokLeftAngle)) {
701 // in HLSL, 'vector' alone means float4.
702 new(&type) TType(EbtFloat, EvqTemporary, 4);
703 return true;
704 }
705
706 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700707 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600708 expected("scalar type");
709 return false;
710 }
711
712 // COMMA
713 if (! acceptTokenClass(EHTokComma)) {
714 expected(",");
715 return false;
716 }
717
718 // integer
719 if (! peekTokenClass(EHTokIntConstant)) {
720 expected("literal integer");
721 return false;
722 }
723
724 TIntermTyped* vecSize;
725 if (! acceptLiteral(vecSize))
726 return false;
727
728 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
729
730 new(&type) TType(basicType, EvqTemporary, vecSizeI);
731
732 if (vecSizeI == 1)
733 type.makeVector();
734
735 if (!acceptTokenClass(EHTokRightAngle)) {
736 expected("right angle bracket");
737 return false;
738 }
739
740 return true;
741}
742
743// matrix_template_type
744// : MATRIX
745// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
746//
747bool HlslGrammar::acceptMatrixTemplateType(TType& type)
748{
749 if (! acceptTokenClass(EHTokMatrix))
750 return false;
751
752 if (! acceptTokenClass(EHTokLeftAngle)) {
753 // in HLSL, 'matrix' alone means float4x4.
754 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
755 return true;
756 }
757
758 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700759 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600760 expected("scalar type");
761 return false;
762 }
763
764 // COMMA
765 if (! acceptTokenClass(EHTokComma)) {
766 expected(",");
767 return false;
768 }
769
770 // integer rows
771 if (! peekTokenClass(EHTokIntConstant)) {
772 expected("literal integer");
773 return false;
774 }
775
776 TIntermTyped* rows;
777 if (! acceptLiteral(rows))
778 return false;
779
780 // COMMA
781 if (! acceptTokenClass(EHTokComma)) {
782 expected(",");
783 return false;
784 }
785
786 // integer cols
787 if (! peekTokenClass(EHTokIntConstant)) {
788 expected("literal integer");
789 return false;
790 }
791
792 TIntermTyped* cols;
793 if (! acceptLiteral(cols))
794 return false;
795
796 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600797 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
798 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600799
800 if (!acceptTokenClass(EHTokRightAngle)) {
801 expected("right angle bracket");
802 return false;
803 }
804
805 return true;
806}
807
steve-lunargf49cdf42016-11-17 15:04:20 -0700808// layout_geometry
809// : LINESTREAM
810// | POINTSTREAM
811// | TRIANGLESTREAM
812//
813bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
814{
815 // read geometry type
816 const EHlslTokenClass geometryType = peek();
817
818 switch (geometryType) {
819 case EHTokPointStream: geometry = ElgPoints; break;
820 case EHTokLineStream: geometry = ElgLineStrip; break;
821 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
822 default:
823 return false; // not a layout geometry
824 }
825
826 advanceToken(); // consume the layout keyword
827 return true;
828}
829
830// stream_out_template_type
831// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
832//
833bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
834{
835 geometry = ElgNone;
836
837 if (! acceptOutputPrimitiveGeometry(geometry))
838 return false;
839
840 if (! acceptTokenClass(EHTokLeftAngle))
841 return false;
842
843 if (! acceptType(type)) {
844 expected("stream output type");
845 return false;
846 }
847
848 type.getQualifier().storage = EvqVaryingOut;
849
850 if (! acceptTokenClass(EHTokRightAngle)) {
851 expected("right angle bracket");
852 return false;
853 }
854
855 return true;
856}
857
John Kessenicha1e2d492016-09-20 13:22:58 -0600858// annotations
859// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600860//
John Kessenicha1e2d492016-09-20 13:22:58 -0600861bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600862{
John Kessenicha1e2d492016-09-20 13:22:58 -0600863 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600864 return false;
865
John Kessenicha1e2d492016-09-20 13:22:58 -0600866 // note that we are nesting a name space
867 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600868
869 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
870 do {
871 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
872 while (acceptTokenClass(EHTokSemicolon))
873 ;
874
875 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600876 break;
John Kessenich86f71382016-09-19 20:23:18 -0600877
878 // declaration
879 TIntermNode* node;
880 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600881 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600882 return false;
883 }
884 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600885
886 parseContext.unnestAnnotations();
887 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600888}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600889
LoopDawg4886f692016-06-29 10:58:58 -0600890// sampler_type
891// : SAMPLER
892// | SAMPLER1D
893// | SAMPLER2D
894// | SAMPLER3D
895// | SAMPLERCUBE
896// | SAMPLERSTATE
897// | SAMPLERCOMPARISONSTATE
898bool HlslGrammar::acceptSamplerType(TType& type)
899{
900 // read sampler type
901 const EHlslTokenClass samplerType = peek();
902
LoopDawga78b0292016-07-19 14:28:05 -0600903 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600904 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600905
LoopDawga78b0292016-07-19 14:28:05 -0600906 bool isShadow = false;
907
LoopDawg4886f692016-06-29 10:58:58 -0600908 switch (samplerType) {
909 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600910 case EHTokSampler1d: /*dim = Esd1D*/; break;
911 case EHTokSampler2d: /*dim = Esd2D*/; break;
912 case EHTokSampler3d: /*dim = Esd3D*/; break;
913 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600914 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600915 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600916 default:
917 return false; // not a sampler declaration
918 }
919
920 advanceToken(); // consume the sampler type keyword
921
922 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600923
924 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600925 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600926
927 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
928
929 return true;
930}
931
932// texture_type
933// | BUFFER
934// | TEXTURE1D
935// | TEXTURE1DARRAY
936// | TEXTURE2D
937// | TEXTURE2DARRAY
938// | TEXTURE3D
939// | TEXTURECUBE
940// | TEXTURECUBEARRAY
941// | TEXTURE2DMS
942// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600943// | RWBUFFER
944// | RWTEXTURE1D
945// | RWTEXTURE1DARRAY
946// | RWTEXTURE2D
947// | RWTEXTURE2DARRAY
948// | RWTEXTURE3D
949
LoopDawg4886f692016-06-29 10:58:58 -0600950bool HlslGrammar::acceptTextureType(TType& type)
951{
952 const EHlslTokenClass textureType = peek();
953
954 TSamplerDim dim = EsdNone;
955 bool array = false;
956 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600957 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600958
959 switch (textureType) {
960 case EHTokBuffer: dim = EsdBuffer; break;
961 case EHTokTexture1d: dim = Esd1D; break;
962 case EHTokTexture1darray: dim = Esd1D; array = true; break;
963 case EHTokTexture2d: dim = Esd2D; break;
964 case EHTokTexture2darray: dim = Esd2D; array = true; break;
965 case EHTokTexture3d: dim = Esd3D; break;
966 case EHTokTextureCube: dim = EsdCube; break;
967 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
968 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
969 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -0600970 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
971 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
972 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
973 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
974 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
975 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600976 default:
977 return false; // not a texture declaration
978 }
979
980 advanceToken(); // consume the texture object keyword
981
982 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
983
984 TIntermTyped* msCount = nullptr;
985
steve-lunargbb0183f2016-10-04 16:58:14 -0600986 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -0600987 if (acceptTokenClass(EHTokLeftAngle)) {
988 if (! acceptType(txType)) {
989 expected("scalar or vector type");
990 return false;
991 }
992
993 const TBasicType basicRetType = txType.getBasicType() ;
994
995 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
996 unimplemented("basic type in texture");
997 return false;
998 }
999
steve-lunargd53f7172016-07-27 15:46:48 -06001000 // Buffers can handle small mats if they fit in 4 components
1001 if (dim == EsdBuffer && txType.isMatrix()) {
1002 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1003 expected("components < 4 in matrix buffer type");
1004 return false;
1005 }
1006
1007 // TODO: except we don't handle it yet...
1008 unimplemented("matrix type in buffer");
1009 return false;
1010 }
1011
LoopDawg4886f692016-06-29 10:58:58 -06001012 if (!txType.isScalar() && !txType.isVector()) {
1013 expected("scalar or vector type");
1014 return false;
1015 }
1016
LoopDawg4886f692016-06-29 10:58:58 -06001017 if (ms && acceptTokenClass(EHTokComma)) {
1018 // read sample count for multisample types, if given
1019 if (! peekTokenClass(EHTokIntConstant)) {
1020 expected("multisample count");
1021 return false;
1022 }
1023
1024 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1025 return false;
1026 }
1027
1028 if (! acceptTokenClass(EHTokRightAngle)) {
1029 expected("right angle bracket");
1030 return false;
1031 }
1032 } else if (ms) {
1033 expected("texture type for multisample");
1034 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001035 } else if (image) {
1036 expected("type for RWTexture/RWBuffer");
1037 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001038 }
1039
1040 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001041 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001042
1043 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001044 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001045
steve-lunarg4f2da272016-10-10 15:24:57 -06001046 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1047 if (image || dim == EsdBuffer)
1048 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001049
1050 // Non-image Buffers are combined
1051 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001052 sampler.set(txType.getBasicType(), dim, array);
1053 } else {
1054 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001055 if (image) {
1056 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1057 } else {
1058 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1059 }
steve-lunargd53f7172016-07-27 15:46:48 -06001060 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001061
1062 // Remember the declared vector size.
1063 sampler.vectorSize = txType.getVectorSize();
LoopDawg4886f692016-06-29 10:58:58 -06001064
1065 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001066 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001067
1068 return true;
1069}
1070
1071
John Kessenich87142c72016-03-12 20:24:24 -07001072// If token is for a type, update 'type' with the type information,
1073// and return true and advance.
1074// Otherwise, return false, and don't advance
1075bool HlslGrammar::acceptType(TType& type)
1076{
steve-lunarg3226b082016-10-26 19:18:55 -06001077 // Basic types for min* types, broken out here in case of future
1078 // changes, e.g, to use native halfs.
1079 static const TBasicType min16float_bt = EbtFloat;
1080 static const TBasicType min10float_bt = EbtFloat;
1081 static const TBasicType min16int_bt = EbtInt;
1082 static const TBasicType min12int_bt = EbtInt;
1083 static const TBasicType min16uint_bt = EbtUint;
1084
John Kessenich9c86c6a2016-05-03 22:49:24 -06001085 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001086 case EHTokVector:
1087 return acceptVectorTemplateType(type);
1088 break;
1089
1090 case EHTokMatrix:
1091 return acceptMatrixTemplateType(type);
1092 break;
1093
steve-lunargf49cdf42016-11-17 15:04:20 -07001094 case EHTokPointStream: // fall through
1095 case EHTokLineStream: // ...
1096 case EHTokTriangleStream: // ...
1097 {
1098 TLayoutGeometry geometry;
1099 if (! acceptStreamOutTemplateType(type, geometry))
1100 return false;
1101
1102 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1103 return false;
1104
1105 return true;
1106 }
1107
LoopDawg4886f692016-06-29 10:58:58 -06001108 case EHTokSampler: // fall through
1109 case EHTokSampler1d: // ...
1110 case EHTokSampler2d: // ...
1111 case EHTokSampler3d: // ...
1112 case EHTokSamplerCube: // ...
1113 case EHTokSamplerState: // ...
1114 case EHTokSamplerComparisonState: // ...
1115 return acceptSamplerType(type);
1116 break;
1117
1118 case EHTokBuffer: // fall through
1119 case EHTokTexture1d: // ...
1120 case EHTokTexture1darray: // ...
1121 case EHTokTexture2d: // ...
1122 case EHTokTexture2darray: // ...
1123 case EHTokTexture3d: // ...
1124 case EHTokTextureCube: // ...
1125 case EHTokTextureCubearray: // ...
1126 case EHTokTexture2DMS: // ...
1127 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001128 case EHTokRWTexture1d: // ...
1129 case EHTokRWTexture1darray: // ...
1130 case EHTokRWTexture2d: // ...
1131 case EHTokRWTexture2darray: // ...
1132 case EHTokRWTexture3d: // ...
1133 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001134 return acceptTextureType(type);
1135 break;
1136
John Kesseniche6e74942016-06-11 16:43:14 -06001137 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001138 case EHTokCBuffer:
1139 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001140 return acceptStruct(type);
1141 break;
1142
1143 case EHTokIdentifier:
1144 // An identifier could be for a user-defined type.
1145 // Note we cache the symbol table lookup, to save for a later rule
1146 // when this is not a type.
1147 token.symbol = parseContext.symbolTable.find(*token.string);
1148 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1149 type.shallowCopy(token.symbol->getType());
1150 advanceToken();
1151 return true;
1152 } else
1153 return false;
1154
John Kessenich71351de2016-06-08 12:50:56 -06001155 case EHTokVoid:
1156 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001157 break;
John Kessenich71351de2016-06-08 12:50:56 -06001158
John Kessenicha1e2d492016-09-20 13:22:58 -06001159 case EHTokString:
1160 new(&type) TType(EbtString);
1161 break;
1162
John Kessenich87142c72016-03-12 20:24:24 -07001163 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001164 new(&type) TType(EbtFloat);
1165 break;
John Kessenich87142c72016-03-12 20:24:24 -07001166 case EHTokFloat1:
1167 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001168 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001169 break;
John Kessenich87142c72016-03-12 20:24:24 -07001170 case EHTokFloat2:
1171 new(&type) TType(EbtFloat, EvqTemporary, 2);
1172 break;
1173 case EHTokFloat3:
1174 new(&type) TType(EbtFloat, EvqTemporary, 3);
1175 break;
1176 case EHTokFloat4:
1177 new(&type) TType(EbtFloat, EvqTemporary, 4);
1178 break;
1179
John Kessenich71351de2016-06-08 12:50:56 -06001180 case EHTokDouble:
1181 new(&type) TType(EbtDouble);
1182 break;
1183 case EHTokDouble1:
1184 new(&type) TType(EbtDouble);
1185 type.makeVector();
1186 break;
1187 case EHTokDouble2:
1188 new(&type) TType(EbtDouble, EvqTemporary, 2);
1189 break;
1190 case EHTokDouble3:
1191 new(&type) TType(EbtDouble, EvqTemporary, 3);
1192 break;
1193 case EHTokDouble4:
1194 new(&type) TType(EbtDouble, EvqTemporary, 4);
1195 break;
1196
1197 case EHTokInt:
1198 case EHTokDword:
1199 new(&type) TType(EbtInt);
1200 break;
1201 case EHTokInt1:
1202 new(&type) TType(EbtInt);
1203 type.makeVector();
1204 break;
John Kessenich87142c72016-03-12 20:24:24 -07001205 case EHTokInt2:
1206 new(&type) TType(EbtInt, EvqTemporary, 2);
1207 break;
1208 case EHTokInt3:
1209 new(&type) TType(EbtInt, EvqTemporary, 3);
1210 break;
1211 case EHTokInt4:
1212 new(&type) TType(EbtInt, EvqTemporary, 4);
1213 break;
1214
John Kessenich71351de2016-06-08 12:50:56 -06001215 case EHTokUint:
1216 new(&type) TType(EbtUint);
1217 break;
1218 case EHTokUint1:
1219 new(&type) TType(EbtUint);
1220 type.makeVector();
1221 break;
1222 case EHTokUint2:
1223 new(&type) TType(EbtUint, EvqTemporary, 2);
1224 break;
1225 case EHTokUint3:
1226 new(&type) TType(EbtUint, EvqTemporary, 3);
1227 break;
1228 case EHTokUint4:
1229 new(&type) TType(EbtUint, EvqTemporary, 4);
1230 break;
1231
LoopDawg6daaa4f2016-06-23 19:13:48 -06001232
John Kessenich71351de2016-06-08 12:50:56 -06001233 case EHTokBool:
1234 new(&type) TType(EbtBool);
1235 break;
1236 case EHTokBool1:
1237 new(&type) TType(EbtBool);
1238 type.makeVector();
1239 break;
John Kessenich87142c72016-03-12 20:24:24 -07001240 case EHTokBool2:
1241 new(&type) TType(EbtBool, EvqTemporary, 2);
1242 break;
1243 case EHTokBool3:
1244 new(&type) TType(EbtBool, EvqTemporary, 3);
1245 break;
1246 case EHTokBool4:
1247 new(&type) TType(EbtBool, EvqTemporary, 4);
1248 break;
1249
steve-lunarg3226b082016-10-26 19:18:55 -06001250 case EHTokMin16float:
1251 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1252 break;
1253 case EHTokMin16float1:
1254 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1255 type.makeVector();
1256 break;
1257 case EHTokMin16float2:
1258 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1259 break;
1260 case EHTokMin16float3:
1261 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1262 break;
1263 case EHTokMin16float4:
1264 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1265 break;
1266
1267 case EHTokMin10float:
1268 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1269 break;
1270 case EHTokMin10float1:
1271 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1272 type.makeVector();
1273 break;
1274 case EHTokMin10float2:
1275 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1276 break;
1277 case EHTokMin10float3:
1278 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1279 break;
1280 case EHTokMin10float4:
1281 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1282 break;
1283
1284 case EHTokMin16int:
1285 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1286 break;
1287 case EHTokMin16int1:
1288 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1289 type.makeVector();
1290 break;
1291 case EHTokMin16int2:
1292 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1293 break;
1294 case EHTokMin16int3:
1295 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1296 break;
1297 case EHTokMin16int4:
1298 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1299 break;
1300
1301 case EHTokMin12int:
1302 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1303 break;
1304 case EHTokMin12int1:
1305 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1306 type.makeVector();
1307 break;
1308 case EHTokMin12int2:
1309 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1310 break;
1311 case EHTokMin12int3:
1312 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1313 break;
1314 case EHTokMin12int4:
1315 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1316 break;
1317
1318 case EHTokMin16uint:
1319 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1320 break;
1321 case EHTokMin16uint1:
1322 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1323 type.makeVector();
1324 break;
1325 case EHTokMin16uint2:
1326 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1327 break;
1328 case EHTokMin16uint3:
1329 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1330 break;
1331 case EHTokMin16uint4:
1332 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1333 break;
1334
John Kessenich0133c122016-05-20 12:17:26 -06001335 case EHTokInt1x1:
1336 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1337 break;
1338 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001339 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001340 break;
1341 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001342 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001343 break;
1344 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001345 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001346 break;
1347 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001348 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001349 break;
1350 case EHTokInt2x2:
1351 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1352 break;
1353 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001354 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001355 break;
1356 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001357 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001358 break;
1359 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001360 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001361 break;
1362 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001363 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001364 break;
1365 case EHTokInt3x3:
1366 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1367 break;
1368 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001369 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001370 break;
1371 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001372 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001373 break;
1374 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001375 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001376 break;
1377 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001378 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001379 break;
1380 case EHTokInt4x4:
1381 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1382 break;
1383
John Kessenich71351de2016-06-08 12:50:56 -06001384 case EHTokUint1x1:
1385 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1386 break;
1387 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001388 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001389 break;
1390 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001391 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001392 break;
1393 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001394 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001395 break;
1396 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001397 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001398 break;
1399 case EHTokUint2x2:
1400 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1401 break;
1402 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001403 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001404 break;
1405 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001406 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001407 break;
1408 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001409 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001410 break;
1411 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001412 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001413 break;
1414 case EHTokUint3x3:
1415 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1416 break;
1417 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001418 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001419 break;
1420 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001421 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001422 break;
1423 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001424 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001425 break;
1426 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001427 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001428 break;
1429 case EHTokUint4x4:
1430 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1431 break;
1432
1433 case EHTokBool1x1:
1434 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1435 break;
1436 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001437 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001438 break;
1439 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001440 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001441 break;
1442 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001443 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001444 break;
1445 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001446 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001447 break;
1448 case EHTokBool2x2:
1449 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1450 break;
1451 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001452 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001453 break;
1454 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001455 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001456 break;
1457 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001458 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001459 break;
1460 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001461 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001462 break;
1463 case EHTokBool3x3:
1464 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1465 break;
1466 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001467 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001468 break;
1469 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001470 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001471 break;
1472 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001473 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001474 break;
1475 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001476 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001477 break;
1478 case EHTokBool4x4:
1479 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1480 break;
1481
John Kessenich0133c122016-05-20 12:17:26 -06001482 case EHTokFloat1x1:
1483 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1484 break;
1485 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001486 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001487 break;
1488 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001489 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001490 break;
1491 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001492 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001493 break;
1494 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001495 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001496 break;
John Kessenich87142c72016-03-12 20:24:24 -07001497 case EHTokFloat2x2:
1498 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1499 break;
1500 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001501 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001502 break;
1503 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001504 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001505 break;
John Kessenich0133c122016-05-20 12:17:26 -06001506 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001507 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001508 break;
John Kessenich87142c72016-03-12 20:24:24 -07001509 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001510 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001511 break;
1512 case EHTokFloat3x3:
1513 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1514 break;
1515 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001516 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001517 break;
John Kessenich0133c122016-05-20 12:17:26 -06001518 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001519 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001520 break;
John Kessenich87142c72016-03-12 20:24:24 -07001521 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001522 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001523 break;
1524 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001525 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001526 break;
1527 case EHTokFloat4x4:
1528 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1529 break;
1530
John Kessenich0133c122016-05-20 12:17:26 -06001531 case EHTokDouble1x1:
1532 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1533 break;
1534 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001535 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001536 break;
1537 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001538 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001539 break;
1540 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001541 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001542 break;
1543 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001544 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001545 break;
1546 case EHTokDouble2x2:
1547 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1548 break;
1549 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001550 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001551 break;
1552 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001553 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001554 break;
1555 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001556 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001557 break;
1558 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001559 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001560 break;
1561 case EHTokDouble3x3:
1562 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1563 break;
1564 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001565 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001566 break;
1567 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001568 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001569 break;
1570 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001571 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001572 break;
1573 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001574 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001575 break;
1576 case EHTokDouble4x4:
1577 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1578 break;
1579
John Kessenich87142c72016-03-12 20:24:24 -07001580 default:
1581 return false;
1582 }
1583
1584 advanceToken();
1585
1586 return true;
1587}
1588
John Kesseniche6e74942016-06-11 16:43:14 -06001589// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001590// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1591// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1592//
1593// struct_type
1594// : STRUCT
1595// | CBUFFER
1596// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001597//
1598bool HlslGrammar::acceptStruct(TType& type)
1599{
John Kessenichb804de62016-09-05 12:19:18 -06001600 // This storage qualifier will tell us whether it's an AST
1601 // block type or just a generic structure type.
1602 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001603
1604 // CBUFFER
1605 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001606 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001607 // TBUFFER
1608 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001609 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001610 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001611 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001612 return false;
1613
1614 // IDENTIFIER
1615 TString structName = "";
1616 if (peekTokenClass(EHTokIdentifier)) {
1617 structName = *token.string;
1618 advanceToken();
1619 }
1620
John Kessenich3d157c52016-07-25 16:05:33 -06001621 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001622 TQualifier postDeclQualifier;
1623 postDeclQualifier.clear();
1624 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001625
John Kesseniche6e74942016-06-11 16:43:14 -06001626 // LEFT_BRACE
1627 if (! acceptTokenClass(EHTokLeftBrace)) {
1628 expected("{");
1629 return false;
1630 }
1631
1632 // struct_declaration_list
1633 TTypeList* typeList;
1634 if (! acceptStructDeclarationList(typeList)) {
1635 expected("struct member declarations");
1636 return false;
1637 }
1638
1639 // RIGHT_BRACE
1640 if (! acceptTokenClass(EHTokRightBrace)) {
1641 expected("}");
1642 return false;
1643 }
1644
1645 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001646 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001647 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001648 else {
John Kessenich7735b942016-09-05 12:40:06 -06001649 postDeclQualifier.storage = storageQualifier;
1650 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001651 }
John Kesseniche6e74942016-06-11 16:43:14 -06001652
John Kessenich3d157c52016-07-25 16:05:33 -06001653 // If it was named, which means the type can be reused later, add
1654 // it to the symbol table. (Unless it's a block, in which
1655 // case the name is not a type.)
1656 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001657 TVariable* userTypeDef = new TVariable(&structName, type, true);
1658 if (! parseContext.symbolTable.insert(*userTypeDef))
1659 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1660 }
1661
1662 return true;
1663}
1664
1665// struct_declaration_list
1666// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1667//
1668// struct_declaration
1669// : fully_specified_type struct_declarator COMMA struct_declarator ...
1670//
1671// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001672// : IDENTIFIER post_decls
1673// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001674//
1675bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1676{
1677 typeList = new TTypeList();
1678
1679 do {
1680 // success on seeing the RIGHT_BRACE coming up
1681 if (peekTokenClass(EHTokRightBrace))
1682 return true;
1683
1684 // struct_declaration
1685
1686 // fully_specified_type
1687 TType memberType;
1688 if (! acceptFullySpecifiedType(memberType)) {
1689 expected("member type");
1690 return false;
1691 }
1692
1693 // struct_declarator COMMA struct_declarator ...
1694 do {
1695 // peek IDENTIFIER
1696 if (! peekTokenClass(EHTokIdentifier)) {
1697 expected("member name");
1698 return false;
1699 }
1700
1701 // add it to the list of members
1702 TTypeLoc member = { new TType(EbtVoid), token.loc };
1703 member.type->shallowCopy(memberType);
1704 member.type->setFieldName(*token.string);
1705 typeList->push_back(member);
1706
1707 // accept IDENTIFIER
1708 advanceToken();
1709
1710 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001711 TArraySizes* arraySizes = nullptr;
1712 acceptArraySpecifier(arraySizes);
1713 if (arraySizes)
1714 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001715
John Kessenich7735b942016-09-05 12:40:06 -06001716 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001717
John Kesseniche6e74942016-06-11 16:43:14 -06001718 // success on seeing the SEMICOLON coming up
1719 if (peekTokenClass(EHTokSemicolon))
1720 break;
1721
1722 // COMMA
1723 if (! acceptTokenClass(EHTokComma)) {
1724 expected(",");
1725 return false;
1726 }
1727
1728 } while (true);
1729
1730 // SEMI_COLON
1731 if (! acceptTokenClass(EHTokSemicolon)) {
1732 expected(";");
1733 return false;
1734 }
1735
1736 } while (true);
1737}
1738
John Kessenich5f934b02016-03-13 17:58:25 -06001739// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001740// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001741// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001742//
1743bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1744{
John Kessenich078d7f22016-03-14 10:02:11 -06001745 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001746 if (! acceptTokenClass(EHTokLeftParen))
1747 return false;
1748
John Kessenich71351de2016-06-08 12:50:56 -06001749 // VOID RIGHT_PAREN
1750 if (! acceptTokenClass(EHTokVoid)) {
1751 do {
1752 // parameter_declaration
1753 if (! acceptParameterDeclaration(function))
1754 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001755
John Kessenich71351de2016-06-08 12:50:56 -06001756 // COMMA
1757 if (! acceptTokenClass(EHTokComma))
1758 break;
1759 } while (true);
1760 }
John Kessenich5f934b02016-03-13 17:58:25 -06001761
John Kessenich078d7f22016-03-14 10:02:11 -06001762 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001763 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001764 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001765 return false;
1766 }
1767
1768 return true;
1769}
1770
1771// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001772// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001773// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001774//
1775bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1776{
1777 // fully_specified_type
1778 TType* type = new TType;
1779 if (! acceptFullySpecifiedType(*type))
1780 return false;
1781
1782 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001783 HlslToken idToken;
1784 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001785
John Kessenich19b92ff2016-06-19 11:50:34 -06001786 // array_specifier
1787 TArraySizes* arraySizes = nullptr;
1788 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001789 if (arraySizes) {
1790 if (arraySizes->isImplicit()) {
1791 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1792 return false;
1793 }
1794
John Kessenich19b92ff2016-06-19 11:50:34 -06001795 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001796 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001797
1798 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001799 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001800
John Kessenich5aa59e22016-06-17 15:50:47 -06001801 parseContext.paramFix(*type);
1802
John Kessenichaecd4972016-03-14 10:46:34 -06001803 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001804 function.addParameter(param);
1805
1806 return true;
1807}
1808
1809// Do the work to create the function definition in addition to
1810// parsing the body (compound_statement).
steve-lunarg1868b142016-10-20 13:07:10 -06001811bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001812{
John Kessenicha3051662016-09-02 19:13:36 -06001813 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001814 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001815
John Kessenich077e0522016-06-09 02:02:17 -06001816 // This does a pushScope()
steve-lunarg1868b142016-10-20 13:07:10 -06001817 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06001818
1819 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001820 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001821 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001822 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001823 return true;
1824 }
1825
1826 return false;
1827}
1828
John Kessenich0d2b6de2016-06-05 11:23:11 -06001829// Accept an expression with parenthesis around it, where
1830// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001831// syntactically required ones like in "if ( expression )".
1832//
1833// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001834//
1835// Note this one is not set up to be speculative; as it gives
1836// errors if not found.
1837//
1838bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1839{
1840 // LEFT_PAREN
1841 if (! acceptTokenClass(EHTokLeftParen))
1842 expected("(");
1843
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001844 bool decl = false;
1845 TIntermNode* declNode = nullptr;
1846 decl = acceptControlDeclaration(declNode);
1847 if (decl) {
1848 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1849 expected("initialized declaration");
1850 return false;
1851 } else
1852 expression = declNode->getAsTyped();
1853 } else {
1854 // no declaration
1855 if (! acceptExpression(expression)) {
1856 expected("expression");
1857 return false;
1858 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001859 }
1860
1861 // RIGHT_PAREN
1862 if (! acceptTokenClass(EHTokRightParen))
1863 expected(")");
1864
1865 return true;
1866}
1867
John Kessenich34fb0362016-05-03 23:17:20 -06001868// The top-level full expression recognizer.
1869//
John Kessenich87142c72016-03-12 20:24:24 -07001870// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001871// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001872//
1873bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1874{
LoopDawgef764a22016-06-03 09:17:51 -06001875 node = nullptr;
1876
John Kessenich34fb0362016-05-03 23:17:20 -06001877 // assignment_expression
1878 if (! acceptAssignmentExpression(node))
1879 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001880
John Kessenich34fb0362016-05-03 23:17:20 -06001881 if (! peekTokenClass(EHTokComma))
1882 return true;
1883
1884 do {
1885 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001886 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001887 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001888
John Kessenich34fb0362016-05-03 23:17:20 -06001889 // ... assignment_expression
1890 TIntermTyped* rightNode = nullptr;
1891 if (! acceptAssignmentExpression(rightNode)) {
1892 expected("assignment expression");
1893 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001894 }
1895
John Kessenich34fb0362016-05-03 23:17:20 -06001896 node = intermediate.addComma(node, rightNode, loc);
1897
1898 if (! peekTokenClass(EHTokComma))
1899 return true;
1900 } while (true);
1901}
1902
John Kessenich07354242016-07-01 19:58:06 -06001903// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07001904// : LEFT_BRACE RIGHT_BRACE
1905// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001906//
1907// initializer_list
1908// : assignment_expression COMMA assignment_expression COMMA ...
1909//
1910bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1911{
1912 // LEFT_BRACE
1913 if (! acceptTokenClass(EHTokLeftBrace))
1914 return false;
1915
John Kessenich98ad4852016-11-27 17:39:07 -07001916 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001917 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07001918 if (acceptTokenClass(EHTokRightBrace)) {
1919 // a zero-length initializer list
1920 node = intermediate.makeAggregate(loc);
1921 return true;
1922 }
1923
1924 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06001925 node = nullptr;
1926 do {
1927 // assignment_expression
1928 TIntermTyped* expr;
1929 if (! acceptAssignmentExpression(expr)) {
1930 expected("assignment expression in initializer list");
1931 return false;
1932 }
1933 node = intermediate.growAggregate(node, expr, loc);
1934
1935 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001936 if (acceptTokenClass(EHTokComma)) {
1937 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1938 return true;
John Kessenich07354242016-07-01 19:58:06 -06001939 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001940 }
John Kessenich07354242016-07-01 19:58:06 -06001941
1942 // RIGHT_BRACE
1943 if (acceptTokenClass(EHTokRightBrace))
1944 return true;
1945
1946 expected(", or }");
1947 return false;
1948 } while (true);
1949}
1950
John Kessenich34fb0362016-05-03 23:17:20 -06001951// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001952// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001953//
1954// a op (b op (c op d))
1955//
1956// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001957// : initializer
1958// | conditional_expression
1959// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001960//
1961bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1962{
John Kessenich07354242016-07-01 19:58:06 -06001963 // initializer
1964 if (peekTokenClass(EHTokLeftBrace)) {
1965 if (acceptInitializer(node))
1966 return true;
1967
1968 expected("initializer");
1969 return false;
1970 }
1971
John Kessenich00957f82016-07-27 10:39:57 -06001972 // conditional_expression
1973 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001974 return false;
1975
John Kessenich07354242016-07-01 19:58:06 -06001976 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001977 TOperator assignOp = HlslOpMap::assignment(peek());
1978 if (assignOp == EOpNull)
1979 return true;
1980
John Kessenich00957f82016-07-27 10:39:57 -06001981 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001982 TSourceLoc loc = token.loc;
1983 advanceToken();
1984
John Kessenich00957f82016-07-27 10:39:57 -06001985 // conditional_expression assign_op conditional_expression ...
1986 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001987 // gets the right-to-left associativity.
1988 TIntermTyped* rightNode = nullptr;
1989 if (! acceptAssignmentExpression(rightNode)) {
1990 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001991 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001992 }
1993
John Kessenichd21baed2016-09-16 03:05:12 -06001994 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06001995 node = parseContext.handleLvalue(loc, "assign", node);
1996
John Kessenichfea226b2016-07-28 17:53:56 -06001997 if (node == nullptr) {
1998 parseContext.error(loc, "could not create assignment", "", "");
1999 return false;
2000 }
John Kessenich34fb0362016-05-03 23:17:20 -06002001
2002 if (! peekTokenClass(EHTokComma))
2003 return true;
2004
2005 return true;
2006}
2007
John Kessenich00957f82016-07-27 10:39:57 -06002008// Accept a conditional expression, which associates right-to-left,
2009// accomplished by the "true" expression calling down to lower
2010// precedence levels than this level.
2011//
2012// conditional_expression
2013// : binary_expression
2014// | binary_expression QUESTION expression COLON assignment_expression
2015//
2016bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2017{
2018 // binary_expression
2019 if (! acceptBinaryExpression(node, PlLogicalOr))
2020 return false;
2021
2022 if (! acceptTokenClass(EHTokQuestion))
2023 return true;
2024
2025 TIntermTyped* trueNode = nullptr;
2026 if (! acceptExpression(trueNode)) {
2027 expected("expression after ?");
2028 return false;
2029 }
2030 TSourceLoc loc = token.loc;
2031
2032 if (! acceptTokenClass(EHTokColon)) {
2033 expected(":");
2034 return false;
2035 }
2036
2037 TIntermTyped* falseNode = nullptr;
2038 if (! acceptAssignmentExpression(falseNode)) {
2039 expected("expression after :");
2040 return false;
2041 }
2042
2043 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2044
2045 return true;
2046}
2047
John Kessenich34fb0362016-05-03 23:17:20 -06002048// Accept a binary expression, for binary operations that
2049// associate left-to-right. This is, it is implicit, for example
2050//
2051// ((a op b) op c) op d
2052//
2053// binary_expression
2054// : expression op expression op expression ...
2055//
2056// where 'expression' is the next higher level in precedence.
2057//
2058bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2059{
2060 if (precedenceLevel > PlMul)
2061 return acceptUnaryExpression(node);
2062
2063 // assignment_expression
2064 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2065 return false;
2066
John Kessenich34fb0362016-05-03 23:17:20 -06002067 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002068 TOperator op = HlslOpMap::binary(peek());
2069 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2070 if (tokenLevel < precedenceLevel)
2071 return true;
2072
John Kessenich34fb0362016-05-03 23:17:20 -06002073 // ... op
2074 TSourceLoc loc = token.loc;
2075 advanceToken();
2076
2077 // ... expression
2078 TIntermTyped* rightNode = nullptr;
2079 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2080 expected("expression");
2081 return false;
2082 }
2083
2084 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002085 if (node == nullptr) {
2086 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2087 return false;
2088 }
John Kessenich34fb0362016-05-03 23:17:20 -06002089 } while (true);
2090}
2091
2092// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002093// : (type) unary_expression
2094// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002095// | - unary_expression
2096// | ! unary_expression
2097// | ~ unary_expression
2098// | ++ unary_expression
2099// | -- unary_expression
2100// | postfix_expression
2101//
2102bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2103{
John Kessenich1cc1a282016-06-03 16:55:49 -06002104 // (type) unary_expression
2105 // Have to look two steps ahead, because this could be, e.g., a
2106 // postfix_expression instead, since that also starts with at "(".
2107 if (acceptTokenClass(EHTokLeftParen)) {
2108 TType castType;
2109 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002110 if (acceptTokenClass(EHTokRightParen)) {
2111 // We've matched "(type)" now, get the expression to cast
2112 TSourceLoc loc = token.loc;
2113 if (! acceptUnaryExpression(node))
2114 return false;
2115
2116 // Hook it up like a constructor
2117 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2118 if (constructorFunction == nullptr) {
2119 expected("type that can be constructed");
2120 return false;
2121 }
2122 TIntermTyped* arguments = nullptr;
2123 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2124 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2125
2126 return true;
2127 } else {
2128 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2129 // the '(int' part. We must back up twice.
2130 recedeToken();
2131 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002132 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002133 } else {
2134 // This isn't a type cast, but it still started "(", so if it is a
2135 // unary expression, it can only be a postfix_expression, so try that.
2136 // Back it up first.
2137 recedeToken();
2138 return acceptPostfixExpression(node);
2139 }
2140 }
2141
2142 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002143 TOperator unaryOp = HlslOpMap::preUnary(peek());
2144
John Kessenich1cc1a282016-06-03 16:55:49 -06002145 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002146 if (unaryOp == EOpNull)
2147 return acceptPostfixExpression(node);
2148
2149 // op unary_expression
2150 TSourceLoc loc = token.loc;
2151 advanceToken();
2152 if (! acceptUnaryExpression(node))
2153 return false;
2154
2155 // + is a no-op
2156 if (unaryOp == EOpAdd)
2157 return true;
2158
2159 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002160
2161 // These unary ops require lvalues
2162 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2163 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002164
2165 return node != nullptr;
2166}
2167
2168// postfix_expression
2169// : LEFT_PAREN expression RIGHT_PAREN
2170// | literal
2171// | constructor
2172// | identifier
2173// | function_call
2174// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2175// | postfix_expression DOT IDENTIFIER
2176// | postfix_expression INC_OP
2177// | postfix_expression DEC_OP
2178//
2179bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2180{
2181 // Not implemented as self-recursive:
2182 // The logical "right recursion" is done with an loop at the end
2183
2184 // idToken will pick up either a variable or a function name in a function call
2185 HlslToken idToken;
2186
John Kessenich21472ae2016-06-04 11:46:33 -06002187 // Find something before the postfix operations, as they can't operate
2188 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002189 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002190 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002191 if (! acceptExpression(node)) {
2192 expected("expression");
2193 return false;
2194 }
2195 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002196 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002197 return false;
2198 }
John Kessenich34fb0362016-05-03 23:17:20 -06002199 } else if (acceptLiteral(node)) {
2200 // literal (nothing else to do yet), go on to the
2201 } else if (acceptConstructor(node)) {
2202 // constructor (nothing else to do yet)
2203 } else if (acceptIdentifier(idToken)) {
2204 // identifier or function_call name
2205 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002206 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002207 } else if (acceptFunctionCall(idToken, node)) {
2208 // function_call (nothing else to do yet)
2209 } else {
2210 expected("function call arguments");
2211 return false;
2212 }
John Kessenich21472ae2016-06-04 11:46:33 -06002213 } else {
2214 // nothing found, can't post operate
2215 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002216 }
2217
steve-lunarga2b01a02016-11-28 17:09:54 -07002218 // This is to guarantee we do this no matter how we get out of the stack frame.
2219 // This way there's no bug if an early return forgets to do it.
2220 struct tFinalize {
2221 tFinalize(HlslParseContext& p) : parseContext(p) { }
2222 ~tFinalize() { parseContext.finalizeFlattening(); }
2223 HlslParseContext& parseContext;
2224 } finalize(parseContext);
2225
2226 // Initialize the flattening accumulation data, so we can track data across multiple bracket or
2227 // dot operators. This can also be nested, e.g, for [], so we have to track each nesting
2228 // level: hence the init and finalize. Even though in practice these must be
2229 // constants, they are parsed no matter what.
2230 parseContext.initFlattening();
2231
John Kessenich21472ae2016-06-04 11:46:33 -06002232 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002233 do {
2234 TSourceLoc loc = token.loc;
2235 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002236
John Kessenich34fb0362016-05-03 23:17:20 -06002237 // Consume only a valid post-unary operator, otherwise we are done.
2238 switch (postOp) {
2239 case EOpIndexDirectStruct:
2240 case EOpIndexIndirect:
2241 case EOpPostIncrement:
2242 case EOpPostDecrement:
2243 advanceToken();
2244 break;
2245 default:
2246 return true;
2247 }
John Kessenich87142c72016-03-12 20:24:24 -07002248
John Kessenich34fb0362016-05-03 23:17:20 -06002249 // We have a valid post-unary operator, process it.
2250 switch (postOp) {
2251 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002252 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002253 // DOT IDENTIFIER
2254 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002255 HlslToken field;
2256 if (! acceptIdentifier(field)) {
2257 expected("swizzle or member");
2258 return false;
2259 }
LoopDawg4886f692016-06-29 10:58:58 -06002260
2261 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002262 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002263
2264 // 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 -07002265 if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
LoopDawg4886f692016-06-29 10:58:58 -06002266 if (! acceptFunctionCall(field, node, base)) {
2267 expected("function parameters");
2268 return false;
2269 }
2270 }
2271
John Kessenich34fb0362016-05-03 23:17:20 -06002272 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002273 }
John Kessenich34fb0362016-05-03 23:17:20 -06002274 case EOpIndexIndirect:
2275 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002276 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002277 TIntermTyped* indexNode = nullptr;
2278 if (! acceptExpression(indexNode) ||
2279 ! peekTokenClass(EHTokRightBracket)) {
2280 expected("expression followed by ']'");
2281 return false;
2282 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002283 advanceToken();
2284 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2285 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002286 }
2287 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002288 // INC_OP
2289 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002290 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002291 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002292 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002293 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002294 break;
2295 default:
2296 assert(0);
2297 break;
2298 }
2299 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002300}
2301
John Kessenichd016be12016-03-13 11:24:20 -06002302// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002303// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002304//
2305bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2306{
2307 // type
2308 TType type;
2309 if (acceptType(type)) {
2310 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2311 if (constructorFunction == nullptr)
2312 return false;
2313
2314 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002315 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002316 if (! acceptArguments(constructorFunction, arguments)) {
2317 expected("constructor arguments");
2318 return false;
2319 }
2320
2321 // hook it up
2322 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2323
2324 return true;
2325 }
2326
2327 return false;
2328}
2329
John Kessenich34fb0362016-05-03 23:17:20 -06002330// The function_call identifier was already recognized, and passed in as idToken.
2331//
2332// function_call
2333// : [idToken] arguments
2334//
LoopDawg4886f692016-06-29 10:58:58 -06002335bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002336{
John Kessenich4678ca92016-05-13 09:33:42 -06002337 // arguments
2338 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2339 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002340
2341 // methods have an implicit first argument of the calling object.
2342 if (base != nullptr)
2343 parseContext.handleFunctionArgument(function, arguments, base);
2344
John Kessenich4678ca92016-05-13 09:33:42 -06002345 if (! acceptArguments(function, arguments))
2346 return false;
2347
2348 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2349
2350 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002351}
2352
John Kessenich87142c72016-03-12 20:24:24 -07002353// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002354// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002355//
John Kessenichd016be12016-03-13 11:24:20 -06002356// The arguments are pushed onto the 'function' argument list and
2357// onto the 'arguments' aggregate.
2358//
John Kessenich4678ca92016-05-13 09:33:42 -06002359bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002360{
John Kessenich078d7f22016-03-14 10:02:11 -06002361 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002362 if (! acceptTokenClass(EHTokLeftParen))
2363 return false;
2364
2365 do {
John Kessenichd016be12016-03-13 11:24:20 -06002366 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002367 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002368 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002369 break;
John Kessenichd016be12016-03-13 11:24:20 -06002370
2371 // hook it up
2372 parseContext.handleFunctionArgument(function, arguments, arg);
2373
John Kessenich078d7f22016-03-14 10:02:11 -06002374 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002375 if (! acceptTokenClass(EHTokComma))
2376 break;
2377 } while (true);
2378
John Kessenich078d7f22016-03-14 10:02:11 -06002379 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002380 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002381 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002382 return false;
2383 }
2384
2385 return true;
2386}
2387
2388bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2389{
2390 switch (token.tokenClass) {
2391 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002392 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002393 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002394 case EHTokUintConstant:
2395 node = intermediate.addConstantUnion(token.u, token.loc, true);
2396 break;
John Kessenich87142c72016-03-12 20:24:24 -07002397 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002398 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002399 break;
2400 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002401 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002402 break;
2403 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002404 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002405 break;
John Kessenich86f71382016-09-19 20:23:18 -06002406 case EHTokStringConstant:
2407 node = nullptr;
2408 break;
John Kessenich87142c72016-03-12 20:24:24 -07002409
2410 default:
2411 return false;
2412 }
2413
2414 advanceToken();
2415
2416 return true;
2417}
2418
John Kessenich5f934b02016-03-13 17:58:25 -06002419// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002420// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002421//
John Kessenich21472ae2016-06-04 11:46:33 -06002422bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002423{
John Kessenich21472ae2016-06-04 11:46:33 -06002424 TIntermAggregate* compoundStatement = nullptr;
2425
John Kessenich34fb0362016-05-03 23:17:20 -06002426 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002427 if (! acceptTokenClass(EHTokLeftBrace))
2428 return false;
2429
2430 // statement statement ...
2431 TIntermNode* statement = nullptr;
2432 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002433 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2434 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2435 branch->getFlowOp() == EOpDefault)) {
2436 // hook up individual subsequences within a switch statement
2437 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2438 compoundStatement = nullptr;
2439 } else {
2440 // hook it up to the growing compound statement
2441 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2442 }
John Kessenich5f934b02016-03-13 17:58:25 -06002443 }
John Kessenich34fb0362016-05-03 23:17:20 -06002444 if (compoundStatement)
2445 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002446
John Kessenich21472ae2016-06-04 11:46:33 -06002447 retStatement = compoundStatement;
2448
John Kessenich34fb0362016-05-03 23:17:20 -06002449 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002450 return acceptTokenClass(EHTokRightBrace);
2451}
2452
John Kessenich0d2b6de2016-06-05 11:23:11 -06002453bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2454{
2455 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002456 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002457 parseContext.popScope();
2458
2459 return result;
2460}
2461
John Kessenich077e0522016-06-09 02:02:17 -06002462bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002463{
John Kessenich077e0522016-06-09 02:02:17 -06002464 parseContext.pushScope();
2465 bool result = acceptCompoundStatement(statement);
2466 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002467
2468 return result;
2469}
2470
John Kessenich5f934b02016-03-13 17:58:25 -06002471// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002472// : attributes attributed_statement
2473//
2474// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002475// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002476// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002477// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002478// | declaration_statement
2479// | selection_statement
2480// | switch_statement
2481// | case_label
2482// | iteration_statement
2483// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002484//
2485bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2486{
John Kessenich21472ae2016-06-04 11:46:33 -06002487 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002488
John Kessenich21472ae2016-06-04 11:46:33 -06002489 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002490 TAttributeMap attributes;
2491 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002492
John Kessenich21472ae2016-06-04 11:46:33 -06002493 // attributed_statement
2494 switch (peek()) {
2495 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002496 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002497
John Kessenich21472ae2016-06-04 11:46:33 -06002498 case EHTokIf:
2499 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002500
John Kessenich21472ae2016-06-04 11:46:33 -06002501 case EHTokSwitch:
2502 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002503
John Kessenich21472ae2016-06-04 11:46:33 -06002504 case EHTokFor:
2505 case EHTokDo:
2506 case EHTokWhile:
2507 return acceptIterationStatement(statement);
2508
2509 case EHTokContinue:
2510 case EHTokBreak:
2511 case EHTokDiscard:
2512 case EHTokReturn:
2513 return acceptJumpStatement(statement);
2514
2515 case EHTokCase:
2516 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002517 case EHTokDefault:
2518 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002519
2520 case EHTokSemicolon:
2521 return acceptTokenClass(EHTokSemicolon);
2522
2523 case EHTokRightBrace:
2524 // Performance: not strictly necessary, but stops a bunch of hunting early,
2525 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002526 return false;
2527
John Kessenich21472ae2016-06-04 11:46:33 -06002528 default:
2529 {
2530 // declaration
2531 if (acceptDeclaration(statement))
2532 return true;
2533
2534 // expression
2535 TIntermTyped* node;
2536 if (acceptExpression(node))
2537 statement = node;
2538 else
2539 return false;
2540
2541 // SEMICOLON (following an expression)
2542 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002543 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002544 return false;
2545 }
2546 }
2547 }
2548
John Kessenich5f934b02016-03-13 17:58:25 -06002549 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002550}
2551
John Kessenich21472ae2016-06-04 11:46:33 -06002552// attributes
2553// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2554//
2555// attribute:
2556// : UNROLL
2557// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2558// | FASTOPT
2559// | ALLOW_UAV_CONDITION
2560// | BRANCH
2561// | FLATTEN
2562// | FORCECASE
2563// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002564// | DOMAIN
2565// | EARLYDEPTHSTENCIL
2566// | INSTANCE
2567// | MAXTESSFACTOR
2568// | OUTPUTCONTROLPOINTS
2569// | OUTPUTTOPOLOGY
2570// | PARTITIONING
2571// | PATCHCONSTANTFUNC
2572// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002573//
steve-lunarg1868b142016-10-20 13:07:10 -06002574void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002575{
steve-lunarg1868b142016-10-20 13:07:10 -06002576 // For now, accept the [ XXX(X) ] syntax, but drop all but
2577 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002578 // TODO: subset to correct set? Pass on?
2579 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002580 HlslToken idToken;
2581
John Kessenich0d2b6de2016-06-05 11:23:11 -06002582 // LEFT_BRACKET?
2583 if (! acceptTokenClass(EHTokLeftBracket))
2584 return;
2585
2586 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002587 if (acceptIdentifier(idToken)) {
2588 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002589 } else if (! peekTokenClass(EHTokRightBracket)) {
2590 expected("identifier");
2591 advanceToken();
2592 }
2593
steve-lunarga22f7db2016-11-11 08:17:44 -07002594 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002595
2596 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002597 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002598 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002599
John Kessenich0d2b6de2016-06-05 11:23:11 -06002600 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002601 bool expectingExpression = false;
steve-lunarg1868b142016-10-20 13:07:10 -06002602
steve-lunarga22f7db2016-11-11 08:17:44 -07002603 while (acceptAssignmentExpression(node)) {
2604 expectingExpression = false;
2605 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002606 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002607 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002608 }
2609
steve-lunarga22f7db2016-11-11 08:17:44 -07002610 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002611 if (! acceptTokenClass(EHTokRightParen))
2612 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002613
2614 // Error for partial or missing expression
2615 if (expectingExpression || expressions->getSequence().empty())
2616 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002617 }
2618
2619 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002620 if (!acceptTokenClass(EHTokRightBracket)) {
2621 expected("]");
2622 return;
2623 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002624
steve-lunarg1868b142016-10-20 13:07:10 -06002625 // Add any values we found into the attribute map. This accepts
2626 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002627 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002628 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002629}
2630
John Kessenich0d2b6de2016-06-05 11:23:11 -06002631// selection_statement
2632// : IF LEFT_PAREN expression RIGHT_PAREN statement
2633// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2634//
John Kessenich21472ae2016-06-04 11:46:33 -06002635bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2636{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002637 TSourceLoc loc = token.loc;
2638
2639 // IF
2640 if (! acceptTokenClass(EHTokIf))
2641 return false;
2642
2643 // so that something declared in the condition is scoped to the lifetimes
2644 // of the then-else statements
2645 parseContext.pushScope();
2646
2647 // LEFT_PAREN expression RIGHT_PAREN
2648 TIntermTyped* condition;
2649 if (! acceptParenExpression(condition))
2650 return false;
2651
2652 // create the child statements
2653 TIntermNodePair thenElse = { nullptr, nullptr };
2654
2655 // then statement
2656 if (! acceptScopedStatement(thenElse.node1)) {
2657 expected("then statement");
2658 return false;
2659 }
2660
2661 // ELSE
2662 if (acceptTokenClass(EHTokElse)) {
2663 // else statement
2664 if (! acceptScopedStatement(thenElse.node2)) {
2665 expected("else statement");
2666 return false;
2667 }
2668 }
2669
2670 // Put the pieces together
2671 statement = intermediate.addSelection(condition, thenElse, loc);
2672 parseContext.popScope();
2673
2674 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002675}
2676
John Kessenichd02dc5d2016-07-01 00:04:11 -06002677// switch_statement
2678// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2679//
John Kessenich21472ae2016-06-04 11:46:33 -06002680bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2681{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002682 // SWITCH
2683 TSourceLoc loc = token.loc;
2684 if (! acceptTokenClass(EHTokSwitch))
2685 return false;
2686
2687 // LEFT_PAREN expression RIGHT_PAREN
2688 parseContext.pushScope();
2689 TIntermTyped* switchExpression;
2690 if (! acceptParenExpression(switchExpression)) {
2691 parseContext.popScope();
2692 return false;
2693 }
2694
2695 // compound_statement
2696 parseContext.pushSwitchSequence(new TIntermSequence);
2697 bool statementOkay = acceptCompoundStatement(statement);
2698 if (statementOkay)
2699 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2700
2701 parseContext.popSwitchSequence();
2702 parseContext.popScope();
2703
2704 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002705}
2706
John Kessenich119f8f62016-06-05 15:44:07 -06002707// iteration_statement
2708// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2709// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2710// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2711//
2712// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002713bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2714{
John Kessenich119f8f62016-06-05 15:44:07 -06002715 TSourceLoc loc = token.loc;
2716 TIntermTyped* condition = nullptr;
2717
2718 EHlslTokenClass loop = peek();
2719 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2720
2721 // WHILE or DO or FOR
2722 advanceToken();
2723
2724 switch (loop) {
2725 case EHTokWhile:
2726 // so that something declared in the condition is scoped to the lifetime
2727 // of the while sub-statement
2728 parseContext.pushScope();
2729 parseContext.nestLooping();
2730
2731 // LEFT_PAREN condition RIGHT_PAREN
2732 if (! acceptParenExpression(condition))
2733 return false;
2734
2735 // statement
2736 if (! acceptScopedStatement(statement)) {
2737 expected("while sub-statement");
2738 return false;
2739 }
2740
2741 parseContext.unnestLooping();
2742 parseContext.popScope();
2743
2744 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2745
2746 return true;
2747
2748 case EHTokDo:
2749 parseContext.nestLooping();
2750
2751 if (! acceptTokenClass(EHTokLeftBrace))
2752 expected("{");
2753
2754 // statement
2755 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2756 expected("do sub-statement");
2757 return false;
2758 }
2759
2760 if (! acceptTokenClass(EHTokRightBrace))
2761 expected("}");
2762
2763 // WHILE
2764 if (! acceptTokenClass(EHTokWhile)) {
2765 expected("while");
2766 return false;
2767 }
2768
2769 // LEFT_PAREN condition RIGHT_PAREN
2770 TIntermTyped* condition;
2771 if (! acceptParenExpression(condition))
2772 return false;
2773
2774 if (! acceptTokenClass(EHTokSemicolon))
2775 expected(";");
2776
2777 parseContext.unnestLooping();
2778
2779 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2780
2781 return true;
2782
2783 case EHTokFor:
2784 {
2785 // LEFT_PAREN
2786 if (! acceptTokenClass(EHTokLeftParen))
2787 expected("(");
2788
2789 // so that something declared in the condition is scoped to the lifetime
2790 // of the for sub-statement
2791 parseContext.pushScope();
2792
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002793 // initializer
2794 TIntermNode* initNode = nullptr;
2795 if (! acceptControlDeclaration(initNode)) {
2796 TIntermTyped* initExpr = nullptr;
2797 acceptExpression(initExpr);
2798 initNode = initExpr;
2799 }
2800 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002801 if (! acceptTokenClass(EHTokSemicolon))
2802 expected(";");
2803
2804 parseContext.nestLooping();
2805
2806 // condition SEMI_COLON
2807 acceptExpression(condition);
2808 if (! acceptTokenClass(EHTokSemicolon))
2809 expected(";");
2810
2811 // iterator SEMI_COLON
2812 TIntermTyped* iterator = nullptr;
2813 acceptExpression(iterator);
2814 if (! acceptTokenClass(EHTokRightParen))
2815 expected(")");
2816
2817 // statement
2818 if (! acceptScopedStatement(statement)) {
2819 expected("for sub-statement");
2820 return false;
2821 }
2822
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002823 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002824
2825 parseContext.popScope();
2826 parseContext.unnestLooping();
2827
2828 return true;
2829 }
2830
2831 default:
2832 return false;
2833 }
John Kessenich21472ae2016-06-04 11:46:33 -06002834}
2835
2836// jump_statement
2837// : CONTINUE SEMICOLON
2838// | BREAK SEMICOLON
2839// | DISCARD SEMICOLON
2840// | RETURN SEMICOLON
2841// | RETURN expression SEMICOLON
2842//
2843bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2844{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002845 EHlslTokenClass jump = peek();
2846 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002847 case EHTokContinue:
2848 case EHTokBreak:
2849 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002850 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002851 advanceToken();
2852 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002853 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002854 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002855 return false;
2856 }
John Kessenich21472ae2016-06-04 11:46:33 -06002857
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002858 switch (jump) {
2859 case EHTokContinue:
2860 statement = intermediate.addBranch(EOpContinue, token.loc);
2861 break;
2862 case EHTokBreak:
2863 statement = intermediate.addBranch(EOpBreak, token.loc);
2864 break;
2865 case EHTokDiscard:
2866 statement = intermediate.addBranch(EOpKill, token.loc);
2867 break;
2868
2869 case EHTokReturn:
2870 {
2871 // expression
2872 TIntermTyped* node;
2873 if (acceptExpression(node)) {
2874 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002875 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002876 } else
2877 statement = intermediate.addBranch(EOpReturn, token.loc);
2878 break;
2879 }
2880
2881 default:
2882 assert(0);
2883 return false;
2884 }
2885
2886 // SEMICOLON
2887 if (! acceptTokenClass(EHTokSemicolon))
2888 expected(";");
2889
2890 return true;
2891}
John Kessenich21472ae2016-06-04 11:46:33 -06002892
John Kessenichd02dc5d2016-07-01 00:04:11 -06002893// case_label
2894// : CASE expression COLON
2895//
John Kessenich21472ae2016-06-04 11:46:33 -06002896bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2897{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002898 TSourceLoc loc = token.loc;
2899 if (! acceptTokenClass(EHTokCase))
2900 return false;
2901
2902 TIntermTyped* expression;
2903 if (! acceptExpression(expression)) {
2904 expected("case expression");
2905 return false;
2906 }
2907
2908 if (! acceptTokenClass(EHTokColon)) {
2909 expected(":");
2910 return false;
2911 }
2912
2913 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2914
2915 return true;
2916}
2917
2918// default_label
2919// : DEFAULT COLON
2920//
2921bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2922{
2923 TSourceLoc loc = token.loc;
2924 if (! acceptTokenClass(EHTokDefault))
2925 return false;
2926
2927 if (! acceptTokenClass(EHTokColon)) {
2928 expected(":");
2929 return false;
2930 }
2931
2932 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2933
2934 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002935}
2936
John Kessenich19b92ff2016-06-19 11:50:34 -06002937// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06002938// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
2939// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002940//
2941void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2942{
2943 arraySizes = nullptr;
2944
steve-lunarg7b211a32016-10-13 12:26:18 -06002945 // Early-out if there aren't any array dimensions
2946 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06002947 return;
2948
steve-lunarg7b211a32016-10-13 12:26:18 -06002949 // 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 -06002950 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06002951
2952 // Collect each array dimension.
2953 while (acceptTokenClass(EHTokLeftBracket)) {
2954 TSourceLoc loc = token.loc;
2955 TIntermTyped* sizeExpr = nullptr;
2956
2957 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
2958 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
2959
2960 if (! acceptTokenClass(EHTokRightBracket)) {
2961 expected("]");
2962 return;
2963 }
2964
2965 if (hasArraySize) {
2966 TArraySize arraySize;
2967 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2968 arraySizes->addInnerSize(arraySize);
2969 } else {
2970 arraySizes->addInnerSize(0); // sized by initializers.
2971 }
steve-lunarg265c0612016-09-27 10:57:35 -06002972 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002973}
2974
John Kessenich630dd7d2016-06-12 23:52:12 -06002975// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002976// : COLON semantic // optional
2977// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2978// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002979// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002980// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002981//
John Kessenich7735b942016-09-05 12:40:06 -06002982void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002983{
John Kessenich630dd7d2016-06-12 23:52:12 -06002984 do {
2985 // COLON
2986 if (acceptTokenClass(EHTokColon)) {
2987 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002988 if (peekTokenClass(EHTokLayout))
2989 acceptLayoutQualifierList(qualifier);
2990 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002991 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002992 if (! acceptTokenClass(EHTokLeftParen)) {
2993 expected("(");
2994 return;
2995 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002996 HlslToken locationToken;
2997 if (! acceptIdentifier(locationToken)) {
2998 expected("c[subcomponent][.component]");
2999 return;
3000 }
3001 HlslToken componentToken;
3002 if (acceptTokenClass(EHTokDot)) {
3003 if (! acceptIdentifier(componentToken)) {
3004 expected("component");
3005 return;
3006 }
3007 }
John Kessenich630dd7d2016-06-12 23:52:12 -06003008 if (! acceptTokenClass(EHTokRightParen)) {
3009 expected(")");
3010 break;
3011 }
John Kessenich7735b942016-09-05 12:40:06 -06003012 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003013 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06003014 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06003015 return;
3016 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06003017 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
3018 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003019 if (! acceptTokenClass(EHTokLeftParen)) {
3020 expected("(");
3021 return;
3022 }
John Kessenichb38f0712016-07-30 10:29:54 -06003023 HlslToken registerDesc; // for Type#
3024 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003025 if (! acceptIdentifier(registerDesc)) {
3026 expected("register number description");
3027 return;
3028 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003029 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3030 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003031 // Then we didn't really see the registerDesc yet, it was
3032 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003033 profile = registerDesc;
3034 if (! acceptIdentifier(registerDesc)) {
3035 expected("register number description");
3036 return;
3037 }
3038 }
John Kessenichb38f0712016-07-30 10:29:54 -06003039 int subComponent = 0;
3040 if (acceptTokenClass(EHTokLeftBracket)) {
3041 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3042 if (! peekTokenClass(EHTokIntConstant)) {
3043 expected("literal integer");
3044 return;
3045 }
3046 subComponent = token.i;
3047 advanceToken();
3048 if (! acceptTokenClass(EHTokRightBracket)) {
3049 expected("]");
3050 break;
3051 }
3052 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003053 // (COMMA SPACEN)opt
3054 HlslToken spaceDesc;
3055 if (acceptTokenClass(EHTokComma)) {
3056 if (! acceptIdentifier(spaceDesc)) {
3057 expected ("space identifier");
3058 return;
3059 }
3060 }
3061 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003062 if (! acceptTokenClass(EHTokRightParen)) {
3063 expected(")");
3064 break;
3065 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003066 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003067 } else {
3068 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003069 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003070 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003071 } else if (peekTokenClass(EHTokLeftAngle))
3072 acceptAnnotations(qualifier);
3073 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003074 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003075
John Kessenich630dd7d2016-06-12 23:52:12 -06003076 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003077}
3078
John Kesseniche01a9bc2016-03-12 20:11:22 -07003079} // end namespace glslang