blob: 9652129ca9a1dbb2cc3c853a520bbb1d75b7e72d [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
2//Copyright (C) 2016 Google, Inc.
LoopDawg6daaa4f2016-06-23 19:13:48 -06003//Copyright (C) 2016 LunarG, Inc.
John Kesseniche01a9bc2016-03-12 20:11:22 -07004//
5//All rights reserved.
6//
7//Redistribution and use in source and binary forms, with or without
8//modification, are permitted provided that the following conditions
9//are met:
10//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of Google, Inc., nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
23//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34//POSSIBILITY OF SUCH DAMAGE.
35//
36
John Kessenichd016be12016-03-13 11:24:20 -060037//
38// This is a set of mutually recursive methods implementing the HLSL grammar.
39// Generally, each returns
40// - through an argument: a type specifically appropriate to which rule it
41// recognized
42// - through the return value: true/false to indicate whether or not it
43// recognized its rule
44//
45// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060046// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060047// will build the AST.
48//
49// The next token, yet to be "accepted" is always sitting in 'token'.
50// When a method says it accepts a rule, that means all tokens involved
51// in the rule will have been consumed, and none left in 'token'.
52//
53
John Kesseniche01a9bc2016-03-12 20:11:22 -070054#include "hlslTokens.h"
55#include "hlslGrammar.h"
56
57namespace glslang {
58
59// Root entry point to this recursive decent parser.
60// Return true if compilation unit was successfully accepted.
61bool HlslGrammar::parse()
62{
63 advanceToken();
64 return acceptCompilationUnit();
65}
66
67void HlslGrammar::expected(const char* syntax)
68{
69 parseContext.error(token.loc, "Expected", syntax, "");
70}
71
LoopDawg4886f692016-06-29 10:58:58 -060072void HlslGrammar::unimplemented(const char* error)
73{
74 parseContext.error(token.loc, "Unimplemented", error, "");
75}
76
John Kessenichaecd4972016-03-14 10:46:34 -060077// Only process the next token if it is an identifier.
78// Return true if it was an identifier.
79bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
80{
81 if (peekTokenClass(EHTokIdentifier)) {
82 idToken = token;
83 advanceToken();
84 return true;
85 }
86
87 return false;
88}
89
John Kesseniche01a9bc2016-03-12 20:11:22 -070090// compilationUnit
91// : list of externalDeclaration
steve-lunargcb88de52016-08-03 07:04:18 -060092// | SEMICOLONS
John Kesseniche01a9bc2016-03-12 20:11:22 -070093//
94bool HlslGrammar::acceptCompilationUnit()
95{
John Kessenichd016be12016-03-13 11:24:20 -060096 TIntermNode* unitNode = nullptr;
97
John Kessenich9c86c6a2016-05-03 22:49:24 -060098 while (! peekTokenClass(EHTokNone)) {
steve-lunargcb88de52016-08-03 07:04:18 -060099 // HLSL allows semicolons between global declarations, e.g, between functions.
100 if (acceptTokenClass(EHTokSemicolon))
101 continue;
102
John Kessenichd016be12016-03-13 11:24:20 -0600103 // externalDeclaration
104 TIntermNode* declarationNode;
105 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700106 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600107
108 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600109 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700110 }
111
John Kessenichd016be12016-03-13 11:24:20 -0600112 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600113 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600114
John Kesseniche01a9bc2016-03-12 20:11:22 -0700115 return true;
116}
117
LoopDawg4886f692016-06-29 10:58:58 -0600118// sampler_state
119// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
120//
121// sampler_state_assignment
122// : sampler_state_identifier EQUAL value SEMICOLON
123//
124// sampler_state_identifier
125// : ADDRESSU
126// | ADDRESSV
127// | ADDRESSW
128// | BORDERCOLOR
129// | FILTER
130// | MAXANISOTROPY
131// | MAXLOD
132// | MINLOD
133// | MIPLODBIAS
134//
135bool HlslGrammar::acceptSamplerState()
136{
137 // TODO: this should be genericized to accept a list of valid tokens and
138 // return token/value pairs. Presently it is specific to texture values.
139
140 if (! acceptTokenClass(EHTokLeftBrace))
141 return true;
142
143 parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
144
145 do {
146 // read state name
147 HlslToken state;
148 if (! acceptIdentifier(state))
149 break; // end of list
150
151 // FXC accepts any case
152 TString stateName = *state.string;
153 std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
154
155 if (! acceptTokenClass(EHTokAssign)) {
156 expected("assign");
157 return false;
158 }
159
160 if (stateName == "minlod" || stateName == "maxlod") {
161 if (! peekTokenClass(EHTokIntConstant)) {
162 expected("integer");
163 return false;
164 }
165
166 TIntermTyped* lod = nullptr;
167 if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer
168 return false;
169 } else if (stateName == "maxanisotropy") {
170 if (! peekTokenClass(EHTokIntConstant)) {
171 expected("integer");
172 return false;
173 }
174
175 TIntermTyped* maxAnisotropy = nullptr;
176 if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer
177 return false;
178 } else if (stateName == "filter") {
179 HlslToken filterMode;
180 if (! acceptIdentifier(filterMode)) {
181 expected("filter mode");
182 return false;
183 }
184 } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
185 HlslToken addrMode;
186 if (! acceptIdentifier(addrMode)) {
187 expected("texture address mode");
188 return false;
189 }
190 } else if (stateName == "miplodbias") {
191 TIntermTyped* lodBias = nullptr;
192 if (! acceptLiteral(lodBias)) {
193 expected("lod bias");
194 return false;
195 }
196 } else if (stateName == "bordercolor") {
197 return false;
198 } else {
199 expected("texture state");
200 return false;
201 }
202
203 // SEMICOLON
204 if (! acceptTokenClass(EHTokSemicolon)) {
205 expected("semicolon");
206 return false;
207 }
208 } while (true);
209
210 if (! acceptTokenClass(EHTokRightBrace))
211 return false;
212
213 return true;
214}
215
216// sampler_declaration_dx9
217// : SAMPLER identifier EQUAL sampler_type sampler_state
218//
John Kesseniche4821e42016-07-16 10:19:43 -0600219bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
LoopDawg4886f692016-06-29 10:58:58 -0600220{
221 if (! acceptTokenClass(EHTokSampler))
222 return false;
223
224 // TODO: remove this when DX9 style declarations are implemented.
225 unimplemented("Direct3D 9 sampler declaration");
226
227 // read sampler name
228 HlslToken name;
229 if (! acceptIdentifier(name)) {
230 expected("sampler name");
231 return false;
232 }
233
234 if (! acceptTokenClass(EHTokAssign)) {
235 expected("=");
236 return false;
237 }
238
239 return false;
240}
241
242
John Kesseniche01a9bc2016-03-12 20:11:22 -0700243// declaration
LoopDawg4886f692016-06-29 10:58:58 -0600244// : sampler_declaration_dx9 post_decls SEMICOLON
245// | fully_specified_type declarator_list SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600246// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
LoopDawg4886f692016-06-29 10:58:58 -0600247// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
John Kessenich5e69ec62016-07-05 00:02:40 -0600248// | typedef declaration
John Kessenich87142c72016-03-12 20:24:24 -0700249//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600250// declarator_list
251// : declarator COMMA declarator COMMA declarator... // zero or more declarators
John Kessenich532543c2016-07-01 19:06:44 -0600252//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600253// declarator
John Kessenich532543c2016-07-01 19:06:44 -0600254// : identifier array_specifier post_decls
255// | identifier array_specifier post_decls EQUAL assignment_expression
John Kessenichd5ed0b62016-07-04 17:32:45 -0600256// | identifier function_parameters post_decls // function prototype
John Kessenich532543c2016-07-01 19:06:44 -0600257//
John Kessenichd5ed0b62016-07-04 17:32:45 -0600258// Parsing has to go pretty far in to know whether it's a variable, prototype, or
259// function definition, so the implementation below doesn't perfectly divide up the grammar
John Kessenich532543c2016-07-01 19:06:44 -0600260// as above. (The 'identifier' in the first item in init_declarator list is the
261// same as 'identifier' for function declarations.)
262//
263// 'node' could get populated if the declaration creates code, like an initializer
John Kessenichd016be12016-03-13 11:24:20 -0600264// or a function body.
265//
266bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700267{
John Kessenichd016be12016-03-13 11:24:20 -0600268 node = nullptr;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600269 bool list = false;
John Kessenichd016be12016-03-13 11:24:20 -0600270
John Kessenich5e69ec62016-07-05 00:02:40 -0600271 // typedef
272 bool typedefDecl = acceptTokenClass(EHTokTypedef);
273
John Kesseniche82061d2016-09-27 14:38:57 -0600274 TType declaredType;
LoopDawg4886f692016-06-29 10:58:58 -0600275
276 // DX9 sampler declaration use a different syntax
John Kessenich267590d2016-08-05 17:34:34 -0600277 // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
278 // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
279 // HLSL shaders, this will have to be a master level switch
280 // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
281 // For that reason, this line is commented out
Dan Bakerc7e50162016-08-05 14:52:38 -0400282
John Kesseniche82061d2016-09-27 14:38:57 -0600283 // if (acceptSamplerDeclarationDX9(declaredType))
Dan Bakerc7e50162016-08-05 14:52:38 -0400284 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600285
286 // fully_specified_type
John Kesseniche82061d2016-09-27 14:38:57 -0600287 if (! acceptFullySpecifiedType(declaredType))
John Kessenich87142c72016-03-12 20:24:24 -0700288 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600289
John Kessenich87142c72016-03-12 20:24:24 -0700290 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600291 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600292 while (acceptIdentifier(idToken)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600293 // function_parameters
John Kesseniche82061d2016-09-27 14:38:57 -0600294 TFunction& function = *new TFunction(idToken.string, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600295 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600296 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600297 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600298
John Kessenichd5ed0b62016-07-04 17:32:45 -0600299 // compound_statement (function body definition) or just a prototype?
300 if (peekTokenClass(EHTokLeftBrace)) {
301 if (list)
302 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600303 if (typedefDecl)
304 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600305 return acceptFunctionDefinition(function, node);
John Kessenich5e69ec62016-07-05 00:02:40 -0600306 } else {
307 if (typedefDecl)
308 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600309 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600310 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600311 } else {
John Kessenich6dbc0a72016-09-27 19:13:05 -0600312 // A variable declaration. Fix the storage qualifier if it's a global.
313 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
314 declaredType.getQualifier().storage = EvqUniform;
315
John Kesseniche82061d2016-09-27 14:38:57 -0600316 // We can handle multiple variables per type declaration, so
317 // the number of types can expand when arrayness is different.
318 TType variableType;
319 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600320
John Kesseniche82061d2016-09-27 14:38:57 -0600321 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600322 TArraySizes* arraySizes = nullptr;
323 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600324
John Kesseniche82061d2016-09-27 14:38:57 -0600325 // Fix arrayness in the variableType
326 if (declaredType.isImplicitlySizedArray()) {
327 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
328 // of different sizes, for this case sharing the shallow copy of arrayness
329 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
330 variableType.newArraySizes(declaredType.getArraySizes());
331 }
332 if (arraySizes || variableType.isArray()) {
333 // In the most general case, arrayness is potentially coming both from the
334 // declared type and from the variable: "int[] a[];" or just one or the other.
335 // Merge it all to the variableType, so all arrayness is part of the variableType.
336 parseContext.arrayDimMerge(variableType, arraySizes);
337 }
338
LoopDawg4886f692016-06-29 10:58:58 -0600339 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600340 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600341 if (! acceptSamplerState())
342 return false;
343 }
344
John Kessenichd5ed0b62016-07-04 17:32:45 -0600345 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600346 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600347
348 // EQUAL assignment_expression
349 TIntermTyped* expressionNode = nullptr;
350 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600351 if (typedefDecl)
352 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600353 if (! acceptAssignmentExpression(expressionNode)) {
354 expected("initializer");
355 return false;
356 }
357 }
358
John Kessenich6dbc0a72016-09-27 19:13:05 -0600359 // Hand off the actual declaration
360
361 // TODO: things scoped within an annotation need their own name space;
362 // TODO: strings are not yet handled.
363 if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
364 if (typedefDecl)
365 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType);
366 else if (variableType.getBasicType() == EbtBlock)
367 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
368 else {
369 if (variableType.getQualifier().storage == EvqUniform && variableType.getBasicType() != EbtSampler) {
370 // this isn't really an individual variable, but a member of the $Global buffer
371 parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
372 } else {
373 // Declare the variable and add any initializer code to the AST.
374 // The top-level node is always made into an aggregate, as that's
375 // historically how the AST has been.
376 node = intermediate.growAggregate(node,
377 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
378 expressionNode),
379 idToken.loc);
380 }
381 }
John Kessenich5e69ec62016-07-05 00:02:40 -0600382 }
John Kessenich5f934b02016-03-13 17:58:25 -0600383 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600384
385 if (acceptTokenClass(EHTokComma)) {
386 list = true;
387 continue;
388 }
389 };
390
391 // The top-level node is a sequence.
392 if (node != nullptr)
393 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700394
John Kessenich078d7f22016-03-14 10:02:11 -0600395 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600396 if (! acceptTokenClass(EHTokSemicolon)) {
397 expected(";");
398 return false;
399 }
400
John Kesseniche01a9bc2016-03-12 20:11:22 -0700401 return true;
402}
403
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600404// control_declaration
405// : fully_specified_type identifier EQUAL expression
406//
407bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
408{
409 node = nullptr;
410
411 // fully_specified_type
412 TType type;
413 if (! acceptFullySpecifiedType(type))
414 return false;
415
416 // identifier
417 HlslToken idToken;
418 if (! acceptIdentifier(idToken)) {
419 expected("identifier");
420 return false;
421 }
422
423 // EQUAL
424 TIntermTyped* expressionNode = nullptr;
425 if (! acceptTokenClass(EHTokAssign)) {
426 expected("=");
427 return false;
428 }
429
430 // expression
431 if (! acceptExpression(expressionNode)) {
432 expected("initializer");
433 return false;
434 }
435
John Kesseniche82061d2016-09-27 14:38:57 -0600436 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600437
438 return true;
439}
440
John Kessenich87142c72016-03-12 20:24:24 -0700441// fully_specified_type
442// : type_specifier
443// | type_qualifier type_specifier
444//
445bool HlslGrammar::acceptFullySpecifiedType(TType& type)
446{
447 // type_qualifier
448 TQualifier qualifier;
449 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600450 if (! acceptQualifier(qualifier))
451 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600452 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700453
454 // type_specifier
455 if (! acceptType(type))
456 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600457 if (type.getBasicType() == EbtBlock) {
458 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600459 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600460 // further, it can create an anonymous instance of the block
461 if (peekTokenClass(EHTokSemicolon))
462 parseContext.declareBlock(loc, type);
463 } else
464 type.getQualifier() = qualifier;
John Kessenich87142c72016-03-12 20:24:24 -0700465
466 return true;
467}
468
John Kessenich630dd7d2016-06-12 23:52:12 -0600469// type_qualifier
470// : qualifier qualifier ...
471//
472// Zero or more of these, so this can't return false.
473//
John Kessenichb9e39122016-08-17 10:22:08 -0600474bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700475{
John Kessenich630dd7d2016-06-12 23:52:12 -0600476 do {
477 switch (peek()) {
478 case EHTokStatic:
John Kessenich6dbc0a72016-09-27 19:13:05 -0600479 qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
John Kessenich630dd7d2016-06-12 23:52:12 -0600480 break;
481 case EHTokExtern:
482 // TODO: no meaning in glslang?
483 break;
484 case EHTokShared:
485 // TODO: hint
486 break;
487 case EHTokGroupShared:
488 qualifier.storage = EvqShared;
489 break;
490 case EHTokUniform:
491 qualifier.storage = EvqUniform;
492 break;
493 case EHTokConst:
494 qualifier.storage = EvqConst;
495 break;
496 case EHTokVolatile:
497 qualifier.volatil = true;
498 break;
499 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600500 qualifier.smooth = true;
501 break;
502 case EHTokCentroid:
503 qualifier.centroid = true;
504 break;
505 case EHTokNointerpolation:
506 qualifier.flat = true;
507 break;
508 case EHTokNoperspective:
509 qualifier.nopersp = true;
510 break;
511 case EHTokSample:
512 qualifier.sample = true;
513 break;
514 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600515 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600516 break;
517 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600518 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600519 break;
520 case EHTokPrecise:
521 qualifier.noContraction = true;
522 break;
LoopDawg9249c702016-07-12 20:44:32 -0600523 case EHTokIn:
524 qualifier.storage = EvqIn;
525 break;
526 case EHTokOut:
527 qualifier.storage = EvqOut;
528 break;
529 case EHTokInOut:
530 qualifier.storage = EvqInOut;
531 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600532 case EHTokLayout:
533 if (! acceptLayoutQualifierList(qualifier))
534 return false;
535 continue;
John Kessenich630dd7d2016-06-12 23:52:12 -0600536 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600537 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600538 }
539 advanceToken();
540 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700541}
542
John Kessenichb9e39122016-08-17 10:22:08 -0600543// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600544// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600545//
546// layout_qualifier
547// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600548// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600549//
550// Zero or more of these, so this can't return false.
551//
552bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
553{
554 if (! acceptTokenClass(EHTokLayout))
555 return false;
556
557 // LEFT_PAREN
558 if (! acceptTokenClass(EHTokLeftParen))
559 return false;
560
561 do {
562 // identifier
563 HlslToken idToken;
564 if (! acceptIdentifier(idToken))
565 break;
566
567 // EQUAL expression
568 if (acceptTokenClass(EHTokAssign)) {
569 TIntermTyped* expr;
570 if (! acceptConditionalExpression(expr)) {
571 expected("expression");
572 return false;
573 }
574 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
575 } else
576 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
577
578 // COMMA
579 if (! acceptTokenClass(EHTokComma))
580 break;
581 } while (true);
582
583 // RIGHT_PAREN
584 if (! acceptTokenClass(EHTokRightParen)) {
585 expected(")");
586 return false;
587 }
588
589 return true;
590}
591
LoopDawg6daaa4f2016-06-23 19:13:48 -0600592// template_type
593// : FLOAT
594// | DOUBLE
595// | INT
596// | DWORD
597// | UINT
598// | BOOL
599//
600bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
601{
602 switch (peek()) {
603 case EHTokFloat:
604 basicType = EbtFloat;
605 break;
606 case EHTokDouble:
607 basicType = EbtDouble;
608 break;
609 case EHTokInt:
610 case EHTokDword:
611 basicType = EbtInt;
612 break;
613 case EHTokUint:
614 basicType = EbtUint;
615 break;
616 case EHTokBool:
617 basicType = EbtBool;
618 break;
619 default:
620 return false;
621 }
622
623 advanceToken();
624
625 return true;
626}
627
628// vector_template_type
629// : VECTOR
630// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
631//
632bool HlslGrammar::acceptVectorTemplateType(TType& type)
633{
634 if (! acceptTokenClass(EHTokVector))
635 return false;
636
637 if (! acceptTokenClass(EHTokLeftAngle)) {
638 // in HLSL, 'vector' alone means float4.
639 new(&type) TType(EbtFloat, EvqTemporary, 4);
640 return true;
641 }
642
643 TBasicType basicType;
644 if (! acceptTemplateType(basicType)) {
645 expected("scalar type");
646 return false;
647 }
648
649 // COMMA
650 if (! acceptTokenClass(EHTokComma)) {
651 expected(",");
652 return false;
653 }
654
655 // integer
656 if (! peekTokenClass(EHTokIntConstant)) {
657 expected("literal integer");
658 return false;
659 }
660
661 TIntermTyped* vecSize;
662 if (! acceptLiteral(vecSize))
663 return false;
664
665 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
666
667 new(&type) TType(basicType, EvqTemporary, vecSizeI);
668
669 if (vecSizeI == 1)
670 type.makeVector();
671
672 if (!acceptTokenClass(EHTokRightAngle)) {
673 expected("right angle bracket");
674 return false;
675 }
676
677 return true;
678}
679
680// matrix_template_type
681// : MATRIX
682// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
683//
684bool HlslGrammar::acceptMatrixTemplateType(TType& type)
685{
686 if (! acceptTokenClass(EHTokMatrix))
687 return false;
688
689 if (! acceptTokenClass(EHTokLeftAngle)) {
690 // in HLSL, 'matrix' alone means float4x4.
691 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
692 return true;
693 }
694
695 TBasicType basicType;
696 if (! acceptTemplateType(basicType)) {
697 expected("scalar type");
698 return false;
699 }
700
701 // COMMA
702 if (! acceptTokenClass(EHTokComma)) {
703 expected(",");
704 return false;
705 }
706
707 // integer rows
708 if (! peekTokenClass(EHTokIntConstant)) {
709 expected("literal integer");
710 return false;
711 }
712
713 TIntermTyped* rows;
714 if (! acceptLiteral(rows))
715 return false;
716
717 // COMMA
718 if (! acceptTokenClass(EHTokComma)) {
719 expected(",");
720 return false;
721 }
722
723 // integer cols
724 if (! peekTokenClass(EHTokIntConstant)) {
725 expected("literal integer");
726 return false;
727 }
728
729 TIntermTyped* cols;
730 if (! acceptLiteral(cols))
731 return false;
732
733 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600734 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
735 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600736
737 if (!acceptTokenClass(EHTokRightAngle)) {
738 expected("right angle bracket");
739 return false;
740 }
741
742 return true;
743}
744
John Kessenicha1e2d492016-09-20 13:22:58 -0600745// annotations
746// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600747//
John Kessenicha1e2d492016-09-20 13:22:58 -0600748bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600749{
John Kessenicha1e2d492016-09-20 13:22:58 -0600750 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600751 return false;
752
John Kessenicha1e2d492016-09-20 13:22:58 -0600753 // note that we are nesting a name space
754 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600755
756 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
757 do {
758 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
759 while (acceptTokenClass(EHTokSemicolon))
760 ;
761
762 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600763 break;
John Kessenich86f71382016-09-19 20:23:18 -0600764
765 // declaration
766 TIntermNode* node;
767 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600768 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600769 return false;
770 }
771 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600772
773 parseContext.unnestAnnotations();
774 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600775}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600776
LoopDawg4886f692016-06-29 10:58:58 -0600777// sampler_type
778// : SAMPLER
779// | SAMPLER1D
780// | SAMPLER2D
781// | SAMPLER3D
782// | SAMPLERCUBE
783// | SAMPLERSTATE
784// | SAMPLERCOMPARISONSTATE
785bool HlslGrammar::acceptSamplerType(TType& type)
786{
787 // read sampler type
788 const EHlslTokenClass samplerType = peek();
789
LoopDawga78b0292016-07-19 14:28:05 -0600790 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600791 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600792
LoopDawga78b0292016-07-19 14:28:05 -0600793 bool isShadow = false;
794
LoopDawg4886f692016-06-29 10:58:58 -0600795 switch (samplerType) {
796 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600797 case EHTokSampler1d: /*dim = Esd1D*/; break;
798 case EHTokSampler2d: /*dim = Esd2D*/; break;
799 case EHTokSampler3d: /*dim = Esd3D*/; break;
800 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600801 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600802 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600803 default:
804 return false; // not a sampler declaration
805 }
806
807 advanceToken(); // consume the sampler type keyword
808
809 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600810
811 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600812 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600813
814 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
815
816 return true;
817}
818
819// texture_type
820// | BUFFER
821// | TEXTURE1D
822// | TEXTURE1DARRAY
823// | TEXTURE2D
824// | TEXTURE2DARRAY
825// | TEXTURE3D
826// | TEXTURECUBE
827// | TEXTURECUBEARRAY
828// | TEXTURE2DMS
829// | TEXTURE2DMSARRAY
830bool HlslGrammar::acceptTextureType(TType& type)
831{
832 const EHlslTokenClass textureType = peek();
833
834 TSamplerDim dim = EsdNone;
835 bool array = false;
836 bool ms = false;
837
838 switch (textureType) {
839 case EHTokBuffer: dim = EsdBuffer; break;
840 case EHTokTexture1d: dim = Esd1D; break;
841 case EHTokTexture1darray: dim = Esd1D; array = true; break;
842 case EHTokTexture2d: dim = Esd2D; break;
843 case EHTokTexture2darray: dim = Esd2D; array = true; break;
844 case EHTokTexture3d: dim = Esd3D; break;
845 case EHTokTextureCube: dim = EsdCube; break;
846 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
847 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
848 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
849 default:
850 return false; // not a texture declaration
851 }
852
853 advanceToken(); // consume the texture object keyword
854
855 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
856
857 TIntermTyped* msCount = nullptr;
858
859 // texture type: required for multisample types!
860 if (acceptTokenClass(EHTokLeftAngle)) {
861 if (! acceptType(txType)) {
862 expected("scalar or vector type");
863 return false;
864 }
865
866 const TBasicType basicRetType = txType.getBasicType() ;
867
868 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
869 unimplemented("basic type in texture");
870 return false;
871 }
872
steve-lunargd53f7172016-07-27 15:46:48 -0600873 // Buffers can handle small mats if they fit in 4 components
874 if (dim == EsdBuffer && txType.isMatrix()) {
875 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
876 expected("components < 4 in matrix buffer type");
877 return false;
878 }
879
880 // TODO: except we don't handle it yet...
881 unimplemented("matrix type in buffer");
882 return false;
883 }
884
LoopDawg4886f692016-06-29 10:58:58 -0600885 if (!txType.isScalar() && !txType.isVector()) {
886 expected("scalar or vector type");
887 return false;
888 }
889
890 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
891 // TODO: handle vec2/3 types
892 expected("vector size not yet supported in texture type");
893 return false;
894 }
895
896 if (ms && acceptTokenClass(EHTokComma)) {
897 // read sample count for multisample types, if given
898 if (! peekTokenClass(EHTokIntConstant)) {
899 expected("multisample count");
900 return false;
901 }
902
903 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
904 return false;
905 }
906
907 if (! acceptTokenClass(EHTokRightAngle)) {
908 expected("right angle bracket");
909 return false;
910 }
911 } else if (ms) {
912 expected("texture type for multisample");
913 return false;
914 }
915
916 TArraySizes* arraySizes = nullptr;
917 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
918
919 TSampler sampler;
steve-lunargd53f7172016-07-27 15:46:48 -0600920
921 // Buffers are combined.
922 if (dim == EsdBuffer) {
923 sampler.set(txType.getBasicType(), dim, array);
924 } else {
925 // DX10 textures are separated. TODO: DX9.
926 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
927 }
LoopDawg4886f692016-06-29 10:58:58 -0600928
929 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
930
931 return true;
932}
933
934
John Kessenich87142c72016-03-12 20:24:24 -0700935// If token is for a type, update 'type' with the type information,
936// and return true and advance.
937// Otherwise, return false, and don't advance
938bool HlslGrammar::acceptType(TType& type)
939{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600940 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600941 case EHTokVector:
942 return acceptVectorTemplateType(type);
943 break;
944
945 case EHTokMatrix:
946 return acceptMatrixTemplateType(type);
947 break;
948
LoopDawg4886f692016-06-29 10:58:58 -0600949 case EHTokSampler: // fall through
950 case EHTokSampler1d: // ...
951 case EHTokSampler2d: // ...
952 case EHTokSampler3d: // ...
953 case EHTokSamplerCube: // ...
954 case EHTokSamplerState: // ...
955 case EHTokSamplerComparisonState: // ...
956 return acceptSamplerType(type);
957 break;
958
959 case EHTokBuffer: // fall through
960 case EHTokTexture1d: // ...
961 case EHTokTexture1darray: // ...
962 case EHTokTexture2d: // ...
963 case EHTokTexture2darray: // ...
964 case EHTokTexture3d: // ...
965 case EHTokTextureCube: // ...
966 case EHTokTextureCubearray: // ...
967 case EHTokTexture2DMS: // ...
968 case EHTokTexture2DMSarray: // ...
969 return acceptTextureType(type);
970 break;
971
John Kesseniche6e74942016-06-11 16:43:14 -0600972 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600973 case EHTokCBuffer:
974 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600975 return acceptStruct(type);
976 break;
977
978 case EHTokIdentifier:
979 // An identifier could be for a user-defined type.
980 // Note we cache the symbol table lookup, to save for a later rule
981 // when this is not a type.
982 token.symbol = parseContext.symbolTable.find(*token.string);
983 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
984 type.shallowCopy(token.symbol->getType());
985 advanceToken();
986 return true;
987 } else
988 return false;
989
John Kessenich71351de2016-06-08 12:50:56 -0600990 case EHTokVoid:
991 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700992 break;
John Kessenich71351de2016-06-08 12:50:56 -0600993
John Kessenicha1e2d492016-09-20 13:22:58 -0600994 case EHTokString:
995 new(&type) TType(EbtString);
996 break;
997
John Kessenich87142c72016-03-12 20:24:24 -0700998 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600999 new(&type) TType(EbtFloat);
1000 break;
John Kessenich87142c72016-03-12 20:24:24 -07001001 case EHTokFloat1:
1002 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001003 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001004 break;
John Kessenich87142c72016-03-12 20:24:24 -07001005 case EHTokFloat2:
1006 new(&type) TType(EbtFloat, EvqTemporary, 2);
1007 break;
1008 case EHTokFloat3:
1009 new(&type) TType(EbtFloat, EvqTemporary, 3);
1010 break;
1011 case EHTokFloat4:
1012 new(&type) TType(EbtFloat, EvqTemporary, 4);
1013 break;
1014
John Kessenich71351de2016-06-08 12:50:56 -06001015 case EHTokDouble:
1016 new(&type) TType(EbtDouble);
1017 break;
1018 case EHTokDouble1:
1019 new(&type) TType(EbtDouble);
1020 type.makeVector();
1021 break;
1022 case EHTokDouble2:
1023 new(&type) TType(EbtDouble, EvqTemporary, 2);
1024 break;
1025 case EHTokDouble3:
1026 new(&type) TType(EbtDouble, EvqTemporary, 3);
1027 break;
1028 case EHTokDouble4:
1029 new(&type) TType(EbtDouble, EvqTemporary, 4);
1030 break;
1031
1032 case EHTokInt:
1033 case EHTokDword:
1034 new(&type) TType(EbtInt);
1035 break;
1036 case EHTokInt1:
1037 new(&type) TType(EbtInt);
1038 type.makeVector();
1039 break;
John Kessenich87142c72016-03-12 20:24:24 -07001040 case EHTokInt2:
1041 new(&type) TType(EbtInt, EvqTemporary, 2);
1042 break;
1043 case EHTokInt3:
1044 new(&type) TType(EbtInt, EvqTemporary, 3);
1045 break;
1046 case EHTokInt4:
1047 new(&type) TType(EbtInt, EvqTemporary, 4);
1048 break;
1049
John Kessenich71351de2016-06-08 12:50:56 -06001050 case EHTokUint:
1051 new(&type) TType(EbtUint);
1052 break;
1053 case EHTokUint1:
1054 new(&type) TType(EbtUint);
1055 type.makeVector();
1056 break;
1057 case EHTokUint2:
1058 new(&type) TType(EbtUint, EvqTemporary, 2);
1059 break;
1060 case EHTokUint3:
1061 new(&type) TType(EbtUint, EvqTemporary, 3);
1062 break;
1063 case EHTokUint4:
1064 new(&type) TType(EbtUint, EvqTemporary, 4);
1065 break;
1066
LoopDawg6daaa4f2016-06-23 19:13:48 -06001067
John Kessenich71351de2016-06-08 12:50:56 -06001068 case EHTokBool:
1069 new(&type) TType(EbtBool);
1070 break;
1071 case EHTokBool1:
1072 new(&type) TType(EbtBool);
1073 type.makeVector();
1074 break;
John Kessenich87142c72016-03-12 20:24:24 -07001075 case EHTokBool2:
1076 new(&type) TType(EbtBool, EvqTemporary, 2);
1077 break;
1078 case EHTokBool3:
1079 new(&type) TType(EbtBool, EvqTemporary, 3);
1080 break;
1081 case EHTokBool4:
1082 new(&type) TType(EbtBool, EvqTemporary, 4);
1083 break;
1084
John Kessenich0133c122016-05-20 12:17:26 -06001085 case EHTokInt1x1:
1086 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1087 break;
1088 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001089 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001090 break;
1091 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001092 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001093 break;
1094 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001095 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001096 break;
1097 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001098 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001099 break;
1100 case EHTokInt2x2:
1101 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1102 break;
1103 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001104 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001105 break;
1106 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001107 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001108 break;
1109 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001110 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001111 break;
1112 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001113 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001114 break;
1115 case EHTokInt3x3:
1116 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1117 break;
1118 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001119 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001120 break;
1121 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001122 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001123 break;
1124 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001125 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001126 break;
1127 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001128 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001129 break;
1130 case EHTokInt4x4:
1131 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1132 break;
1133
John Kessenich71351de2016-06-08 12:50:56 -06001134 case EHTokUint1x1:
1135 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1136 break;
1137 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001138 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001139 break;
1140 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001141 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001142 break;
1143 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001144 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001145 break;
1146 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001147 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001148 break;
1149 case EHTokUint2x2:
1150 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1151 break;
1152 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001153 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001154 break;
1155 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001156 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001157 break;
1158 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001159 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001160 break;
1161 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001162 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001163 break;
1164 case EHTokUint3x3:
1165 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1166 break;
1167 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001168 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001169 break;
1170 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001171 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001172 break;
1173 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001174 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001175 break;
1176 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001177 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001178 break;
1179 case EHTokUint4x4:
1180 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1181 break;
1182
1183 case EHTokBool1x1:
1184 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1185 break;
1186 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001187 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001188 break;
1189 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001190 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001191 break;
1192 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001193 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001194 break;
1195 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001196 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001197 break;
1198 case EHTokBool2x2:
1199 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1200 break;
1201 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001202 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001203 break;
1204 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001205 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001206 break;
1207 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001208 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001209 break;
1210 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001211 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001212 break;
1213 case EHTokBool3x3:
1214 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1215 break;
1216 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001217 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001218 break;
1219 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001220 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001221 break;
1222 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001223 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001224 break;
1225 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001226 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001227 break;
1228 case EHTokBool4x4:
1229 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1230 break;
1231
John Kessenich0133c122016-05-20 12:17:26 -06001232 case EHTokFloat1x1:
1233 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1234 break;
1235 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001236 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001237 break;
1238 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001239 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001240 break;
1241 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001242 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001243 break;
1244 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001245 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001246 break;
John Kessenich87142c72016-03-12 20:24:24 -07001247 case EHTokFloat2x2:
1248 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1249 break;
1250 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001251 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001252 break;
1253 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001254 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001255 break;
John Kessenich0133c122016-05-20 12:17:26 -06001256 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001257 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001258 break;
John Kessenich87142c72016-03-12 20:24:24 -07001259 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001260 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001261 break;
1262 case EHTokFloat3x3:
1263 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1264 break;
1265 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001266 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001267 break;
John Kessenich0133c122016-05-20 12:17:26 -06001268 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001269 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001270 break;
John Kessenich87142c72016-03-12 20:24:24 -07001271 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001272 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001273 break;
1274 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001275 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001276 break;
1277 case EHTokFloat4x4:
1278 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1279 break;
1280
John Kessenich0133c122016-05-20 12:17:26 -06001281 case EHTokDouble1x1:
1282 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1283 break;
1284 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001285 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001286 break;
1287 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001288 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001289 break;
1290 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001291 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001292 break;
1293 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001294 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001295 break;
1296 case EHTokDouble2x2:
1297 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1298 break;
1299 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001300 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001301 break;
1302 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001303 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001304 break;
1305 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001306 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001307 break;
1308 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001309 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001310 break;
1311 case EHTokDouble3x3:
1312 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1313 break;
1314 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001315 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001316 break;
1317 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001318 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001319 break;
1320 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001321 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001322 break;
1323 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001324 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001325 break;
1326 case EHTokDouble4x4:
1327 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1328 break;
1329
John Kessenich87142c72016-03-12 20:24:24 -07001330 default:
1331 return false;
1332 }
1333
1334 advanceToken();
1335
1336 return true;
1337}
1338
John Kesseniche6e74942016-06-11 16:43:14 -06001339// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001340// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1341// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1342//
1343// struct_type
1344// : STRUCT
1345// | CBUFFER
1346// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001347//
1348bool HlslGrammar::acceptStruct(TType& type)
1349{
John Kessenichb804de62016-09-05 12:19:18 -06001350 // This storage qualifier will tell us whether it's an AST
1351 // block type or just a generic structure type.
1352 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001353
1354 // CBUFFER
1355 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001356 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001357 // TBUFFER
1358 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001359 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001360 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001361 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001362 return false;
1363
1364 // IDENTIFIER
1365 TString structName = "";
1366 if (peekTokenClass(EHTokIdentifier)) {
1367 structName = *token.string;
1368 advanceToken();
1369 }
1370
John Kessenich3d157c52016-07-25 16:05:33 -06001371 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001372 TQualifier postDeclQualifier;
1373 postDeclQualifier.clear();
1374 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001375
John Kesseniche6e74942016-06-11 16:43:14 -06001376 // LEFT_BRACE
1377 if (! acceptTokenClass(EHTokLeftBrace)) {
1378 expected("{");
1379 return false;
1380 }
1381
1382 // struct_declaration_list
1383 TTypeList* typeList;
1384 if (! acceptStructDeclarationList(typeList)) {
1385 expected("struct member declarations");
1386 return false;
1387 }
1388
1389 // RIGHT_BRACE
1390 if (! acceptTokenClass(EHTokRightBrace)) {
1391 expected("}");
1392 return false;
1393 }
1394
1395 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001396 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001397 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001398 else {
John Kessenich7735b942016-09-05 12:40:06 -06001399 postDeclQualifier.storage = storageQualifier;
1400 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001401 }
John Kesseniche6e74942016-06-11 16:43:14 -06001402
John Kessenich3d157c52016-07-25 16:05:33 -06001403 // If it was named, which means the type can be reused later, add
1404 // it to the symbol table. (Unless it's a block, in which
1405 // case the name is not a type.)
1406 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001407 TVariable* userTypeDef = new TVariable(&structName, type, true);
1408 if (! parseContext.symbolTable.insert(*userTypeDef))
1409 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1410 }
1411
1412 return true;
1413}
1414
1415// struct_declaration_list
1416// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1417//
1418// struct_declaration
1419// : fully_specified_type struct_declarator COMMA struct_declarator ...
1420//
1421// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001422// : IDENTIFIER post_decls
1423// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001424//
1425bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1426{
1427 typeList = new TTypeList();
1428
1429 do {
1430 // success on seeing the RIGHT_BRACE coming up
1431 if (peekTokenClass(EHTokRightBrace))
1432 return true;
1433
1434 // struct_declaration
1435
1436 // fully_specified_type
1437 TType memberType;
1438 if (! acceptFullySpecifiedType(memberType)) {
1439 expected("member type");
1440 return false;
1441 }
1442
1443 // struct_declarator COMMA struct_declarator ...
1444 do {
1445 // peek IDENTIFIER
1446 if (! peekTokenClass(EHTokIdentifier)) {
1447 expected("member name");
1448 return false;
1449 }
1450
1451 // add it to the list of members
1452 TTypeLoc member = { new TType(EbtVoid), token.loc };
1453 member.type->shallowCopy(memberType);
1454 member.type->setFieldName(*token.string);
1455 typeList->push_back(member);
1456
1457 // accept IDENTIFIER
1458 advanceToken();
1459
1460 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001461 TArraySizes* arraySizes = nullptr;
1462 acceptArraySpecifier(arraySizes);
1463 if (arraySizes)
1464 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001465
John Kessenich7735b942016-09-05 12:40:06 -06001466 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001467
John Kesseniche6e74942016-06-11 16:43:14 -06001468 // success on seeing the SEMICOLON coming up
1469 if (peekTokenClass(EHTokSemicolon))
1470 break;
1471
1472 // COMMA
1473 if (! acceptTokenClass(EHTokComma)) {
1474 expected(",");
1475 return false;
1476 }
1477
1478 } while (true);
1479
1480 // SEMI_COLON
1481 if (! acceptTokenClass(EHTokSemicolon)) {
1482 expected(";");
1483 return false;
1484 }
1485
1486 } while (true);
1487}
1488
John Kessenich5f934b02016-03-13 17:58:25 -06001489// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001490// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001491// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001492//
1493bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1494{
John Kessenich078d7f22016-03-14 10:02:11 -06001495 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001496 if (! acceptTokenClass(EHTokLeftParen))
1497 return false;
1498
John Kessenich71351de2016-06-08 12:50:56 -06001499 // VOID RIGHT_PAREN
1500 if (! acceptTokenClass(EHTokVoid)) {
1501 do {
1502 // parameter_declaration
1503 if (! acceptParameterDeclaration(function))
1504 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001505
John Kessenich71351de2016-06-08 12:50:56 -06001506 // COMMA
1507 if (! acceptTokenClass(EHTokComma))
1508 break;
1509 } while (true);
1510 }
John Kessenich5f934b02016-03-13 17:58:25 -06001511
John Kessenich078d7f22016-03-14 10:02:11 -06001512 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001513 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001514 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001515 return false;
1516 }
1517
1518 return true;
1519}
1520
1521// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001522// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001523// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001524//
1525bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1526{
1527 // fully_specified_type
1528 TType* type = new TType;
1529 if (! acceptFullySpecifiedType(*type))
1530 return false;
1531
1532 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001533 HlslToken idToken;
1534 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001535
John Kessenich19b92ff2016-06-19 11:50:34 -06001536 // array_specifier
1537 TArraySizes* arraySizes = nullptr;
1538 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001539 if (arraySizes) {
1540 if (arraySizes->isImplicit()) {
1541 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1542 return false;
1543 }
1544
John Kessenich19b92ff2016-06-19 11:50:34 -06001545 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001546 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001547
1548 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001549 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001550
John Kessenich5aa59e22016-06-17 15:50:47 -06001551 parseContext.paramFix(*type);
1552
John Kessenichaecd4972016-03-14 10:46:34 -06001553 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001554 function.addParameter(param);
1555
1556 return true;
1557}
1558
1559// Do the work to create the function definition in addition to
1560// parsing the body (compound_statement).
1561bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1562{
John Kessenicha3051662016-09-02 19:13:36 -06001563 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001564 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001565
John Kessenich077e0522016-06-09 02:02:17 -06001566 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001567 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001568
1569 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001570 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001571 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001572 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001573 return true;
1574 }
1575
1576 return false;
1577}
1578
John Kessenich0d2b6de2016-06-05 11:23:11 -06001579// Accept an expression with parenthesis around it, where
1580// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001581// syntactically required ones like in "if ( expression )".
1582//
1583// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001584//
1585// Note this one is not set up to be speculative; as it gives
1586// errors if not found.
1587//
1588bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1589{
1590 // LEFT_PAREN
1591 if (! acceptTokenClass(EHTokLeftParen))
1592 expected("(");
1593
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001594 bool decl = false;
1595 TIntermNode* declNode = nullptr;
1596 decl = acceptControlDeclaration(declNode);
1597 if (decl) {
1598 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1599 expected("initialized declaration");
1600 return false;
1601 } else
1602 expression = declNode->getAsTyped();
1603 } else {
1604 // no declaration
1605 if (! acceptExpression(expression)) {
1606 expected("expression");
1607 return false;
1608 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001609 }
1610
1611 // RIGHT_PAREN
1612 if (! acceptTokenClass(EHTokRightParen))
1613 expected(")");
1614
1615 return true;
1616}
1617
John Kessenich34fb0362016-05-03 23:17:20 -06001618// The top-level full expression recognizer.
1619//
John Kessenich87142c72016-03-12 20:24:24 -07001620// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001621// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001622//
1623bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1624{
LoopDawgef764a22016-06-03 09:17:51 -06001625 node = nullptr;
1626
John Kessenich34fb0362016-05-03 23:17:20 -06001627 // assignment_expression
1628 if (! acceptAssignmentExpression(node))
1629 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001630
John Kessenich34fb0362016-05-03 23:17:20 -06001631 if (! peekTokenClass(EHTokComma))
1632 return true;
1633
1634 do {
1635 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001636 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001637 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001638
John Kessenich34fb0362016-05-03 23:17:20 -06001639 // ... assignment_expression
1640 TIntermTyped* rightNode = nullptr;
1641 if (! acceptAssignmentExpression(rightNode)) {
1642 expected("assignment expression");
1643 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001644 }
1645
John Kessenich34fb0362016-05-03 23:17:20 -06001646 node = intermediate.addComma(node, rightNode, loc);
1647
1648 if (! peekTokenClass(EHTokComma))
1649 return true;
1650 } while (true);
1651}
1652
John Kessenich07354242016-07-01 19:58:06 -06001653// initializer
1654// : LEFT_BRACE initializer_list RIGHT_BRACE
1655//
1656// initializer_list
1657// : assignment_expression COMMA assignment_expression COMMA ...
1658//
1659bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1660{
1661 // LEFT_BRACE
1662 if (! acceptTokenClass(EHTokLeftBrace))
1663 return false;
1664
1665 // initializer_list
1666 TSourceLoc loc = token.loc;
1667 node = nullptr;
1668 do {
1669 // assignment_expression
1670 TIntermTyped* expr;
1671 if (! acceptAssignmentExpression(expr)) {
1672 expected("assignment expression in initializer list");
1673 return false;
1674 }
1675 node = intermediate.growAggregate(node, expr, loc);
1676
1677 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001678 if (acceptTokenClass(EHTokComma)) {
1679 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1680 return true;
John Kessenich07354242016-07-01 19:58:06 -06001681 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001682 }
John Kessenich07354242016-07-01 19:58:06 -06001683
1684 // RIGHT_BRACE
1685 if (acceptTokenClass(EHTokRightBrace))
1686 return true;
1687
1688 expected(", or }");
1689 return false;
1690 } while (true);
1691}
1692
John Kessenich34fb0362016-05-03 23:17:20 -06001693// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001694// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001695//
1696// a op (b op (c op d))
1697//
1698// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001699// : initializer
1700// | conditional_expression
1701// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001702//
1703bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1704{
John Kessenich07354242016-07-01 19:58:06 -06001705 // initializer
1706 if (peekTokenClass(EHTokLeftBrace)) {
1707 if (acceptInitializer(node))
1708 return true;
1709
1710 expected("initializer");
1711 return false;
1712 }
1713
John Kessenich00957f82016-07-27 10:39:57 -06001714 // conditional_expression
1715 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001716 return false;
1717
John Kessenich07354242016-07-01 19:58:06 -06001718 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001719 TOperator assignOp = HlslOpMap::assignment(peek());
1720 if (assignOp == EOpNull)
1721 return true;
1722
John Kessenich00957f82016-07-27 10:39:57 -06001723 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001724 TSourceLoc loc = token.loc;
1725 advanceToken();
1726
John Kessenich00957f82016-07-27 10:39:57 -06001727 // conditional_expression assign_op conditional_expression ...
1728 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001729 // gets the right-to-left associativity.
1730 TIntermTyped* rightNode = nullptr;
1731 if (! acceptAssignmentExpression(rightNode)) {
1732 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001733 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001734 }
1735
John Kessenichd21baed2016-09-16 03:05:12 -06001736 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
John Kessenichfea226b2016-07-28 17:53:56 -06001737 if (node == nullptr) {
1738 parseContext.error(loc, "could not create assignment", "", "");
1739 return false;
1740 }
John Kessenich34fb0362016-05-03 23:17:20 -06001741
1742 if (! peekTokenClass(EHTokComma))
1743 return true;
1744
1745 return true;
1746}
1747
John Kessenich00957f82016-07-27 10:39:57 -06001748// Accept a conditional expression, which associates right-to-left,
1749// accomplished by the "true" expression calling down to lower
1750// precedence levels than this level.
1751//
1752// conditional_expression
1753// : binary_expression
1754// | binary_expression QUESTION expression COLON assignment_expression
1755//
1756bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1757{
1758 // binary_expression
1759 if (! acceptBinaryExpression(node, PlLogicalOr))
1760 return false;
1761
1762 if (! acceptTokenClass(EHTokQuestion))
1763 return true;
1764
1765 TIntermTyped* trueNode = nullptr;
1766 if (! acceptExpression(trueNode)) {
1767 expected("expression after ?");
1768 return false;
1769 }
1770 TSourceLoc loc = token.loc;
1771
1772 if (! acceptTokenClass(EHTokColon)) {
1773 expected(":");
1774 return false;
1775 }
1776
1777 TIntermTyped* falseNode = nullptr;
1778 if (! acceptAssignmentExpression(falseNode)) {
1779 expected("expression after :");
1780 return false;
1781 }
1782
1783 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1784
1785 return true;
1786}
1787
John Kessenich34fb0362016-05-03 23:17:20 -06001788// Accept a binary expression, for binary operations that
1789// associate left-to-right. This is, it is implicit, for example
1790//
1791// ((a op b) op c) op d
1792//
1793// binary_expression
1794// : expression op expression op expression ...
1795//
1796// where 'expression' is the next higher level in precedence.
1797//
1798bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1799{
1800 if (precedenceLevel > PlMul)
1801 return acceptUnaryExpression(node);
1802
1803 // assignment_expression
1804 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1805 return false;
1806
John Kessenich34fb0362016-05-03 23:17:20 -06001807 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001808 TOperator op = HlslOpMap::binary(peek());
1809 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1810 if (tokenLevel < precedenceLevel)
1811 return true;
1812
John Kessenich34fb0362016-05-03 23:17:20 -06001813 // ... op
1814 TSourceLoc loc = token.loc;
1815 advanceToken();
1816
1817 // ... expression
1818 TIntermTyped* rightNode = nullptr;
1819 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1820 expected("expression");
1821 return false;
1822 }
1823
1824 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001825 if (node == nullptr) {
1826 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1827 return false;
1828 }
John Kessenich34fb0362016-05-03 23:17:20 -06001829 } while (true);
1830}
1831
1832// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001833// : (type) unary_expression
1834// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001835// | - unary_expression
1836// | ! unary_expression
1837// | ~ unary_expression
1838// | ++ unary_expression
1839// | -- unary_expression
1840// | postfix_expression
1841//
1842bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1843{
John Kessenich1cc1a282016-06-03 16:55:49 -06001844 // (type) unary_expression
1845 // Have to look two steps ahead, because this could be, e.g., a
1846 // postfix_expression instead, since that also starts with at "(".
1847 if (acceptTokenClass(EHTokLeftParen)) {
1848 TType castType;
1849 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001850 if (acceptTokenClass(EHTokRightParen)) {
1851 // We've matched "(type)" now, get the expression to cast
1852 TSourceLoc loc = token.loc;
1853 if (! acceptUnaryExpression(node))
1854 return false;
1855
1856 // Hook it up like a constructor
1857 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1858 if (constructorFunction == nullptr) {
1859 expected("type that can be constructed");
1860 return false;
1861 }
1862 TIntermTyped* arguments = nullptr;
1863 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1864 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1865
1866 return true;
1867 } else {
1868 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
1869 // the '(int' part. We must back up twice.
1870 recedeToken();
1871 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06001872 }
John Kessenich1cc1a282016-06-03 16:55:49 -06001873 } else {
1874 // This isn't a type cast, but it still started "(", so if it is a
1875 // unary expression, it can only be a postfix_expression, so try that.
1876 // Back it up first.
1877 recedeToken();
1878 return acceptPostfixExpression(node);
1879 }
1880 }
1881
1882 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001883 TOperator unaryOp = HlslOpMap::preUnary(peek());
1884
John Kessenich1cc1a282016-06-03 16:55:49 -06001885 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001886 if (unaryOp == EOpNull)
1887 return acceptPostfixExpression(node);
1888
1889 // op unary_expression
1890 TSourceLoc loc = token.loc;
1891 advanceToken();
1892 if (! acceptUnaryExpression(node))
1893 return false;
1894
1895 // + is a no-op
1896 if (unaryOp == EOpAdd)
1897 return true;
1898
1899 node = intermediate.addUnaryMath(unaryOp, node, loc);
1900
1901 return node != nullptr;
1902}
1903
1904// postfix_expression
1905// : LEFT_PAREN expression RIGHT_PAREN
1906// | literal
1907// | constructor
1908// | identifier
1909// | function_call
1910// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1911// | postfix_expression DOT IDENTIFIER
1912// | postfix_expression INC_OP
1913// | postfix_expression DEC_OP
1914//
1915bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1916{
1917 // Not implemented as self-recursive:
1918 // The logical "right recursion" is done with an loop at the end
1919
1920 // idToken will pick up either a variable or a function name in a function call
1921 HlslToken idToken;
1922
John Kessenich21472ae2016-06-04 11:46:33 -06001923 // Find something before the postfix operations, as they can't operate
1924 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001925 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001926 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001927 if (! acceptExpression(node)) {
1928 expected("expression");
1929 return false;
1930 }
1931 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001932 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001933 return false;
1934 }
John Kessenich34fb0362016-05-03 23:17:20 -06001935 } else if (acceptLiteral(node)) {
1936 // literal (nothing else to do yet), go on to the
1937 } else if (acceptConstructor(node)) {
1938 // constructor (nothing else to do yet)
1939 } else if (acceptIdentifier(idToken)) {
1940 // identifier or function_call name
1941 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001942 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001943 } else if (acceptFunctionCall(idToken, node)) {
1944 // function_call (nothing else to do yet)
1945 } else {
1946 expected("function call arguments");
1947 return false;
1948 }
John Kessenich21472ae2016-06-04 11:46:33 -06001949 } else {
1950 // nothing found, can't post operate
1951 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001952 }
1953
John Kessenich21472ae2016-06-04 11:46:33 -06001954 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001955 do {
1956 TSourceLoc loc = token.loc;
1957 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001958
John Kessenich34fb0362016-05-03 23:17:20 -06001959 // Consume only a valid post-unary operator, otherwise we are done.
1960 switch (postOp) {
1961 case EOpIndexDirectStruct:
1962 case EOpIndexIndirect:
1963 case EOpPostIncrement:
1964 case EOpPostDecrement:
1965 advanceToken();
1966 break;
1967 default:
1968 return true;
1969 }
John Kessenich87142c72016-03-12 20:24:24 -07001970
John Kessenich34fb0362016-05-03 23:17:20 -06001971 // We have a valid post-unary operator, process it.
1972 switch (postOp) {
1973 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001974 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001975 // DOT IDENTIFIER
1976 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001977 HlslToken field;
1978 if (! acceptIdentifier(field)) {
1979 expected("swizzle or member");
1980 return false;
1981 }
LoopDawg4886f692016-06-29 10:58:58 -06001982
1983 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001984 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001985
1986 // In the event of a method node, we look for an open paren and accept the function call.
1987 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1988 if (! acceptFunctionCall(field, node, base)) {
1989 expected("function parameters");
1990 return false;
1991 }
1992 }
1993
John Kessenich34fb0362016-05-03 23:17:20 -06001994 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001995 }
John Kessenich34fb0362016-05-03 23:17:20 -06001996 case EOpIndexIndirect:
1997 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001998 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001999 TIntermTyped* indexNode = nullptr;
2000 if (! acceptExpression(indexNode) ||
2001 ! peekTokenClass(EHTokRightBracket)) {
2002 expected("expression followed by ']'");
2003 return false;
2004 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002005 advanceToken();
2006 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2007 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002008 }
2009 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002010 // INC_OP
2011 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002012 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002013 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002014 node = intermediate.addUnaryMath(postOp, node, loc);
2015 break;
2016 default:
2017 assert(0);
2018 break;
2019 }
2020 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002021}
2022
John Kessenichd016be12016-03-13 11:24:20 -06002023// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002024// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002025//
2026bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2027{
2028 // type
2029 TType type;
2030 if (acceptType(type)) {
2031 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2032 if (constructorFunction == nullptr)
2033 return false;
2034
2035 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002036 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002037 if (! acceptArguments(constructorFunction, arguments)) {
2038 expected("constructor arguments");
2039 return false;
2040 }
2041
2042 // hook it up
2043 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2044
2045 return true;
2046 }
2047
2048 return false;
2049}
2050
John Kessenich34fb0362016-05-03 23:17:20 -06002051// The function_call identifier was already recognized, and passed in as idToken.
2052//
2053// function_call
2054// : [idToken] arguments
2055//
LoopDawg4886f692016-06-29 10:58:58 -06002056bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002057{
John Kessenich4678ca92016-05-13 09:33:42 -06002058 // arguments
2059 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2060 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002061
2062 // methods have an implicit first argument of the calling object.
2063 if (base != nullptr)
2064 parseContext.handleFunctionArgument(function, arguments, base);
2065
John Kessenich4678ca92016-05-13 09:33:42 -06002066 if (! acceptArguments(function, arguments))
2067 return false;
2068
2069 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2070
2071 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002072}
2073
John Kessenich87142c72016-03-12 20:24:24 -07002074// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002075// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002076//
John Kessenichd016be12016-03-13 11:24:20 -06002077// The arguments are pushed onto the 'function' argument list and
2078// onto the 'arguments' aggregate.
2079//
John Kessenich4678ca92016-05-13 09:33:42 -06002080bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002081{
John Kessenich078d7f22016-03-14 10:02:11 -06002082 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002083 if (! acceptTokenClass(EHTokLeftParen))
2084 return false;
2085
2086 do {
John Kessenichd016be12016-03-13 11:24:20 -06002087 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002088 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002089 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002090 break;
John Kessenichd016be12016-03-13 11:24:20 -06002091
2092 // hook it up
2093 parseContext.handleFunctionArgument(function, arguments, arg);
2094
John Kessenich078d7f22016-03-14 10:02:11 -06002095 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002096 if (! acceptTokenClass(EHTokComma))
2097 break;
2098 } while (true);
2099
John Kessenich078d7f22016-03-14 10:02:11 -06002100 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002101 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002102 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002103 return false;
2104 }
2105
2106 return true;
2107}
2108
2109bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2110{
2111 switch (token.tokenClass) {
2112 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002113 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002114 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002115 case EHTokUintConstant:
2116 node = intermediate.addConstantUnion(token.u, token.loc, true);
2117 break;
John Kessenich87142c72016-03-12 20:24:24 -07002118 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002119 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002120 break;
2121 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002122 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002123 break;
2124 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002125 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002126 break;
John Kessenich86f71382016-09-19 20:23:18 -06002127 case EHTokStringConstant:
2128 node = nullptr;
2129 break;
John Kessenich87142c72016-03-12 20:24:24 -07002130
2131 default:
2132 return false;
2133 }
2134
2135 advanceToken();
2136
2137 return true;
2138}
2139
John Kessenich5f934b02016-03-13 17:58:25 -06002140// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002141// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002142//
John Kessenich21472ae2016-06-04 11:46:33 -06002143bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002144{
John Kessenich21472ae2016-06-04 11:46:33 -06002145 TIntermAggregate* compoundStatement = nullptr;
2146
John Kessenich34fb0362016-05-03 23:17:20 -06002147 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002148 if (! acceptTokenClass(EHTokLeftBrace))
2149 return false;
2150
2151 // statement statement ...
2152 TIntermNode* statement = nullptr;
2153 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002154 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2155 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2156 branch->getFlowOp() == EOpDefault)) {
2157 // hook up individual subsequences within a switch statement
2158 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2159 compoundStatement = nullptr;
2160 } else {
2161 // hook it up to the growing compound statement
2162 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2163 }
John Kessenich5f934b02016-03-13 17:58:25 -06002164 }
John Kessenich34fb0362016-05-03 23:17:20 -06002165 if (compoundStatement)
2166 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002167
John Kessenich21472ae2016-06-04 11:46:33 -06002168 retStatement = compoundStatement;
2169
John Kessenich34fb0362016-05-03 23:17:20 -06002170 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002171 return acceptTokenClass(EHTokRightBrace);
2172}
2173
John Kessenich0d2b6de2016-06-05 11:23:11 -06002174bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2175{
2176 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002177 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002178 parseContext.popScope();
2179
2180 return result;
2181}
2182
John Kessenich077e0522016-06-09 02:02:17 -06002183bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002184{
John Kessenich077e0522016-06-09 02:02:17 -06002185 parseContext.pushScope();
2186 bool result = acceptCompoundStatement(statement);
2187 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002188
2189 return result;
2190}
2191
John Kessenich5f934b02016-03-13 17:58:25 -06002192// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002193// : attributes attributed_statement
2194//
2195// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002196// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002197// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002198// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002199// | declaration_statement
2200// | selection_statement
2201// | switch_statement
2202// | case_label
2203// | iteration_statement
2204// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002205//
2206bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2207{
John Kessenich21472ae2016-06-04 11:46:33 -06002208 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002209
John Kessenich21472ae2016-06-04 11:46:33 -06002210 // attributes
2211 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002212
John Kessenich21472ae2016-06-04 11:46:33 -06002213 // attributed_statement
2214 switch (peek()) {
2215 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002216 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002217
John Kessenich21472ae2016-06-04 11:46:33 -06002218 case EHTokIf:
2219 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002220
John Kessenich21472ae2016-06-04 11:46:33 -06002221 case EHTokSwitch:
2222 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002223
John Kessenich21472ae2016-06-04 11:46:33 -06002224 case EHTokFor:
2225 case EHTokDo:
2226 case EHTokWhile:
2227 return acceptIterationStatement(statement);
2228
2229 case EHTokContinue:
2230 case EHTokBreak:
2231 case EHTokDiscard:
2232 case EHTokReturn:
2233 return acceptJumpStatement(statement);
2234
2235 case EHTokCase:
2236 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002237 case EHTokDefault:
2238 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002239
2240 case EHTokSemicolon:
2241 return acceptTokenClass(EHTokSemicolon);
2242
2243 case EHTokRightBrace:
2244 // Performance: not strictly necessary, but stops a bunch of hunting early,
2245 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002246 return false;
2247
John Kessenich21472ae2016-06-04 11:46:33 -06002248 default:
2249 {
2250 // declaration
2251 if (acceptDeclaration(statement))
2252 return true;
2253
2254 // expression
2255 TIntermTyped* node;
2256 if (acceptExpression(node))
2257 statement = node;
2258 else
2259 return false;
2260
2261 // SEMICOLON (following an expression)
2262 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002263 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002264 return false;
2265 }
2266 }
2267 }
2268
John Kessenich5f934b02016-03-13 17:58:25 -06002269 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002270}
2271
John Kessenich21472ae2016-06-04 11:46:33 -06002272// attributes
2273// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2274//
2275// attribute:
2276// : UNROLL
2277// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2278// | FASTOPT
2279// | ALLOW_UAV_CONDITION
2280// | BRANCH
2281// | FLATTEN
2282// | FORCECASE
2283// | CALL
2284//
2285void HlslGrammar::acceptAttributes()
2286{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002287 // For now, accept the [ XXX(X) ] syntax, but drop.
2288 // TODO: subset to correct set? Pass on?
2289 do {
2290 // LEFT_BRACKET?
2291 if (! acceptTokenClass(EHTokLeftBracket))
2292 return;
2293
2294 // attribute
2295 if (peekTokenClass(EHTokIdentifier)) {
2296 // 'token.string' is the attribute
2297 advanceToken();
2298 } else if (! peekTokenClass(EHTokRightBracket)) {
2299 expected("identifier");
2300 advanceToken();
2301 }
2302
2303 // (x)
2304 if (acceptTokenClass(EHTokLeftParen)) {
2305 TIntermTyped* node;
2306 if (! acceptLiteral(node))
2307 expected("literal");
2308 // 'node' has the literal in it
2309 if (! acceptTokenClass(EHTokRightParen))
2310 expected(")");
2311 }
2312
2313 // RIGHT_BRACKET
2314 if (acceptTokenClass(EHTokRightBracket))
2315 continue;
2316
2317 expected("]");
2318 return;
2319
2320 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002321}
2322
John Kessenich0d2b6de2016-06-05 11:23:11 -06002323// selection_statement
2324// : IF LEFT_PAREN expression RIGHT_PAREN statement
2325// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2326//
John Kessenich21472ae2016-06-04 11:46:33 -06002327bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2328{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002329 TSourceLoc loc = token.loc;
2330
2331 // IF
2332 if (! acceptTokenClass(EHTokIf))
2333 return false;
2334
2335 // so that something declared in the condition is scoped to the lifetimes
2336 // of the then-else statements
2337 parseContext.pushScope();
2338
2339 // LEFT_PAREN expression RIGHT_PAREN
2340 TIntermTyped* condition;
2341 if (! acceptParenExpression(condition))
2342 return false;
2343
2344 // create the child statements
2345 TIntermNodePair thenElse = { nullptr, nullptr };
2346
2347 // then statement
2348 if (! acceptScopedStatement(thenElse.node1)) {
2349 expected("then statement");
2350 return false;
2351 }
2352
2353 // ELSE
2354 if (acceptTokenClass(EHTokElse)) {
2355 // else statement
2356 if (! acceptScopedStatement(thenElse.node2)) {
2357 expected("else statement");
2358 return false;
2359 }
2360 }
2361
2362 // Put the pieces together
2363 statement = intermediate.addSelection(condition, thenElse, loc);
2364 parseContext.popScope();
2365
2366 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002367}
2368
John Kessenichd02dc5d2016-07-01 00:04:11 -06002369// switch_statement
2370// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2371//
John Kessenich21472ae2016-06-04 11:46:33 -06002372bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2373{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002374 // SWITCH
2375 TSourceLoc loc = token.loc;
2376 if (! acceptTokenClass(EHTokSwitch))
2377 return false;
2378
2379 // LEFT_PAREN expression RIGHT_PAREN
2380 parseContext.pushScope();
2381 TIntermTyped* switchExpression;
2382 if (! acceptParenExpression(switchExpression)) {
2383 parseContext.popScope();
2384 return false;
2385 }
2386
2387 // compound_statement
2388 parseContext.pushSwitchSequence(new TIntermSequence);
2389 bool statementOkay = acceptCompoundStatement(statement);
2390 if (statementOkay)
2391 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2392
2393 parseContext.popSwitchSequence();
2394 parseContext.popScope();
2395
2396 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002397}
2398
John Kessenich119f8f62016-06-05 15:44:07 -06002399// iteration_statement
2400// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2401// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2402// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2403//
2404// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002405bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2406{
John Kessenich119f8f62016-06-05 15:44:07 -06002407 TSourceLoc loc = token.loc;
2408 TIntermTyped* condition = nullptr;
2409
2410 EHlslTokenClass loop = peek();
2411 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2412
2413 // WHILE or DO or FOR
2414 advanceToken();
2415
2416 switch (loop) {
2417 case EHTokWhile:
2418 // so that something declared in the condition is scoped to the lifetime
2419 // of the while sub-statement
2420 parseContext.pushScope();
2421 parseContext.nestLooping();
2422
2423 // LEFT_PAREN condition RIGHT_PAREN
2424 if (! acceptParenExpression(condition))
2425 return false;
2426
2427 // statement
2428 if (! acceptScopedStatement(statement)) {
2429 expected("while sub-statement");
2430 return false;
2431 }
2432
2433 parseContext.unnestLooping();
2434 parseContext.popScope();
2435
2436 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2437
2438 return true;
2439
2440 case EHTokDo:
2441 parseContext.nestLooping();
2442
2443 if (! acceptTokenClass(EHTokLeftBrace))
2444 expected("{");
2445
2446 // statement
2447 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2448 expected("do sub-statement");
2449 return false;
2450 }
2451
2452 if (! acceptTokenClass(EHTokRightBrace))
2453 expected("}");
2454
2455 // WHILE
2456 if (! acceptTokenClass(EHTokWhile)) {
2457 expected("while");
2458 return false;
2459 }
2460
2461 // LEFT_PAREN condition RIGHT_PAREN
2462 TIntermTyped* condition;
2463 if (! acceptParenExpression(condition))
2464 return false;
2465
2466 if (! acceptTokenClass(EHTokSemicolon))
2467 expected(";");
2468
2469 parseContext.unnestLooping();
2470
2471 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2472
2473 return true;
2474
2475 case EHTokFor:
2476 {
2477 // LEFT_PAREN
2478 if (! acceptTokenClass(EHTokLeftParen))
2479 expected("(");
2480
2481 // so that something declared in the condition is scoped to the lifetime
2482 // of the for sub-statement
2483 parseContext.pushScope();
2484
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002485 // initializer
2486 TIntermNode* initNode = nullptr;
2487 if (! acceptControlDeclaration(initNode)) {
2488 TIntermTyped* initExpr = nullptr;
2489 acceptExpression(initExpr);
2490 initNode = initExpr;
2491 }
2492 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002493 if (! acceptTokenClass(EHTokSemicolon))
2494 expected(";");
2495
2496 parseContext.nestLooping();
2497
2498 // condition SEMI_COLON
2499 acceptExpression(condition);
2500 if (! acceptTokenClass(EHTokSemicolon))
2501 expected(";");
2502
2503 // iterator SEMI_COLON
2504 TIntermTyped* iterator = nullptr;
2505 acceptExpression(iterator);
2506 if (! acceptTokenClass(EHTokRightParen))
2507 expected(")");
2508
2509 // statement
2510 if (! acceptScopedStatement(statement)) {
2511 expected("for sub-statement");
2512 return false;
2513 }
2514
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002515 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002516
2517 parseContext.popScope();
2518 parseContext.unnestLooping();
2519
2520 return true;
2521 }
2522
2523 default:
2524 return false;
2525 }
John Kessenich21472ae2016-06-04 11:46:33 -06002526}
2527
2528// jump_statement
2529// : CONTINUE SEMICOLON
2530// | BREAK SEMICOLON
2531// | DISCARD SEMICOLON
2532// | RETURN SEMICOLON
2533// | RETURN expression SEMICOLON
2534//
2535bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2536{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002537 EHlslTokenClass jump = peek();
2538 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002539 case EHTokContinue:
2540 case EHTokBreak:
2541 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002542 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002543 advanceToken();
2544 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002545 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002546 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002547 return false;
2548 }
John Kessenich21472ae2016-06-04 11:46:33 -06002549
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002550 switch (jump) {
2551 case EHTokContinue:
2552 statement = intermediate.addBranch(EOpContinue, token.loc);
2553 break;
2554 case EHTokBreak:
2555 statement = intermediate.addBranch(EOpBreak, token.loc);
2556 break;
2557 case EHTokDiscard:
2558 statement = intermediate.addBranch(EOpKill, token.loc);
2559 break;
2560
2561 case EHTokReturn:
2562 {
2563 // expression
2564 TIntermTyped* node;
2565 if (acceptExpression(node)) {
2566 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002567 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002568 } else
2569 statement = intermediate.addBranch(EOpReturn, token.loc);
2570 break;
2571 }
2572
2573 default:
2574 assert(0);
2575 return false;
2576 }
2577
2578 // SEMICOLON
2579 if (! acceptTokenClass(EHTokSemicolon))
2580 expected(";");
2581
2582 return true;
2583}
John Kessenich21472ae2016-06-04 11:46:33 -06002584
John Kessenichd02dc5d2016-07-01 00:04:11 -06002585// case_label
2586// : CASE expression COLON
2587//
John Kessenich21472ae2016-06-04 11:46:33 -06002588bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2589{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002590 TSourceLoc loc = token.loc;
2591 if (! acceptTokenClass(EHTokCase))
2592 return false;
2593
2594 TIntermTyped* expression;
2595 if (! acceptExpression(expression)) {
2596 expected("case expression");
2597 return false;
2598 }
2599
2600 if (! acceptTokenClass(EHTokColon)) {
2601 expected(":");
2602 return false;
2603 }
2604
2605 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2606
2607 return true;
2608}
2609
2610// default_label
2611// : DEFAULT COLON
2612//
2613bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2614{
2615 TSourceLoc loc = token.loc;
2616 if (! acceptTokenClass(EHTokDefault))
2617 return false;
2618
2619 if (! acceptTokenClass(EHTokColon)) {
2620 expected(":");
2621 return false;
2622 }
2623
2624 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2625
2626 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002627}
2628
John Kessenich19b92ff2016-06-19 11:50:34 -06002629// array_specifier
2630// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
steve-lunarg265c0612016-09-27 10:57:35 -06002631// : LEFT_BRACKET RGHT_BRACKET post_decls // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002632//
2633void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2634{
2635 arraySizes = nullptr;
2636
2637 if (! acceptTokenClass(EHTokLeftBracket))
2638 return;
2639
2640 TSourceLoc loc = token.loc;
steve-lunarg265c0612016-09-27 10:57:35 -06002641 TIntermTyped* sizeExpr = nullptr;
2642
2643 // Array sizing expression is optional. If ommitted, array is implicitly sized.
2644 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
John Kessenich19b92ff2016-06-19 11:50:34 -06002645
2646 if (! acceptTokenClass(EHTokRightBracket)) {
2647 expected("]");
2648 return;
2649 }
2650
John Kessenich19b92ff2016-06-19 11:50:34 -06002651 arraySizes = new TArraySizes;
steve-lunarg265c0612016-09-27 10:57:35 -06002652
2653 if (hasArraySize) {
2654 TArraySize arraySize;
2655 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2656 arraySizes->addInnerSize(arraySize);
2657 } else {
2658 arraySizes->addInnerSize(); // implicitly sized
2659 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002660}
2661
John Kessenich630dd7d2016-06-12 23:52:12 -06002662// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002663// : COLON semantic // optional
2664// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2665// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002666// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002667// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002668//
John Kessenich7735b942016-09-05 12:40:06 -06002669void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002670{
John Kessenich630dd7d2016-06-12 23:52:12 -06002671 do {
2672 // COLON
2673 if (acceptTokenClass(EHTokColon)) {
2674 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002675 if (peekTokenClass(EHTokLayout))
2676 acceptLayoutQualifierList(qualifier);
2677 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002678 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002679 if (! acceptTokenClass(EHTokLeftParen)) {
2680 expected("(");
2681 return;
2682 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002683 HlslToken locationToken;
2684 if (! acceptIdentifier(locationToken)) {
2685 expected("c[subcomponent][.component]");
2686 return;
2687 }
2688 HlslToken componentToken;
2689 if (acceptTokenClass(EHTokDot)) {
2690 if (! acceptIdentifier(componentToken)) {
2691 expected("component");
2692 return;
2693 }
2694 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002695 if (! acceptTokenClass(EHTokRightParen)) {
2696 expected(")");
2697 break;
2698 }
John Kessenich7735b942016-09-05 12:40:06 -06002699 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002700 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002701 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002702 return;
2703 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002704 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2705 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002706 if (! acceptTokenClass(EHTokLeftParen)) {
2707 expected("(");
2708 return;
2709 }
John Kessenichb38f0712016-07-30 10:29:54 -06002710 HlslToken registerDesc; // for Type#
2711 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002712 if (! acceptIdentifier(registerDesc)) {
2713 expected("register number description");
2714 return;
2715 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002716 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2717 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002718 // Then we didn't really see the registerDesc yet, it was
2719 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002720 profile = registerDesc;
2721 if (! acceptIdentifier(registerDesc)) {
2722 expected("register number description");
2723 return;
2724 }
2725 }
John Kessenichb38f0712016-07-30 10:29:54 -06002726 int subComponent = 0;
2727 if (acceptTokenClass(EHTokLeftBracket)) {
2728 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2729 if (! peekTokenClass(EHTokIntConstant)) {
2730 expected("literal integer");
2731 return;
2732 }
2733 subComponent = token.i;
2734 advanceToken();
2735 if (! acceptTokenClass(EHTokRightBracket)) {
2736 expected("]");
2737 break;
2738 }
2739 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002740 // (COMMA SPACEN)opt
2741 HlslToken spaceDesc;
2742 if (acceptTokenClass(EHTokComma)) {
2743 if (! acceptIdentifier(spaceDesc)) {
2744 expected ("space identifier");
2745 return;
2746 }
2747 }
2748 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002749 if (! acceptTokenClass(EHTokRightParen)) {
2750 expected(")");
2751 break;
2752 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002753 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002754 } else {
2755 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002756 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002757 }
John Kessenicha1e2d492016-09-20 13:22:58 -06002758 } else if (peekTokenClass(EHTokLeftAngle))
2759 acceptAnnotations(qualifier);
2760 else
John Kessenich630dd7d2016-06-12 23:52:12 -06002761 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002762
John Kessenich630dd7d2016-06-12 23:52:12 -06002763 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002764}
2765
John Kesseniche01a9bc2016-03-12 20:11:22 -07002766} // end namespace glslang