blob: 10dfcc832449bc1a99ad96e8a6d7aca013ad564c [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)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600311 // function_parameters
John Kesseniche82061d2016-09-27 14:38:57 -0600312 TFunction& function = *new TFunction(idToken.string, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600313 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600314 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600315 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600316
John Kessenichd5ed0b62016-07-04 17:32:45 -0600317 // compound_statement (function body definition) or just a prototype?
318 if (peekTokenClass(EHTokLeftBrace)) {
319 if (list)
320 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600321 if (typedefDecl)
322 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
steve-lunarg1868b142016-10-20 13:07:10 -0600323 return acceptFunctionDefinition(function, node, attributes);
John Kessenich5e69ec62016-07-05 00:02:40 -0600324 } else {
325 if (typedefDecl)
326 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600327 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600328 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600329 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600330 // A variable declaration. Fix the storage qualifier if it's a global.
331 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
332 declaredType.getQualifier().storage = EvqUniform;
333
John Kesseniche82061d2016-09-27 14:38:57 -0600334 // We can handle multiple variables per type declaration, so
335 // the number of types can expand when arrayness is different.
336 TType variableType;
337 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600338
John Kesseniche82061d2016-09-27 14:38:57 -0600339 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600340 TArraySizes* arraySizes = nullptr;
341 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600342
John Kesseniche82061d2016-09-27 14:38:57 -0600343 // Fix arrayness in the variableType
344 if (declaredType.isImplicitlySizedArray()) {
345 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
346 // of different sizes, for this case sharing the shallow copy of arrayness
347 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
348 variableType.newArraySizes(declaredType.getArraySizes());
349 }
350 if (arraySizes || variableType.isArray()) {
351 // In the most general case, arrayness is potentially coming both from the
352 // declared type and from the variable: "int[] a[];" or just one or the other.
353 // Merge it all to the variableType, so all arrayness is part of the variableType.
354 parseContext.arrayDimMerge(variableType, arraySizes);
355 }
356
LoopDawg4886f692016-06-29 10:58:58 -0600357 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600358 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600359 if (! acceptSamplerState())
360 return false;
361 }
362
John Kessenichd5ed0b62016-07-04 17:32:45 -0600363 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600364 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600365
366 // EQUAL assignment_expression
367 TIntermTyped* expressionNode = nullptr;
368 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600369 if (typedefDecl)
370 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600371 if (! acceptAssignmentExpression(expressionNode)) {
372 expected("initializer");
373 return false;
374 }
375 }
376
John Kessenich6dbc0a72016-09-27 19:13:05 -0600377 // Hand off the actual declaration
378
379 // TODO: things scoped within an annotation need their own name space;
380 // TODO: strings are not yet handled.
381 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
382 if (typedefDecl)
383 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
384 else if (variableType.getBasicType() == EbtBlock)
385 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
386 else {
John Kessenichf571d0c2016-10-01 12:35:01 -0600387 if (variableType.getQualifier().storage == EvqUniform && ! variableType.isOpaque()) {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600388 // this isn't really an individual variable, but a member of the $Global buffer
389 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
390 } else {
391 // Declare the variable and add any initializer code to the AST.
392 // The top-level node is always made into an aggregate, as that's
393 // historically how the AST has been.
394 node = intermediate.growAggregate(node,
395 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
396 expressionNode),
397 idToken.loc);
398 }
399 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600400 }
John Kessenich5f934b02016-03-13 17:58:25 -0600401 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600402
403 if (acceptTokenClass(EHTokComma)) {
404 list = true;
405 continue;
406 }
407 };
408
409 // The top-level node is a sequence.
410 if (node != nullptr)
411 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700412
John Kessenich078d7f22016-03-14 10:02:11 -0600413 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600414 if (! acceptTokenClass(EHTokSemicolon)) {
415 expected(";");
416 return false;
417 }
418
John Kesseniche01a9bc2016-03-12 20:11:22 -0700419 return true;
420}
421
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600422// control_declaration
423// : fully_specified_type identifier EQUAL expression
424//
425bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
426{
427 node = nullptr;
428
429 // fully_specified_type
430 TType type;
431 if (! acceptFullySpecifiedType(type))
432 return false;
433
434 // identifier
435 HlslToken idToken;
436 if (! acceptIdentifier(idToken)) {
437 expected("identifier");
438 return false;
439 }
440
441 // EQUAL
442 TIntermTyped* expressionNode = nullptr;
443 if (! acceptTokenClass(EHTokAssign)) {
444 expected("=");
445 return false;
446 }
447
448 // expression
449 if (! acceptExpression(expressionNode)) {
450 expected("initializer");
451 return false;
452 }
453
John Kesseniche82061d2016-09-27 14:38:57 -0600454 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600455
456 return true;
457}
458
John Kessenich87142c72016-03-12 20:24:24 -0700459// fully_specified_type
460// : type_specifier
461// | type_qualifier type_specifier
462//
463bool HlslGrammar::acceptFullySpecifiedType(TType& type)
464{
465 // type_qualifier
466 TQualifier qualifier;
467 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600468 if (! acceptQualifier(qualifier))
469 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600470 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700471
472 // type_specifier
473 if (! acceptType(type))
474 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600475 if (type.getBasicType() == EbtBlock) {
476 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600477 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600478 // further, it can create an anonymous instance of the block
479 if (peekTokenClass(EHTokSemicolon))
480 parseContext.declareBlock(loc, type);
steve-lunargbb0183f2016-10-04 16:58:14 -0600481 } else {
482 // Some qualifiers are set when parsing the type. Merge those with
483 // whatever comes from acceptQualifier.
484 assert(qualifier.layoutFormat == ElfNone);
steve-lunargf49cdf42016-11-17 15:04:20 -0700485
steve-lunargbb0183f2016-10-04 16:58:14 -0600486 qualifier.layoutFormat = type.getQualifier().layoutFormat;
steve-lunarg3226b082016-10-26 19:18:55 -0600487 qualifier.precision = type.getQualifier().precision;
steve-lunargf49cdf42016-11-17 15:04:20 -0700488
489 if (type.getQualifier().storage == EvqVaryingOut)
490 qualifier.storage = type.getQualifier().storage;
491
492 type.getQualifier() = qualifier;
steve-lunargbb0183f2016-10-04 16:58:14 -0600493 }
John Kessenich87142c72016-03-12 20:24:24 -0700494
495 return true;
496}
497
John Kessenich630dd7d2016-06-12 23:52:12 -0600498// type_qualifier
499// : qualifier qualifier ...
500//
501// Zero or more of these, so this can't return false.
502//
John Kessenichb9e39122016-08-17 10:22:08 -0600503bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700504{
John Kessenich630dd7d2016-06-12 23:52:12 -0600505 do {
506 switch (peek()) {
507 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600508 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600509 break;
510 case EHTokExtern:
511 // TODO: no meaning in glslang?
512 break;
513 case EHTokShared:
514 // TODO: hint
515 break;
516 case EHTokGroupShared:
517 qualifier.storage = EvqShared;
518 break;
519 case EHTokUniform:
520 qualifier.storage = EvqUniform;
521 break;
522 case EHTokConst:
523 qualifier.storage = EvqConst;
524 break;
525 case EHTokVolatile:
526 qualifier.volatil = true;
527 break;
528 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600529 qualifier.smooth = true;
530 break;
531 case EHTokCentroid:
532 qualifier.centroid = true;
533 break;
534 case EHTokNointerpolation:
535 qualifier.flat = true;
536 break;
537 case EHTokNoperspective:
538 qualifier.nopersp = true;
539 break;
540 case EHTokSample:
541 qualifier.sample = true;
542 break;
543 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600544 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600545 break;
546 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600547 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600548 break;
549 case EHTokPrecise:
550 qualifier.noContraction = true;
551 break;
LoopDawg9249c702016-07-12 20:44:32 -0600552 case EHTokIn:
553 qualifier.storage = EvqIn;
554 break;
555 case EHTokOut:
556 qualifier.storage = EvqOut;
557 break;
558 case EHTokInOut:
559 qualifier.storage = EvqInOut;
560 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600561 case EHTokLayout:
562 if (! acceptLayoutQualifierList(qualifier))
563 return false;
564 continue;
steve-lunargf49cdf42016-11-17 15:04:20 -0700565
566 // GS geometries: these are specified on stage input variables, and are an error (not verified here)
567 // for output variables.
568 case EHTokPoint:
569 qualifier.storage = EvqIn;
570 if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
571 return false;
572 break;
573 case EHTokLine:
574 qualifier.storage = EvqIn;
575 if (!parseContext.handleInputGeometry(token.loc, ElgLines))
576 return false;
577 break;
578 case EHTokTriangle:
579 qualifier.storage = EvqIn;
580 if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
581 return false;
582 break;
583 case EHTokLineAdj:
584 qualifier.storage = EvqIn;
585 if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
586 return false;
587 break;
588 case EHTokTriangleAdj:
589 qualifier.storage = EvqIn;
590 if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
591 return false;
592 break;
593
John Kessenich630dd7d2016-06-12 23:52:12 -0600594 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600595 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600596 }
597 advanceToken();
598 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700599}
600
John Kessenichb9e39122016-08-17 10:22:08 -0600601// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600602// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600603//
604// layout_qualifier
605// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600606// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600607//
608// Zero or more of these, so this can't return false.
609//
610bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
611{
612 if (! acceptTokenClass(EHTokLayout))
613 return false;
614
615 // LEFT_PAREN
616 if (! acceptTokenClass(EHTokLeftParen))
617 return false;
618
619 do {
620 // identifier
621 HlslToken idToken;
622 if (! acceptIdentifier(idToken))
623 break;
624
625 // EQUAL expression
626 if (acceptTokenClass(EHTokAssign)) {
627 TIntermTyped* expr;
628 if (! acceptConditionalExpression(expr)) {
629 expected("expression");
630 return false;
631 }
632 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
633 } else
634 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
635
636 // COMMA
637 if (! acceptTokenClass(EHTokComma))
638 break;
639 } while (true);
640
641 // RIGHT_PAREN
642 if (! acceptTokenClass(EHTokRightParen)) {
643 expected(")");
644 return false;
645 }
646
647 return true;
648}
649
LoopDawg6daaa4f2016-06-23 19:13:48 -0600650// template_type
651// : FLOAT
652// | DOUBLE
653// | INT
654// | DWORD
655// | UINT
656// | BOOL
657//
steve-lunargf49cdf42016-11-17 15:04:20 -0700658bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
LoopDawg6daaa4f2016-06-23 19:13:48 -0600659{
660 switch (peek()) {
661 case EHTokFloat:
662 basicType = EbtFloat;
663 break;
664 case EHTokDouble:
665 basicType = EbtDouble;
666 break;
667 case EHTokInt:
668 case EHTokDword:
669 basicType = EbtInt;
670 break;
671 case EHTokUint:
672 basicType = EbtUint;
673 break;
674 case EHTokBool:
675 basicType = EbtBool;
676 break;
677 default:
678 return false;
679 }
680
681 advanceToken();
682
683 return true;
684}
685
686// vector_template_type
687// : VECTOR
688// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
689//
690bool HlslGrammar::acceptVectorTemplateType(TType& type)
691{
692 if (! acceptTokenClass(EHTokVector))
693 return false;
694
695 if (! acceptTokenClass(EHTokLeftAngle)) {
696 // in HLSL, 'vector' alone means float4.
697 new(&type) TType(EbtFloat, EvqTemporary, 4);
698 return true;
699 }
700
701 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700702 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600703 expected("scalar type");
704 return false;
705 }
706
707 // COMMA
708 if (! acceptTokenClass(EHTokComma)) {
709 expected(",");
710 return false;
711 }
712
713 // integer
714 if (! peekTokenClass(EHTokIntConstant)) {
715 expected("literal integer");
716 return false;
717 }
718
719 TIntermTyped* vecSize;
720 if (! acceptLiteral(vecSize))
721 return false;
722
723 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
724
725 new(&type) TType(basicType, EvqTemporary, vecSizeI);
726
727 if (vecSizeI == 1)
728 type.makeVector();
729
730 if (!acceptTokenClass(EHTokRightAngle)) {
731 expected("right angle bracket");
732 return false;
733 }
734
735 return true;
736}
737
738// matrix_template_type
739// : MATRIX
740// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
741//
742bool HlslGrammar::acceptMatrixTemplateType(TType& type)
743{
744 if (! acceptTokenClass(EHTokMatrix))
745 return false;
746
747 if (! acceptTokenClass(EHTokLeftAngle)) {
748 // in HLSL, 'matrix' alone means float4x4.
749 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
750 return true;
751 }
752
753 TBasicType basicType;
steve-lunargf49cdf42016-11-17 15:04:20 -0700754 if (! acceptTemplateVecMatBasicType(basicType)) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600755 expected("scalar type");
756 return false;
757 }
758
759 // COMMA
760 if (! acceptTokenClass(EHTokComma)) {
761 expected(",");
762 return false;
763 }
764
765 // integer rows
766 if (! peekTokenClass(EHTokIntConstant)) {
767 expected("literal integer");
768 return false;
769 }
770
771 TIntermTyped* rows;
772 if (! acceptLiteral(rows))
773 return false;
774
775 // COMMA
776 if (! acceptTokenClass(EHTokComma)) {
777 expected(",");
778 return false;
779 }
780
781 // integer cols
782 if (! peekTokenClass(EHTokIntConstant)) {
783 expected("literal integer");
784 return false;
785 }
786
787 TIntermTyped* cols;
788 if (! acceptLiteral(cols))
789 return false;
790
791 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600792 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
793 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600794
795 if (!acceptTokenClass(EHTokRightAngle)) {
796 expected("right angle bracket");
797 return false;
798 }
799
800 return true;
801}
802
steve-lunargf49cdf42016-11-17 15:04:20 -0700803// layout_geometry
804// : LINESTREAM
805// | POINTSTREAM
806// | TRIANGLESTREAM
807//
808bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
809{
810 // read geometry type
811 const EHlslTokenClass geometryType = peek();
812
813 switch (geometryType) {
814 case EHTokPointStream: geometry = ElgPoints; break;
815 case EHTokLineStream: geometry = ElgLineStrip; break;
816 case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
817 default:
818 return false; // not a layout geometry
819 }
820
821 advanceToken(); // consume the layout keyword
822 return true;
823}
824
825// stream_out_template_type
826// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
827//
828bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
829{
830 geometry = ElgNone;
831
832 if (! acceptOutputPrimitiveGeometry(geometry))
833 return false;
834
835 if (! acceptTokenClass(EHTokLeftAngle))
836 return false;
837
838 if (! acceptType(type)) {
839 expected("stream output type");
840 return false;
841 }
842
843 type.getQualifier().storage = EvqVaryingOut;
844
845 if (! acceptTokenClass(EHTokRightAngle)) {
846 expected("right angle bracket");
847 return false;
848 }
849
850 return true;
851}
852
John Kessenicha1e2d492016-09-20 13:22:58 -0600853// annotations
854// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600855//
John Kessenicha1e2d492016-09-20 13:22:58 -0600856bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600857{
John Kessenicha1e2d492016-09-20 13:22:58 -0600858 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600859 return false;
860
John Kessenicha1e2d492016-09-20 13:22:58 -0600861 // note that we are nesting a name space
862 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600863
864 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
865 do {
866 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
867 while (acceptTokenClass(EHTokSemicolon))
868 ;
869
870 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600871 break;
John Kessenich86f71382016-09-19 20:23:18 -0600872
873 // declaration
874 TIntermNode* node;
875 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600876 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600877 return false;
878 }
879 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600880
881 parseContext.unnestAnnotations();
882 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600883}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600884
LoopDawg4886f692016-06-29 10:58:58 -0600885// sampler_type
886// : SAMPLER
887// | SAMPLER1D
888// | SAMPLER2D
889// | SAMPLER3D
890// | SAMPLERCUBE
891// | SAMPLERSTATE
892// | SAMPLERCOMPARISONSTATE
893bool HlslGrammar::acceptSamplerType(TType& type)
894{
895 // read sampler type
896 const EHlslTokenClass samplerType = peek();
897
LoopDawga78b0292016-07-19 14:28:05 -0600898 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600899 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600900
LoopDawga78b0292016-07-19 14:28:05 -0600901 bool isShadow = false;
902
LoopDawg4886f692016-06-29 10:58:58 -0600903 switch (samplerType) {
904 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600905 case EHTokSampler1d: /*dim = Esd1D*/; break;
906 case EHTokSampler2d: /*dim = Esd2D*/; break;
907 case EHTokSampler3d: /*dim = Esd3D*/; break;
908 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600909 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600910 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600911 default:
912 return false; // not a sampler declaration
913 }
914
915 advanceToken(); // consume the sampler type keyword
916
917 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600918
919 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600920 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600921
922 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
923
924 return true;
925}
926
927// texture_type
928// | BUFFER
929// | TEXTURE1D
930// | TEXTURE1DARRAY
931// | TEXTURE2D
932// | TEXTURE2DARRAY
933// | TEXTURE3D
934// | TEXTURECUBE
935// | TEXTURECUBEARRAY
936// | TEXTURE2DMS
937// | TEXTURE2DMSARRAY
steve-lunargbb0183f2016-10-04 16:58:14 -0600938// | RWBUFFER
939// | RWTEXTURE1D
940// | RWTEXTURE1DARRAY
941// | RWTEXTURE2D
942// | RWTEXTURE2DARRAY
943// | RWTEXTURE3D
944
LoopDawg4886f692016-06-29 10:58:58 -0600945bool HlslGrammar::acceptTextureType(TType& type)
946{
947 const EHlslTokenClass textureType = peek();
948
949 TSamplerDim dim = EsdNone;
950 bool array = false;
951 bool ms = false;
steve-lunargbb0183f2016-10-04 16:58:14 -0600952 bool image = false;
LoopDawg4886f692016-06-29 10:58:58 -0600953
954 switch (textureType) {
955 case EHTokBuffer: dim = EsdBuffer; break;
956 case EHTokTexture1d: dim = Esd1D; break;
957 case EHTokTexture1darray: dim = Esd1D; array = true; break;
958 case EHTokTexture2d: dim = Esd2D; break;
959 case EHTokTexture2darray: dim = Esd2D; array = true; break;
960 case EHTokTexture3d: dim = Esd3D; break;
961 case EHTokTextureCube: dim = EsdCube; break;
962 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
963 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
964 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
steve-lunargbb0183f2016-10-04 16:58:14 -0600965 case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
966 case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
967 case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
968 case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
969 case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
970 case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600971 default:
972 return false; // not a texture declaration
973 }
974
975 advanceToken(); // consume the texture object keyword
976
977 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
978
979 TIntermTyped* msCount = nullptr;
980
steve-lunargbb0183f2016-10-04 16:58:14 -0600981 // texture type: required for multisample types and RWBuffer/RWTextures!
LoopDawg4886f692016-06-29 10:58:58 -0600982 if (acceptTokenClass(EHTokLeftAngle)) {
983 if (! acceptType(txType)) {
984 expected("scalar or vector type");
985 return false;
986 }
987
988 const TBasicType basicRetType = txType.getBasicType() ;
989
990 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
991 unimplemented("basic type in texture");
992 return false;
993 }
994
steve-lunargd53f7172016-07-27 15:46:48 -0600995 // Buffers can handle small mats if they fit in 4 components
996 if (dim == EsdBuffer && txType.isMatrix()) {
997 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
998 expected("components < 4 in matrix buffer type");
999 return false;
1000 }
1001
1002 // TODO: except we don't handle it yet...
1003 unimplemented("matrix type in buffer");
1004 return false;
1005 }
1006
LoopDawg4886f692016-06-29 10:58:58 -06001007 if (!txType.isScalar() && !txType.isVector()) {
1008 expected("scalar or vector type");
1009 return false;
1010 }
1011
LoopDawg4886f692016-06-29 10:58:58 -06001012 if (ms && acceptTokenClass(EHTokComma)) {
1013 // read sample count for multisample types, if given
1014 if (! peekTokenClass(EHTokIntConstant)) {
1015 expected("multisample count");
1016 return false;
1017 }
1018
1019 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
1020 return false;
1021 }
1022
1023 if (! acceptTokenClass(EHTokRightAngle)) {
1024 expected("right angle bracket");
1025 return false;
1026 }
1027 } else if (ms) {
1028 expected("texture type for multisample");
1029 return false;
steve-lunargbb0183f2016-10-04 16:58:14 -06001030 } else if (image) {
1031 expected("type for RWTexture/RWBuffer");
1032 return false;
LoopDawg4886f692016-06-29 10:58:58 -06001033 }
1034
1035 TArraySizes* arraySizes = nullptr;
steve-lunarg4f2da272016-10-10 15:24:57 -06001036 const bool shadow = false; // declared on the sampler
LoopDawg4886f692016-06-29 10:58:58 -06001037
1038 TSampler sampler;
steve-lunargbb0183f2016-10-04 16:58:14 -06001039 TLayoutFormat format = ElfNone;
steve-lunargd53f7172016-07-27 15:46:48 -06001040
steve-lunarg4f2da272016-10-10 15:24:57 -06001041 // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
1042 if (image || dim == EsdBuffer)
1043 format = parseContext.getLayoutFromTxType(token.loc, txType);
steve-lunargbb0183f2016-10-04 16:58:14 -06001044
1045 // Non-image Buffers are combined
1046 if (dim == EsdBuffer && !image) {
steve-lunargd53f7172016-07-27 15:46:48 -06001047 sampler.set(txType.getBasicType(), dim, array);
1048 } else {
1049 // DX10 textures are separated. TODO: DX9.
steve-lunargbb0183f2016-10-04 16:58:14 -06001050 if (image) {
1051 sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
1052 } else {
1053 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
1054 }
steve-lunargd53f7172016-07-27 15:46:48 -06001055 }
steve-lunarg8b0227c2016-10-14 16:40:32 -06001056
1057 // Remember the declared vector size.
1058 sampler.vectorSize = txType.getVectorSize();
LoopDawg4886f692016-06-29 10:58:58 -06001059
1060 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
steve-lunargbb0183f2016-10-04 16:58:14 -06001061 type.getQualifier().layoutFormat = format;
LoopDawg4886f692016-06-29 10:58:58 -06001062
1063 return true;
1064}
1065
1066
John Kessenich87142c72016-03-12 20:24:24 -07001067// If token is for a type, update 'type' with the type information,
1068// and return true and advance.
1069// Otherwise, return false, and don't advance
1070bool HlslGrammar::acceptType(TType& type)
1071{
steve-lunarg3226b082016-10-26 19:18:55 -06001072 // Basic types for min* types, broken out here in case of future
1073 // changes, e.g, to use native halfs.
1074 static const TBasicType min16float_bt = EbtFloat;
1075 static const TBasicType min10float_bt = EbtFloat;
1076 static const TBasicType min16int_bt = EbtInt;
1077 static const TBasicType min12int_bt = EbtInt;
1078 static const TBasicType min16uint_bt = EbtUint;
1079
John Kessenich9c86c6a2016-05-03 22:49:24 -06001080 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -06001081 case EHTokVector:
1082 return acceptVectorTemplateType(type);
1083 break;
1084
1085 case EHTokMatrix:
1086 return acceptMatrixTemplateType(type);
1087 break;
1088
steve-lunargf49cdf42016-11-17 15:04:20 -07001089 case EHTokPointStream: // fall through
1090 case EHTokLineStream: // ...
1091 case EHTokTriangleStream: // ...
1092 {
1093 TLayoutGeometry geometry;
1094 if (! acceptStreamOutTemplateType(type, geometry))
1095 return false;
1096
1097 if (! parseContext.handleOutputGeometry(token.loc, geometry))
1098 return false;
1099
1100 return true;
1101 }
1102
LoopDawg4886f692016-06-29 10:58:58 -06001103 case EHTokSampler: // fall through
1104 case EHTokSampler1d: // ...
1105 case EHTokSampler2d: // ...
1106 case EHTokSampler3d: // ...
1107 case EHTokSamplerCube: // ...
1108 case EHTokSamplerState: // ...
1109 case EHTokSamplerComparisonState: // ...
1110 return acceptSamplerType(type);
1111 break;
1112
1113 case EHTokBuffer: // fall through
1114 case EHTokTexture1d: // ...
1115 case EHTokTexture1darray: // ...
1116 case EHTokTexture2d: // ...
1117 case EHTokTexture2darray: // ...
1118 case EHTokTexture3d: // ...
1119 case EHTokTextureCube: // ...
1120 case EHTokTextureCubearray: // ...
1121 case EHTokTexture2DMS: // ...
1122 case EHTokTexture2DMSarray: // ...
steve-lunargbb0183f2016-10-04 16:58:14 -06001123 case EHTokRWTexture1d: // ...
1124 case EHTokRWTexture1darray: // ...
1125 case EHTokRWTexture2d: // ...
1126 case EHTokRWTexture2darray: // ...
1127 case EHTokRWTexture3d: // ...
1128 case EHTokRWBuffer: // ...
LoopDawg4886f692016-06-29 10:58:58 -06001129 return acceptTextureType(type);
1130 break;
1131
John Kesseniche6e74942016-06-11 16:43:14 -06001132 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -06001133 case EHTokCBuffer:
1134 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -06001135 return acceptStruct(type);
1136 break;
1137
1138 case EHTokIdentifier:
1139 // An identifier could be for a user-defined type.
1140 // Note we cache the symbol table lookup, to save for a later rule
1141 // when this is not a type.
1142 token.symbol = parseContext.symbolTable.find(*token.string);
1143 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
1144 type.shallowCopy(token.symbol->getType());
1145 advanceToken();
1146 return true;
1147 } else
1148 return false;
1149
John Kessenich71351de2016-06-08 12:50:56 -06001150 case EHTokVoid:
1151 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -07001152 break;
John Kessenich71351de2016-06-08 12:50:56 -06001153
John Kessenicha1e2d492016-09-20 13:22:58 -06001154 case EHTokString:
1155 new(&type) TType(EbtString);
1156 break;
1157
John Kessenich87142c72016-03-12 20:24:24 -07001158 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -06001159 new(&type) TType(EbtFloat);
1160 break;
John Kessenich87142c72016-03-12 20:24:24 -07001161 case EHTokFloat1:
1162 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001163 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001164 break;
John Kessenich87142c72016-03-12 20:24:24 -07001165 case EHTokFloat2:
1166 new(&type) TType(EbtFloat, EvqTemporary, 2);
1167 break;
1168 case EHTokFloat3:
1169 new(&type) TType(EbtFloat, EvqTemporary, 3);
1170 break;
1171 case EHTokFloat4:
1172 new(&type) TType(EbtFloat, EvqTemporary, 4);
1173 break;
1174
John Kessenich71351de2016-06-08 12:50:56 -06001175 case EHTokDouble:
1176 new(&type) TType(EbtDouble);
1177 break;
1178 case EHTokDouble1:
1179 new(&type) TType(EbtDouble);
1180 type.makeVector();
1181 break;
1182 case EHTokDouble2:
1183 new(&type) TType(EbtDouble, EvqTemporary, 2);
1184 break;
1185 case EHTokDouble3:
1186 new(&type) TType(EbtDouble, EvqTemporary, 3);
1187 break;
1188 case EHTokDouble4:
1189 new(&type) TType(EbtDouble, EvqTemporary, 4);
1190 break;
1191
1192 case EHTokInt:
1193 case EHTokDword:
1194 new(&type) TType(EbtInt);
1195 break;
1196 case EHTokInt1:
1197 new(&type) TType(EbtInt);
1198 type.makeVector();
1199 break;
John Kessenich87142c72016-03-12 20:24:24 -07001200 case EHTokInt2:
1201 new(&type) TType(EbtInt, EvqTemporary, 2);
1202 break;
1203 case EHTokInt3:
1204 new(&type) TType(EbtInt, EvqTemporary, 3);
1205 break;
1206 case EHTokInt4:
1207 new(&type) TType(EbtInt, EvqTemporary, 4);
1208 break;
1209
John Kessenich71351de2016-06-08 12:50:56 -06001210 case EHTokUint:
1211 new(&type) TType(EbtUint);
1212 break;
1213 case EHTokUint1:
1214 new(&type) TType(EbtUint);
1215 type.makeVector();
1216 break;
1217 case EHTokUint2:
1218 new(&type) TType(EbtUint, EvqTemporary, 2);
1219 break;
1220 case EHTokUint3:
1221 new(&type) TType(EbtUint, EvqTemporary, 3);
1222 break;
1223 case EHTokUint4:
1224 new(&type) TType(EbtUint, EvqTemporary, 4);
1225 break;
1226
LoopDawg6daaa4f2016-06-23 19:13:48 -06001227
John Kessenich71351de2016-06-08 12:50:56 -06001228 case EHTokBool:
1229 new(&type) TType(EbtBool);
1230 break;
1231 case EHTokBool1:
1232 new(&type) TType(EbtBool);
1233 type.makeVector();
1234 break;
John Kessenich87142c72016-03-12 20:24:24 -07001235 case EHTokBool2:
1236 new(&type) TType(EbtBool, EvqTemporary, 2);
1237 break;
1238 case EHTokBool3:
1239 new(&type) TType(EbtBool, EvqTemporary, 3);
1240 break;
1241 case EHTokBool4:
1242 new(&type) TType(EbtBool, EvqTemporary, 4);
1243 break;
1244
steve-lunarg3226b082016-10-26 19:18:55 -06001245 case EHTokMin16float:
1246 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1247 break;
1248 case EHTokMin16float1:
1249 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1250 type.makeVector();
1251 break;
1252 case EHTokMin16float2:
1253 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1254 break;
1255 case EHTokMin16float3:
1256 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1257 break;
1258 case EHTokMin16float4:
1259 new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1260 break;
1261
1262 case EHTokMin10float:
1263 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1264 break;
1265 case EHTokMin10float1:
1266 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1267 type.makeVector();
1268 break;
1269 case EHTokMin10float2:
1270 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1271 break;
1272 case EHTokMin10float3:
1273 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1274 break;
1275 case EHTokMin10float4:
1276 new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1277 break;
1278
1279 case EHTokMin16int:
1280 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1281 break;
1282 case EHTokMin16int1:
1283 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1284 type.makeVector();
1285 break;
1286 case EHTokMin16int2:
1287 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1288 break;
1289 case EHTokMin16int3:
1290 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1291 break;
1292 case EHTokMin16int4:
1293 new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1294 break;
1295
1296 case EHTokMin12int:
1297 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1298 break;
1299 case EHTokMin12int1:
1300 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1301 type.makeVector();
1302 break;
1303 case EHTokMin12int2:
1304 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1305 break;
1306 case EHTokMin12int3:
1307 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1308 break;
1309 case EHTokMin12int4:
1310 new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1311 break;
1312
1313 case EHTokMin16uint:
1314 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1315 break;
1316 case EHTokMin16uint1:
1317 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1318 type.makeVector();
1319 break;
1320 case EHTokMin16uint2:
1321 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1322 break;
1323 case EHTokMin16uint3:
1324 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1325 break;
1326 case EHTokMin16uint4:
1327 new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1328 break;
1329
John Kessenich0133c122016-05-20 12:17:26 -06001330 case EHTokInt1x1:
1331 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1332 break;
1333 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001334 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001335 break;
1336 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001337 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001338 break;
1339 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001340 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001341 break;
1342 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001343 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001344 break;
1345 case EHTokInt2x2:
1346 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1347 break;
1348 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001349 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001350 break;
1351 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001352 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001353 break;
1354 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001355 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001356 break;
1357 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001358 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001359 break;
1360 case EHTokInt3x3:
1361 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1362 break;
1363 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001364 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001365 break;
1366 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001367 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001368 break;
1369 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001370 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001371 break;
1372 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001373 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001374 break;
1375 case EHTokInt4x4:
1376 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1377 break;
1378
John Kessenich71351de2016-06-08 12:50:56 -06001379 case EHTokUint1x1:
1380 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1381 break;
1382 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001383 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001384 break;
1385 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001386 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001387 break;
1388 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001389 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001390 break;
1391 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001392 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001393 break;
1394 case EHTokUint2x2:
1395 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1396 break;
1397 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001398 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001399 break;
1400 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001401 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001402 break;
1403 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001404 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001405 break;
1406 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001407 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001408 break;
1409 case EHTokUint3x3:
1410 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1411 break;
1412 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001413 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001414 break;
1415 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001416 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001417 break;
1418 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001419 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001420 break;
1421 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001422 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001423 break;
1424 case EHTokUint4x4:
1425 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1426 break;
1427
1428 case EHTokBool1x1:
1429 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1430 break;
1431 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001432 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001433 break;
1434 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001435 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001436 break;
1437 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001438 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001439 break;
1440 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001441 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001442 break;
1443 case EHTokBool2x2:
1444 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1445 break;
1446 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001447 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001448 break;
1449 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001450 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001451 break;
1452 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001453 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001454 break;
1455 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001456 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001457 break;
1458 case EHTokBool3x3:
1459 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1460 break;
1461 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001462 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001463 break;
1464 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001465 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001466 break;
1467 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001468 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001469 break;
1470 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001471 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001472 break;
1473 case EHTokBool4x4:
1474 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1475 break;
1476
John Kessenich0133c122016-05-20 12:17:26 -06001477 case EHTokFloat1x1:
1478 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1479 break;
1480 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001481 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001482 break;
1483 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001484 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001485 break;
1486 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001487 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001488 break;
1489 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001490 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001491 break;
John Kessenich87142c72016-03-12 20:24:24 -07001492 case EHTokFloat2x2:
1493 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1494 break;
1495 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001496 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001497 break;
1498 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001499 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001500 break;
John Kessenich0133c122016-05-20 12:17:26 -06001501 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001502 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001503 break;
John Kessenich87142c72016-03-12 20:24:24 -07001504 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001505 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001506 break;
1507 case EHTokFloat3x3:
1508 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1509 break;
1510 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001511 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001512 break;
John Kessenich0133c122016-05-20 12:17:26 -06001513 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001514 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001515 break;
John Kessenich87142c72016-03-12 20:24:24 -07001516 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001517 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001518 break;
1519 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001520 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001521 break;
1522 case EHTokFloat4x4:
1523 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1524 break;
1525
John Kessenich0133c122016-05-20 12:17:26 -06001526 case EHTokDouble1x1:
1527 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1528 break;
1529 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001530 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001531 break;
1532 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001533 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001534 break;
1535 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001536 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001537 break;
1538 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001539 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001540 break;
1541 case EHTokDouble2x2:
1542 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1543 break;
1544 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001545 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001546 break;
1547 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001548 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001549 break;
1550 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001551 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001552 break;
1553 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001554 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001555 break;
1556 case EHTokDouble3x3:
1557 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1558 break;
1559 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001560 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001561 break;
1562 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001563 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001564 break;
1565 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001566 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001567 break;
1568 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001569 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001570 break;
1571 case EHTokDouble4x4:
1572 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1573 break;
1574
John Kessenich87142c72016-03-12 20:24:24 -07001575 default:
1576 return false;
1577 }
1578
1579 advanceToken();
1580
1581 return true;
1582}
1583
John Kesseniche6e74942016-06-11 16:43:14 -06001584// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001585// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1586// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1587//
1588// struct_type
1589// : STRUCT
1590// | CBUFFER
1591// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001592//
1593bool HlslGrammar::acceptStruct(TType& type)
1594{
John Kessenichb804de62016-09-05 12:19:18 -06001595 // This storage qualifier will tell us whether it's an AST
1596 // block type or just a generic structure type.
1597 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001598
1599 // CBUFFER
1600 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001601 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001602 // TBUFFER
1603 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001604 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001605 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001606 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001607 return false;
1608
1609 // IDENTIFIER
1610 TString structName = "";
1611 if (peekTokenClass(EHTokIdentifier)) {
1612 structName = *token.string;
1613 advanceToken();
1614 }
1615
John Kessenich3d157c52016-07-25 16:05:33 -06001616 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001617 TQualifier postDeclQualifier;
1618 postDeclQualifier.clear();
1619 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001620
John Kesseniche6e74942016-06-11 16:43:14 -06001621 // LEFT_BRACE
1622 if (! acceptTokenClass(EHTokLeftBrace)) {
1623 expected("{");
1624 return false;
1625 }
1626
1627 // struct_declaration_list
1628 TTypeList* typeList;
1629 if (! acceptStructDeclarationList(typeList)) {
1630 expected("struct member declarations");
1631 return false;
1632 }
1633
1634 // RIGHT_BRACE
1635 if (! acceptTokenClass(EHTokRightBrace)) {
1636 expected("}");
1637 return false;
1638 }
1639
1640 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001641 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001642 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001643 else {
John Kessenich7735b942016-09-05 12:40:06 -06001644 postDeclQualifier.storage = storageQualifier;
1645 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001646 }
John Kesseniche6e74942016-06-11 16:43:14 -06001647
John Kessenich3d157c52016-07-25 16:05:33 -06001648 // If it was named, which means the type can be reused later, add
1649 // it to the symbol table. (Unless it's a block, in which
1650 // case the name is not a type.)
1651 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001652 TVariable* userTypeDef = new TVariable(&structName, type, true);
1653 if (! parseContext.symbolTable.insert(*userTypeDef))
1654 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1655 }
1656
1657 return true;
1658}
1659
1660// struct_declaration_list
1661// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1662//
1663// struct_declaration
1664// : fully_specified_type struct_declarator COMMA struct_declarator ...
1665//
1666// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001667// : IDENTIFIER post_decls
1668// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001669//
1670bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1671{
1672 typeList = new TTypeList();
1673
1674 do {
1675 // success on seeing the RIGHT_BRACE coming up
1676 if (peekTokenClass(EHTokRightBrace))
1677 return true;
1678
1679 // struct_declaration
1680
1681 // fully_specified_type
1682 TType memberType;
1683 if (! acceptFullySpecifiedType(memberType)) {
1684 expected("member type");
1685 return false;
1686 }
1687
1688 // struct_declarator COMMA struct_declarator ...
1689 do {
1690 // peek IDENTIFIER
1691 if (! peekTokenClass(EHTokIdentifier)) {
1692 expected("member name");
1693 return false;
1694 }
1695
1696 // add it to the list of members
1697 TTypeLoc member = { new TType(EbtVoid), token.loc };
1698 member.type->shallowCopy(memberType);
1699 member.type->setFieldName(*token.string);
1700 typeList->push_back(member);
1701
1702 // accept IDENTIFIER
1703 advanceToken();
1704
1705 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001706 TArraySizes* arraySizes = nullptr;
1707 acceptArraySpecifier(arraySizes);
1708 if (arraySizes)
1709 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001710
John Kessenich7735b942016-09-05 12:40:06 -06001711 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001712
John Kesseniche6e74942016-06-11 16:43:14 -06001713 // success on seeing the SEMICOLON coming up
1714 if (peekTokenClass(EHTokSemicolon))
1715 break;
1716
1717 // COMMA
1718 if (! acceptTokenClass(EHTokComma)) {
1719 expected(",");
1720 return false;
1721 }
1722
1723 } while (true);
1724
1725 // SEMI_COLON
1726 if (! acceptTokenClass(EHTokSemicolon)) {
1727 expected(";");
1728 return false;
1729 }
1730
1731 } while (true);
1732}
1733
John Kessenich5f934b02016-03-13 17:58:25 -06001734// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001735// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001736// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001737//
1738bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1739{
John Kessenich078d7f22016-03-14 10:02:11 -06001740 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001741 if (! acceptTokenClass(EHTokLeftParen))
1742 return false;
1743
John Kessenich71351de2016-06-08 12:50:56 -06001744 // VOID RIGHT_PAREN
1745 if (! acceptTokenClass(EHTokVoid)) {
1746 do {
1747 // parameter_declaration
1748 if (! acceptParameterDeclaration(function))
1749 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001750
John Kessenich71351de2016-06-08 12:50:56 -06001751 // COMMA
1752 if (! acceptTokenClass(EHTokComma))
1753 break;
1754 } while (true);
1755 }
John Kessenich5f934b02016-03-13 17:58:25 -06001756
John Kessenich078d7f22016-03-14 10:02:11 -06001757 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001758 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001759 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001760 return false;
1761 }
1762
1763 return true;
1764}
1765
1766// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001767// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001768// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001769//
1770bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1771{
1772 // fully_specified_type
1773 TType* type = new TType;
1774 if (! acceptFullySpecifiedType(*type))
1775 return false;
1776
1777 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001778 HlslToken idToken;
1779 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001780
John Kessenich19b92ff2016-06-19 11:50:34 -06001781 // array_specifier
1782 TArraySizes* arraySizes = nullptr;
1783 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001784 if (arraySizes) {
1785 if (arraySizes->isImplicit()) {
1786 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1787 return false;
1788 }
1789
John Kessenich19b92ff2016-06-19 11:50:34 -06001790 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001791 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001792
1793 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001794 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001795
John Kessenich5aa59e22016-06-17 15:50:47 -06001796 parseContext.paramFix(*type);
1797
John Kessenichaecd4972016-03-14 10:46:34 -06001798 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001799 function.addParameter(param);
1800
1801 return true;
1802}
1803
1804// Do the work to create the function definition in addition to
1805// parsing the body (compound_statement).
steve-lunarg1868b142016-10-20 13:07:10 -06001806bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
John Kessenich5f934b02016-03-13 17:58:25 -06001807{
John Kessenicha3051662016-09-02 19:13:36 -06001808 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001809 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001810
John Kessenich077e0522016-06-09 02:02:17 -06001811 // This does a pushScope()
steve-lunarg1868b142016-10-20 13:07:10 -06001812 node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06001813
1814 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001815 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001816 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001817 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001818 return true;
1819 }
1820
1821 return false;
1822}
1823
John Kessenich0d2b6de2016-06-05 11:23:11 -06001824// Accept an expression with parenthesis around it, where
1825// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001826// syntactically required ones like in "if ( expression )".
1827//
1828// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001829//
1830// Note this one is not set up to be speculative; as it gives
1831// errors if not found.
1832//
1833bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1834{
1835 // LEFT_PAREN
1836 if (! acceptTokenClass(EHTokLeftParen))
1837 expected("(");
1838
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001839 bool decl = false;
1840 TIntermNode* declNode = nullptr;
1841 decl = acceptControlDeclaration(declNode);
1842 if (decl) {
1843 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1844 expected("initialized declaration");
1845 return false;
1846 } else
1847 expression = declNode->getAsTyped();
1848 } else {
1849 // no declaration
1850 if (! acceptExpression(expression)) {
1851 expected("expression");
1852 return false;
1853 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001854 }
1855
1856 // RIGHT_PAREN
1857 if (! acceptTokenClass(EHTokRightParen))
1858 expected(")");
1859
1860 return true;
1861}
1862
John Kessenich34fb0362016-05-03 23:17:20 -06001863// The top-level full expression recognizer.
1864//
John Kessenich87142c72016-03-12 20:24:24 -07001865// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001866// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001867//
1868bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1869{
LoopDawgef764a22016-06-03 09:17:51 -06001870 node = nullptr;
1871
John Kessenich34fb0362016-05-03 23:17:20 -06001872 // assignment_expression
1873 if (! acceptAssignmentExpression(node))
1874 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001875
John Kessenich34fb0362016-05-03 23:17:20 -06001876 if (! peekTokenClass(EHTokComma))
1877 return true;
1878
1879 do {
1880 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001881 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001882 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001883
John Kessenich34fb0362016-05-03 23:17:20 -06001884 // ... assignment_expression
1885 TIntermTyped* rightNode = nullptr;
1886 if (! acceptAssignmentExpression(rightNode)) {
1887 expected("assignment expression");
1888 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001889 }
1890
John Kessenich34fb0362016-05-03 23:17:20 -06001891 node = intermediate.addComma(node, rightNode, loc);
1892
1893 if (! peekTokenClass(EHTokComma))
1894 return true;
1895 } while (true);
1896}
1897
John Kessenich07354242016-07-01 19:58:06 -06001898// initializer
John Kessenich98ad4852016-11-27 17:39:07 -07001899// : LEFT_BRACE RIGHT_BRACE
1900// | LEFT_BRACE initializer_list RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001901//
1902// initializer_list
1903// : assignment_expression COMMA assignment_expression COMMA ...
1904//
1905bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1906{
1907 // LEFT_BRACE
1908 if (! acceptTokenClass(EHTokLeftBrace))
1909 return false;
1910
John Kessenich98ad4852016-11-27 17:39:07 -07001911 // RIGHT_BRACE
John Kessenich07354242016-07-01 19:58:06 -06001912 TSourceLoc loc = token.loc;
John Kessenich98ad4852016-11-27 17:39:07 -07001913 if (acceptTokenClass(EHTokRightBrace)) {
1914 // a zero-length initializer list
1915 node = intermediate.makeAggregate(loc);
1916 return true;
1917 }
1918
1919 // initializer_list
John Kessenich07354242016-07-01 19:58:06 -06001920 node = nullptr;
1921 do {
1922 // assignment_expression
1923 TIntermTyped* expr;
1924 if (! acceptAssignmentExpression(expr)) {
1925 expected("assignment expression in initializer list");
1926 return false;
1927 }
1928 node = intermediate.growAggregate(node, expr, loc);
1929
1930 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001931 if (acceptTokenClass(EHTokComma)) {
1932 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1933 return true;
John Kessenich07354242016-07-01 19:58:06 -06001934 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001935 }
John Kessenich07354242016-07-01 19:58:06 -06001936
1937 // RIGHT_BRACE
1938 if (acceptTokenClass(EHTokRightBrace))
1939 return true;
1940
1941 expected(", or }");
1942 return false;
1943 } while (true);
1944}
1945
John Kessenich34fb0362016-05-03 23:17:20 -06001946// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001947// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001948//
1949// a op (b op (c op d))
1950//
1951// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001952// : initializer
1953// | conditional_expression
1954// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001955//
1956bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1957{
John Kessenich07354242016-07-01 19:58:06 -06001958 // initializer
1959 if (peekTokenClass(EHTokLeftBrace)) {
1960 if (acceptInitializer(node))
1961 return true;
1962
1963 expected("initializer");
1964 return false;
1965 }
1966
John Kessenich00957f82016-07-27 10:39:57 -06001967 // conditional_expression
1968 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001969 return false;
1970
John Kessenich07354242016-07-01 19:58:06 -06001971 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001972 TOperator assignOp = HlslOpMap::assignment(peek());
1973 if (assignOp == EOpNull)
1974 return true;
1975
John Kessenich00957f82016-07-27 10:39:57 -06001976 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001977 TSourceLoc loc = token.loc;
1978 advanceToken();
1979
John Kessenich00957f82016-07-27 10:39:57 -06001980 // conditional_expression assign_op conditional_expression ...
1981 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001982 // gets the right-to-left associativity.
1983 TIntermTyped* rightNode = nullptr;
1984 if (! acceptAssignmentExpression(rightNode)) {
1985 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001986 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001987 }
1988
John Kessenichd21baed2016-09-16 03:05:12 -06001989 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
steve-lunarg90707962016-10-07 19:35:40 -06001990 node = parseContext.handleLvalue(loc, "assign", node);
1991
John Kessenichfea226b2016-07-28 17:53:56 -06001992 if (node == nullptr) {
1993 parseContext.error(loc, "could not create assignment", "", "");
1994 return false;
1995 }
John Kessenich34fb0362016-05-03 23:17:20 -06001996
1997 if (! peekTokenClass(EHTokComma))
1998 return true;
1999
2000 return true;
2001}
2002
John Kessenich00957f82016-07-27 10:39:57 -06002003// Accept a conditional expression, which associates right-to-left,
2004// accomplished by the "true" expression calling down to lower
2005// precedence levels than this level.
2006//
2007// conditional_expression
2008// : binary_expression
2009// | binary_expression QUESTION expression COLON assignment_expression
2010//
2011bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2012{
2013 // binary_expression
2014 if (! acceptBinaryExpression(node, PlLogicalOr))
2015 return false;
2016
2017 if (! acceptTokenClass(EHTokQuestion))
2018 return true;
2019
2020 TIntermTyped* trueNode = nullptr;
2021 if (! acceptExpression(trueNode)) {
2022 expected("expression after ?");
2023 return false;
2024 }
2025 TSourceLoc loc = token.loc;
2026
2027 if (! acceptTokenClass(EHTokColon)) {
2028 expected(":");
2029 return false;
2030 }
2031
2032 TIntermTyped* falseNode = nullptr;
2033 if (! acceptAssignmentExpression(falseNode)) {
2034 expected("expression after :");
2035 return false;
2036 }
2037
2038 node = intermediate.addSelection(node, trueNode, falseNode, loc);
2039
2040 return true;
2041}
2042
John Kessenich34fb0362016-05-03 23:17:20 -06002043// Accept a binary expression, for binary operations that
2044// associate left-to-right. This is, it is implicit, for example
2045//
2046// ((a op b) op c) op d
2047//
2048// binary_expression
2049// : expression op expression op expression ...
2050//
2051// where 'expression' is the next higher level in precedence.
2052//
2053bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2054{
2055 if (precedenceLevel > PlMul)
2056 return acceptUnaryExpression(node);
2057
2058 // assignment_expression
2059 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2060 return false;
2061
John Kessenich34fb0362016-05-03 23:17:20 -06002062 do {
John Kessenich64076ed2016-07-28 21:43:17 -06002063 TOperator op = HlslOpMap::binary(peek());
2064 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2065 if (tokenLevel < precedenceLevel)
2066 return true;
2067
John Kessenich34fb0362016-05-03 23:17:20 -06002068 // ... op
2069 TSourceLoc loc = token.loc;
2070 advanceToken();
2071
2072 // ... expression
2073 TIntermTyped* rightNode = nullptr;
2074 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2075 expected("expression");
2076 return false;
2077 }
2078
2079 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06002080 if (node == nullptr) {
2081 parseContext.error(loc, "Could not perform requested binary operation", "", "");
2082 return false;
2083 }
John Kessenich34fb0362016-05-03 23:17:20 -06002084 } while (true);
2085}
2086
2087// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06002088// : (type) unary_expression
2089// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06002090// | - unary_expression
2091// | ! unary_expression
2092// | ~ unary_expression
2093// | ++ unary_expression
2094// | -- unary_expression
2095// | postfix_expression
2096//
2097bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
2098{
John Kessenich1cc1a282016-06-03 16:55:49 -06002099 // (type) unary_expression
2100 // Have to look two steps ahead, because this could be, e.g., a
2101 // postfix_expression instead, since that also starts with at "(".
2102 if (acceptTokenClass(EHTokLeftParen)) {
2103 TType castType;
2104 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06002105 if (acceptTokenClass(EHTokRightParen)) {
2106 // We've matched "(type)" now, get the expression to cast
2107 TSourceLoc loc = token.loc;
2108 if (! acceptUnaryExpression(node))
2109 return false;
2110
2111 // Hook it up like a constructor
2112 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
2113 if (constructorFunction == nullptr) {
2114 expected("type that can be constructed");
2115 return false;
2116 }
2117 TIntermTyped* arguments = nullptr;
2118 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
2119 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
2120
2121 return true;
2122 } else {
2123 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
2124 // the '(int' part. We must back up twice.
2125 recedeToken();
2126 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06002127 }
John Kessenich1cc1a282016-06-03 16:55:49 -06002128 } else {
2129 // This isn't a type cast, but it still started "(", so if it is a
2130 // unary expression, it can only be a postfix_expression, so try that.
2131 // Back it up first.
2132 recedeToken();
2133 return acceptPostfixExpression(node);
2134 }
2135 }
2136
2137 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06002138 TOperator unaryOp = HlslOpMap::preUnary(peek());
2139
John Kessenich1cc1a282016-06-03 16:55:49 -06002140 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06002141 if (unaryOp == EOpNull)
2142 return acceptPostfixExpression(node);
2143
2144 // op unary_expression
2145 TSourceLoc loc = token.loc;
2146 advanceToken();
2147 if (! acceptUnaryExpression(node))
2148 return false;
2149
2150 // + is a no-op
2151 if (unaryOp == EOpAdd)
2152 return true;
2153
2154 node = intermediate.addUnaryMath(unaryOp, node, loc);
steve-lunarge5921f12016-10-15 10:29:58 -06002155
2156 // These unary ops require lvalues
2157 if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
2158 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002159
2160 return node != nullptr;
2161}
2162
2163// postfix_expression
2164// : LEFT_PAREN expression RIGHT_PAREN
2165// | literal
2166// | constructor
2167// | identifier
2168// | function_call
2169// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
2170// | postfix_expression DOT IDENTIFIER
2171// | postfix_expression INC_OP
2172// | postfix_expression DEC_OP
2173//
2174bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
2175{
2176 // Not implemented as self-recursive:
2177 // The logical "right recursion" is done with an loop at the end
2178
2179 // idToken will pick up either a variable or a function name in a function call
2180 HlslToken idToken;
2181
John Kessenich21472ae2016-06-04 11:46:33 -06002182 // Find something before the postfix operations, as they can't operate
2183 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07002184 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06002185 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002186 if (! acceptExpression(node)) {
2187 expected("expression");
2188 return false;
2189 }
2190 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002191 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002192 return false;
2193 }
John Kessenich34fb0362016-05-03 23:17:20 -06002194 } else if (acceptLiteral(node)) {
2195 // literal (nothing else to do yet), go on to the
2196 } else if (acceptConstructor(node)) {
2197 // constructor (nothing else to do yet)
2198 } else if (acceptIdentifier(idToken)) {
2199 // identifier or function_call name
2200 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06002201 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06002202 } else if (acceptFunctionCall(idToken, node)) {
2203 // function_call (nothing else to do yet)
2204 } else {
2205 expected("function call arguments");
2206 return false;
2207 }
John Kessenich21472ae2016-06-04 11:46:33 -06002208 } else {
2209 // nothing found, can't post operate
2210 return false;
John Kessenich87142c72016-03-12 20:24:24 -07002211 }
2212
John Kessenich21472ae2016-06-04 11:46:33 -06002213 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06002214 do {
2215 TSourceLoc loc = token.loc;
2216 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07002217
John Kessenich34fb0362016-05-03 23:17:20 -06002218 // Consume only a valid post-unary operator, otherwise we are done.
2219 switch (postOp) {
2220 case EOpIndexDirectStruct:
2221 case EOpIndexIndirect:
2222 case EOpPostIncrement:
2223 case EOpPostDecrement:
2224 advanceToken();
2225 break;
2226 default:
2227 return true;
2228 }
John Kessenich87142c72016-03-12 20:24:24 -07002229
John Kessenich34fb0362016-05-03 23:17:20 -06002230 // We have a valid post-unary operator, process it.
2231 switch (postOp) {
2232 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06002233 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002234 // DOT IDENTIFIER
2235 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06002236 HlslToken field;
2237 if (! acceptIdentifier(field)) {
2238 expected("swizzle or member");
2239 return false;
2240 }
LoopDawg4886f692016-06-29 10:58:58 -06002241
2242 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06002243 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06002244
2245 // In the event of a method node, we look for an open paren and accept the function call.
2246 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
2247 if (! acceptFunctionCall(field, node, base)) {
2248 expected("function parameters");
2249 return false;
2250 }
2251 }
2252
John Kessenich34fb0362016-05-03 23:17:20 -06002253 break;
John Kessenich93a162a2016-06-17 17:16:27 -06002254 }
John Kessenich34fb0362016-05-03 23:17:20 -06002255 case EOpIndexIndirect:
2256 {
John Kessenich19b92ff2016-06-19 11:50:34 -06002257 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06002258 TIntermTyped* indexNode = nullptr;
2259 if (! acceptExpression(indexNode) ||
2260 ! peekTokenClass(EHTokRightBracket)) {
2261 expected("expression followed by ']'");
2262 return false;
2263 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002264 advanceToken();
2265 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2266 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002267 }
2268 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002269 // INC_OP
2270 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002271 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002272 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002273 node = intermediate.addUnaryMath(postOp, node, loc);
steve-lunarg07830e82016-10-10 10:00:14 -06002274 node = parseContext.handleLvalue(loc, "unary operator", node);
John Kessenich34fb0362016-05-03 23:17:20 -06002275 break;
2276 default:
2277 assert(0);
2278 break;
2279 }
2280 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002281}
2282
John Kessenichd016be12016-03-13 11:24:20 -06002283// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002284// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002285//
2286bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2287{
2288 // type
2289 TType type;
2290 if (acceptType(type)) {
2291 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2292 if (constructorFunction == nullptr)
2293 return false;
2294
2295 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002296 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002297 if (! acceptArguments(constructorFunction, arguments)) {
2298 expected("constructor arguments");
2299 return false;
2300 }
2301
2302 // hook it up
2303 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2304
2305 return true;
2306 }
2307
2308 return false;
2309}
2310
John Kessenich34fb0362016-05-03 23:17:20 -06002311// The function_call identifier was already recognized, and passed in as idToken.
2312//
2313// function_call
2314// : [idToken] arguments
2315//
LoopDawg4886f692016-06-29 10:58:58 -06002316bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002317{
John Kessenich4678ca92016-05-13 09:33:42 -06002318 // arguments
2319 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2320 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002321
2322 // methods have an implicit first argument of the calling object.
2323 if (base != nullptr)
2324 parseContext.handleFunctionArgument(function, arguments, base);
2325
John Kessenich4678ca92016-05-13 09:33:42 -06002326 if (! acceptArguments(function, arguments))
2327 return false;
2328
2329 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2330
2331 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002332}
2333
John Kessenich87142c72016-03-12 20:24:24 -07002334// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002335// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002336//
John Kessenichd016be12016-03-13 11:24:20 -06002337// The arguments are pushed onto the 'function' argument list and
2338// onto the 'arguments' aggregate.
2339//
John Kessenich4678ca92016-05-13 09:33:42 -06002340bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002341{
John Kessenich078d7f22016-03-14 10:02:11 -06002342 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002343 if (! acceptTokenClass(EHTokLeftParen))
2344 return false;
2345
2346 do {
John Kessenichd016be12016-03-13 11:24:20 -06002347 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002348 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002349 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002350 break;
John Kessenichd016be12016-03-13 11:24:20 -06002351
2352 // hook it up
2353 parseContext.handleFunctionArgument(function, arguments, arg);
2354
John Kessenich078d7f22016-03-14 10:02:11 -06002355 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002356 if (! acceptTokenClass(EHTokComma))
2357 break;
2358 } while (true);
2359
John Kessenich078d7f22016-03-14 10:02:11 -06002360 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002361 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002362 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002363 return false;
2364 }
2365
2366 return true;
2367}
2368
2369bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2370{
2371 switch (token.tokenClass) {
2372 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002373 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002374 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002375 case EHTokUintConstant:
2376 node = intermediate.addConstantUnion(token.u, token.loc, true);
2377 break;
John Kessenich87142c72016-03-12 20:24:24 -07002378 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002379 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002380 break;
2381 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002382 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002383 break;
2384 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002385 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002386 break;
John Kessenich86f71382016-09-19 20:23:18 -06002387 case EHTokStringConstant:
2388 node = nullptr;
2389 break;
John Kessenich87142c72016-03-12 20:24:24 -07002390
2391 default:
2392 return false;
2393 }
2394
2395 advanceToken();
2396
2397 return true;
2398}
2399
John Kessenich5f934b02016-03-13 17:58:25 -06002400// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002401// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002402//
John Kessenich21472ae2016-06-04 11:46:33 -06002403bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002404{
John Kessenich21472ae2016-06-04 11:46:33 -06002405 TIntermAggregate* compoundStatement = nullptr;
2406
John Kessenich34fb0362016-05-03 23:17:20 -06002407 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002408 if (! acceptTokenClass(EHTokLeftBrace))
2409 return false;
2410
2411 // statement statement ...
2412 TIntermNode* statement = nullptr;
2413 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002414 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2415 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2416 branch->getFlowOp() == EOpDefault)) {
2417 // hook up individual subsequences within a switch statement
2418 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2419 compoundStatement = nullptr;
2420 } else {
2421 // hook it up to the growing compound statement
2422 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2423 }
John Kessenich5f934b02016-03-13 17:58:25 -06002424 }
John Kessenich34fb0362016-05-03 23:17:20 -06002425 if (compoundStatement)
2426 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002427
John Kessenich21472ae2016-06-04 11:46:33 -06002428 retStatement = compoundStatement;
2429
John Kessenich34fb0362016-05-03 23:17:20 -06002430 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002431 return acceptTokenClass(EHTokRightBrace);
2432}
2433
John Kessenich0d2b6de2016-06-05 11:23:11 -06002434bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2435{
2436 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002437 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002438 parseContext.popScope();
2439
2440 return result;
2441}
2442
John Kessenich077e0522016-06-09 02:02:17 -06002443bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002444{
John Kessenich077e0522016-06-09 02:02:17 -06002445 parseContext.pushScope();
2446 bool result = acceptCompoundStatement(statement);
2447 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002448
2449 return result;
2450}
2451
John Kessenich5f934b02016-03-13 17:58:25 -06002452// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002453// : attributes attributed_statement
2454//
2455// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002456// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002457// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002458// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002459// | declaration_statement
2460// | selection_statement
2461// | switch_statement
2462// | case_label
2463// | iteration_statement
2464// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002465//
2466bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2467{
John Kessenich21472ae2016-06-04 11:46:33 -06002468 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002469
John Kessenich21472ae2016-06-04 11:46:33 -06002470 // attributes
steve-lunarg1868b142016-10-20 13:07:10 -06002471 TAttributeMap attributes;
2472 acceptAttributes(attributes);
John Kessenich5f934b02016-03-13 17:58:25 -06002473
John Kessenich21472ae2016-06-04 11:46:33 -06002474 // attributed_statement
2475 switch (peek()) {
2476 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002477 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002478
John Kessenich21472ae2016-06-04 11:46:33 -06002479 case EHTokIf:
2480 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002481
John Kessenich21472ae2016-06-04 11:46:33 -06002482 case EHTokSwitch:
2483 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002484
John Kessenich21472ae2016-06-04 11:46:33 -06002485 case EHTokFor:
2486 case EHTokDo:
2487 case EHTokWhile:
2488 return acceptIterationStatement(statement);
2489
2490 case EHTokContinue:
2491 case EHTokBreak:
2492 case EHTokDiscard:
2493 case EHTokReturn:
2494 return acceptJumpStatement(statement);
2495
2496 case EHTokCase:
2497 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002498 case EHTokDefault:
2499 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002500
2501 case EHTokSemicolon:
2502 return acceptTokenClass(EHTokSemicolon);
2503
2504 case EHTokRightBrace:
2505 // Performance: not strictly necessary, but stops a bunch of hunting early,
2506 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002507 return false;
2508
John Kessenich21472ae2016-06-04 11:46:33 -06002509 default:
2510 {
2511 // declaration
2512 if (acceptDeclaration(statement))
2513 return true;
2514
2515 // expression
2516 TIntermTyped* node;
2517 if (acceptExpression(node))
2518 statement = node;
2519 else
2520 return false;
2521
2522 // SEMICOLON (following an expression)
2523 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002524 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002525 return false;
2526 }
2527 }
2528 }
2529
John Kessenich5f934b02016-03-13 17:58:25 -06002530 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002531}
2532
John Kessenich21472ae2016-06-04 11:46:33 -06002533// attributes
2534// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2535//
2536// attribute:
2537// : UNROLL
2538// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2539// | FASTOPT
2540// | ALLOW_UAV_CONDITION
2541// | BRANCH
2542// | FLATTEN
2543// | FORCECASE
2544// | CALL
steve-lunarg1868b142016-10-20 13:07:10 -06002545// | DOMAIN
2546// | EARLYDEPTHSTENCIL
2547// | INSTANCE
2548// | MAXTESSFACTOR
2549// | OUTPUTCONTROLPOINTS
2550// | OUTPUTTOPOLOGY
2551// | PARTITIONING
2552// | PATCHCONSTANTFUNC
2553// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
John Kessenich21472ae2016-06-04 11:46:33 -06002554//
steve-lunarg1868b142016-10-20 13:07:10 -06002555void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
John Kessenich21472ae2016-06-04 11:46:33 -06002556{
steve-lunarg1868b142016-10-20 13:07:10 -06002557 // For now, accept the [ XXX(X) ] syntax, but drop all but
2558 // numthreads, which is used to set the CS local size.
John Kessenich0d2b6de2016-06-05 11:23:11 -06002559 // TODO: subset to correct set? Pass on?
2560 do {
steve-lunarg1868b142016-10-20 13:07:10 -06002561 HlslToken idToken;
2562
John Kessenich0d2b6de2016-06-05 11:23:11 -06002563 // LEFT_BRACKET?
2564 if (! acceptTokenClass(EHTokLeftBracket))
2565 return;
2566
2567 // attribute
steve-lunarg1868b142016-10-20 13:07:10 -06002568 if (acceptIdentifier(idToken)) {
2569 // 'idToken.string' is the attribute
John Kessenich0d2b6de2016-06-05 11:23:11 -06002570 } else if (! peekTokenClass(EHTokRightBracket)) {
2571 expected("identifier");
2572 advanceToken();
2573 }
2574
steve-lunarga22f7db2016-11-11 08:17:44 -07002575 TIntermAggregate* expressions = nullptr;
steve-lunarg1868b142016-10-20 13:07:10 -06002576
2577 // (x, ...)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002578 if (acceptTokenClass(EHTokLeftParen)) {
steve-lunarga22f7db2016-11-11 08:17:44 -07002579 expressions = new TIntermAggregate;
steve-lunarg1868b142016-10-20 13:07:10 -06002580
John Kessenich0d2b6de2016-06-05 11:23:11 -06002581 TIntermTyped* node;
steve-lunarga22f7db2016-11-11 08:17:44 -07002582 bool expectingExpression = false;
steve-lunarg1868b142016-10-20 13:07:10 -06002583
steve-lunarga22f7db2016-11-11 08:17:44 -07002584 while (acceptAssignmentExpression(node)) {
2585 expectingExpression = false;
2586 expressions->getSequence().push_back(node);
steve-lunarg1868b142016-10-20 13:07:10 -06002587 if (acceptTokenClass(EHTokComma))
steve-lunarga22f7db2016-11-11 08:17:44 -07002588 expectingExpression = true;
steve-lunarg1868b142016-10-20 13:07:10 -06002589 }
2590
steve-lunarga22f7db2016-11-11 08:17:44 -07002591 // 'expressions' is an aggregate with the expressions in it
John Kessenich0d2b6de2016-06-05 11:23:11 -06002592 if (! acceptTokenClass(EHTokRightParen))
2593 expected(")");
steve-lunarga22f7db2016-11-11 08:17:44 -07002594
2595 // Error for partial or missing expression
2596 if (expectingExpression || expressions->getSequence().empty())
2597 expected("expression");
John Kessenich0d2b6de2016-06-05 11:23:11 -06002598 }
2599
2600 // RIGHT_BRACKET
steve-lunarg1868b142016-10-20 13:07:10 -06002601 if (!acceptTokenClass(EHTokRightBracket)) {
2602 expected("]");
2603 return;
2604 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06002605
steve-lunarg1868b142016-10-20 13:07:10 -06002606 // Add any values we found into the attribute map. This accepts
2607 // (and ignores) values not mapping to a known TAttributeType;
steve-lunarga22f7db2016-11-11 08:17:44 -07002608 attributes.setAttribute(idToken.string, expressions);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002609 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002610}
2611
John Kessenich0d2b6de2016-06-05 11:23:11 -06002612// selection_statement
2613// : IF LEFT_PAREN expression RIGHT_PAREN statement
2614// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2615//
John Kessenich21472ae2016-06-04 11:46:33 -06002616bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2617{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002618 TSourceLoc loc = token.loc;
2619
2620 // IF
2621 if (! acceptTokenClass(EHTokIf))
2622 return false;
2623
2624 // so that something declared in the condition is scoped to the lifetimes
2625 // of the then-else statements
2626 parseContext.pushScope();
2627
2628 // LEFT_PAREN expression RIGHT_PAREN
2629 TIntermTyped* condition;
2630 if (! acceptParenExpression(condition))
2631 return false;
2632
2633 // create the child statements
2634 TIntermNodePair thenElse = { nullptr, nullptr };
2635
2636 // then statement
2637 if (! acceptScopedStatement(thenElse.node1)) {
2638 expected("then statement");
2639 return false;
2640 }
2641
2642 // ELSE
2643 if (acceptTokenClass(EHTokElse)) {
2644 // else statement
2645 if (! acceptScopedStatement(thenElse.node2)) {
2646 expected("else statement");
2647 return false;
2648 }
2649 }
2650
2651 // Put the pieces together
2652 statement = intermediate.addSelection(condition, thenElse, loc);
2653 parseContext.popScope();
2654
2655 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002656}
2657
John Kessenichd02dc5d2016-07-01 00:04:11 -06002658// switch_statement
2659// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2660//
John Kessenich21472ae2016-06-04 11:46:33 -06002661bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2662{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002663 // SWITCH
2664 TSourceLoc loc = token.loc;
2665 if (! acceptTokenClass(EHTokSwitch))
2666 return false;
2667
2668 // LEFT_PAREN expression RIGHT_PAREN
2669 parseContext.pushScope();
2670 TIntermTyped* switchExpression;
2671 if (! acceptParenExpression(switchExpression)) {
2672 parseContext.popScope();
2673 return false;
2674 }
2675
2676 // compound_statement
2677 parseContext.pushSwitchSequence(new TIntermSequence);
2678 bool statementOkay = acceptCompoundStatement(statement);
2679 if (statementOkay)
2680 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2681
2682 parseContext.popSwitchSequence();
2683 parseContext.popScope();
2684
2685 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002686}
2687
John Kessenich119f8f62016-06-05 15:44:07 -06002688// iteration_statement
2689// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2690// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2691// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2692//
2693// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002694bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2695{
John Kessenich119f8f62016-06-05 15:44:07 -06002696 TSourceLoc loc = token.loc;
2697 TIntermTyped* condition = nullptr;
2698
2699 EHlslTokenClass loop = peek();
2700 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2701
2702 // WHILE or DO or FOR
2703 advanceToken();
2704
2705 switch (loop) {
2706 case EHTokWhile:
2707 // so that something declared in the condition is scoped to the lifetime
2708 // of the while sub-statement
2709 parseContext.pushScope();
2710 parseContext.nestLooping();
2711
2712 // LEFT_PAREN condition RIGHT_PAREN
2713 if (! acceptParenExpression(condition))
2714 return false;
2715
2716 // statement
2717 if (! acceptScopedStatement(statement)) {
2718 expected("while sub-statement");
2719 return false;
2720 }
2721
2722 parseContext.unnestLooping();
2723 parseContext.popScope();
2724
2725 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2726
2727 return true;
2728
2729 case EHTokDo:
2730 parseContext.nestLooping();
2731
2732 if (! acceptTokenClass(EHTokLeftBrace))
2733 expected("{");
2734
2735 // statement
2736 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2737 expected("do sub-statement");
2738 return false;
2739 }
2740
2741 if (! acceptTokenClass(EHTokRightBrace))
2742 expected("}");
2743
2744 // WHILE
2745 if (! acceptTokenClass(EHTokWhile)) {
2746 expected("while");
2747 return false;
2748 }
2749
2750 // LEFT_PAREN condition RIGHT_PAREN
2751 TIntermTyped* condition;
2752 if (! acceptParenExpression(condition))
2753 return false;
2754
2755 if (! acceptTokenClass(EHTokSemicolon))
2756 expected(";");
2757
2758 parseContext.unnestLooping();
2759
2760 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2761
2762 return true;
2763
2764 case EHTokFor:
2765 {
2766 // LEFT_PAREN
2767 if (! acceptTokenClass(EHTokLeftParen))
2768 expected("(");
2769
2770 // so that something declared in the condition is scoped to the lifetime
2771 // of the for sub-statement
2772 parseContext.pushScope();
2773
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002774 // initializer
2775 TIntermNode* initNode = nullptr;
2776 if (! acceptControlDeclaration(initNode)) {
2777 TIntermTyped* initExpr = nullptr;
2778 acceptExpression(initExpr);
2779 initNode = initExpr;
2780 }
2781 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002782 if (! acceptTokenClass(EHTokSemicolon))
2783 expected(";");
2784
2785 parseContext.nestLooping();
2786
2787 // condition SEMI_COLON
2788 acceptExpression(condition);
2789 if (! acceptTokenClass(EHTokSemicolon))
2790 expected(";");
2791
2792 // iterator SEMI_COLON
2793 TIntermTyped* iterator = nullptr;
2794 acceptExpression(iterator);
2795 if (! acceptTokenClass(EHTokRightParen))
2796 expected(")");
2797
2798 // statement
2799 if (! acceptScopedStatement(statement)) {
2800 expected("for sub-statement");
2801 return false;
2802 }
2803
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002804 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002805
2806 parseContext.popScope();
2807 parseContext.unnestLooping();
2808
2809 return true;
2810 }
2811
2812 default:
2813 return false;
2814 }
John Kessenich21472ae2016-06-04 11:46:33 -06002815}
2816
2817// jump_statement
2818// : CONTINUE SEMICOLON
2819// | BREAK SEMICOLON
2820// | DISCARD SEMICOLON
2821// | RETURN SEMICOLON
2822// | RETURN expression SEMICOLON
2823//
2824bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2825{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002826 EHlslTokenClass jump = peek();
2827 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002828 case EHTokContinue:
2829 case EHTokBreak:
2830 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002831 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002832 advanceToken();
2833 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002834 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002835 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002836 return false;
2837 }
John Kessenich21472ae2016-06-04 11:46:33 -06002838
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002839 switch (jump) {
2840 case EHTokContinue:
2841 statement = intermediate.addBranch(EOpContinue, token.loc);
2842 break;
2843 case EHTokBreak:
2844 statement = intermediate.addBranch(EOpBreak, token.loc);
2845 break;
2846 case EHTokDiscard:
2847 statement = intermediate.addBranch(EOpKill, token.loc);
2848 break;
2849
2850 case EHTokReturn:
2851 {
2852 // expression
2853 TIntermTyped* node;
2854 if (acceptExpression(node)) {
2855 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002856 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002857 } else
2858 statement = intermediate.addBranch(EOpReturn, token.loc);
2859 break;
2860 }
2861
2862 default:
2863 assert(0);
2864 return false;
2865 }
2866
2867 // SEMICOLON
2868 if (! acceptTokenClass(EHTokSemicolon))
2869 expected(";");
2870
2871 return true;
2872}
John Kessenich21472ae2016-06-04 11:46:33 -06002873
John Kessenichd02dc5d2016-07-01 00:04:11 -06002874// case_label
2875// : CASE expression COLON
2876//
John Kessenich21472ae2016-06-04 11:46:33 -06002877bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2878{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002879 TSourceLoc loc = token.loc;
2880 if (! acceptTokenClass(EHTokCase))
2881 return false;
2882
2883 TIntermTyped* expression;
2884 if (! acceptExpression(expression)) {
2885 expected("case expression");
2886 return false;
2887 }
2888
2889 if (! acceptTokenClass(EHTokColon)) {
2890 expected(":");
2891 return false;
2892 }
2893
2894 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2895
2896 return true;
2897}
2898
2899// default_label
2900// : DEFAULT COLON
2901//
2902bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2903{
2904 TSourceLoc loc = token.loc;
2905 if (! acceptTokenClass(EHTokDefault))
2906 return false;
2907
2908 if (! acceptTokenClass(EHTokColon)) {
2909 expected(":");
2910 return false;
2911 }
2912
2913 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2914
2915 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002916}
2917
John Kessenich19b92ff2016-06-19 11:50:34 -06002918// array_specifier
steve-lunarg7b211a32016-10-13 12:26:18 -06002919// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
2920// : LEFT_BRACKET RGHT_BRACKET // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002921//
2922void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2923{
2924 arraySizes = nullptr;
2925
steve-lunarg7b211a32016-10-13 12:26:18 -06002926 // Early-out if there aren't any array dimensions
2927 if (!peekTokenClass(EHTokLeftBracket))
John Kessenich19b92ff2016-06-19 11:50:34 -06002928 return;
2929
steve-lunarg7b211a32016-10-13 12:26:18 -06002930 // 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 -06002931 arraySizes = new TArraySizes;
steve-lunarg7b211a32016-10-13 12:26:18 -06002932
2933 // Collect each array dimension.
2934 while (acceptTokenClass(EHTokLeftBracket)) {
2935 TSourceLoc loc = token.loc;
2936 TIntermTyped* sizeExpr = nullptr;
2937
2938 // Array sizing expression is optional. If ommitted, array will be later sized by initializer list.
2939 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
2940
2941 if (! acceptTokenClass(EHTokRightBracket)) {
2942 expected("]");
2943 return;
2944 }
2945
2946 if (hasArraySize) {
2947 TArraySize arraySize;
2948 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2949 arraySizes->addInnerSize(arraySize);
2950 } else {
2951 arraySizes->addInnerSize(0); // sized by initializers.
2952 }
steve-lunarg265c0612016-09-27 10:57:35 -06002953 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002954}
2955
John Kessenich630dd7d2016-06-12 23:52:12 -06002956// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002957// : COLON semantic // optional
2958// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2959// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002960// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002961// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002962//
John Kessenich7735b942016-09-05 12:40:06 -06002963void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002964{
John Kessenich630dd7d2016-06-12 23:52:12 -06002965 do {
2966 // COLON
2967 if (acceptTokenClass(EHTokColon)) {
2968 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002969 if (peekTokenClass(EHTokLayout))
2970 acceptLayoutQualifierList(qualifier);
2971 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002972 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002973 if (! acceptTokenClass(EHTokLeftParen)) {
2974 expected("(");
2975 return;
2976 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002977 HlslToken locationToken;
2978 if (! acceptIdentifier(locationToken)) {
2979 expected("c[subcomponent][.component]");
2980 return;
2981 }
2982 HlslToken componentToken;
2983 if (acceptTokenClass(EHTokDot)) {
2984 if (! acceptIdentifier(componentToken)) {
2985 expected("component");
2986 return;
2987 }
2988 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002989 if (! acceptTokenClass(EHTokRightParen)) {
2990 expected(")");
2991 break;
2992 }
John Kessenich7735b942016-09-05 12:40:06 -06002993 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002994 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002995 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002996 return;
2997 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002998 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2999 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003000 if (! acceptTokenClass(EHTokLeftParen)) {
3001 expected("(");
3002 return;
3003 }
John Kessenichb38f0712016-07-30 10:29:54 -06003004 HlslToken registerDesc; // for Type#
3005 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06003006 if (! acceptIdentifier(registerDesc)) {
3007 expected("register number description");
3008 return;
3009 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003010 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
3011 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06003012 // Then we didn't really see the registerDesc yet, it was
3013 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06003014 profile = registerDesc;
3015 if (! acceptIdentifier(registerDesc)) {
3016 expected("register number description");
3017 return;
3018 }
3019 }
John Kessenichb38f0712016-07-30 10:29:54 -06003020 int subComponent = 0;
3021 if (acceptTokenClass(EHTokLeftBracket)) {
3022 // LEFT_BRACKET subcomponent RIGHT_BRACKET
3023 if (! peekTokenClass(EHTokIntConstant)) {
3024 expected("literal integer");
3025 return;
3026 }
3027 subComponent = token.i;
3028 advanceToken();
3029 if (! acceptTokenClass(EHTokRightBracket)) {
3030 expected("]");
3031 break;
3032 }
3033 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003034 // (COMMA SPACEN)opt
3035 HlslToken spaceDesc;
3036 if (acceptTokenClass(EHTokComma)) {
3037 if (! acceptIdentifier(spaceDesc)) {
3038 expected ("space identifier");
3039 return;
3040 }
3041 }
3042 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06003043 if (! acceptTokenClass(EHTokRightParen)) {
3044 expected(")");
3045 break;
3046 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06003047 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003048 } else {
3049 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06003050 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06003051 }
John Kessenicha1e2d492016-09-20 13:22:58 -06003052 } else if (peekTokenClass(EHTokLeftAngle))
3053 acceptAnnotations(qualifier);
3054 else
John Kessenich630dd7d2016-06-12 23:52:12 -06003055 break;
John Kessenich078d7f22016-03-14 10:02:11 -06003056
John Kessenich630dd7d2016-06-12 23:52:12 -06003057 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06003058}
3059
John Kesseniche01a9bc2016-03-12 20:11:22 -07003060} // end namespace glslang