blob: 85c2c6972b11fbc8947535502f190c53587c5fc6 [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 Kesseniche82061d2016-09-27 14:38:57 -0600290 if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) {
291 if (declaredType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600292 // Sampler/textures are uniform by default (if no explicit qualifier is present) in
293 // HLSL. This line silently converts samplers *explicitly* declared static to uniform,
294 // which is incorrect but harmless.
John Kesseniche82061d2016-09-27 14:38:57 -0600295 declaredType.getQualifier().storage = EvqUniform;
LoopDawg4886f692016-06-29 10:58:58 -0600296 } else {
John Kesseniche82061d2016-09-27 14:38:57 -0600297 declaredType.getQualifier().storage = EvqGlobal;
LoopDawg4886f692016-06-29 10:58:58 -0600298 }
299 }
John Kessenich87142c72016-03-12 20:24:24 -0700300
301 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600302 HlslToken idToken;
John Kessenichd5ed0b62016-07-04 17:32:45 -0600303 while (acceptIdentifier(idToken)) {
John Kessenich5f934b02016-03-13 17:58:25 -0600304 // function_parameters
John Kesseniche82061d2016-09-27 14:38:57 -0600305 TFunction& function = *new TFunction(idToken.string, declaredType);
John Kessenich9e079532016-09-02 20:05:19 -0600306 if (acceptFunctionParameters(function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600307 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600308 acceptPostDecls(function.getWritableType().getQualifier());
John Kessenich078d7f22016-03-14 10:02:11 -0600309
John Kessenichd5ed0b62016-07-04 17:32:45 -0600310 // compound_statement (function body definition) or just a prototype?
311 if (peekTokenClass(EHTokLeftBrace)) {
312 if (list)
313 parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
John Kessenich5e69ec62016-07-05 00:02:40 -0600314 if (typedefDecl)
315 parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600316 return acceptFunctionDefinition(function, node);
John Kessenich5e69ec62016-07-05 00:02:40 -0600317 } else {
318 if (typedefDecl)
319 parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
John Kessenich9e079532016-09-02 20:05:19 -0600320 parseContext.handleFunctionDeclarator(idToken.loc, function, true);
John Kessenich5e69ec62016-07-05 00:02:40 -0600321 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600322 } else {
John Kesseniche82061d2016-09-27 14:38:57 -0600323 // A variable declaration.
324 // We can handle multiple variables per type declaration, so
325 // the number of types can expand when arrayness is different.
326 TType variableType;
327 variableType.shallowCopy(declaredType);
John Kessenich5f934b02016-03-13 17:58:25 -0600328
John Kesseniche82061d2016-09-27 14:38:57 -0600329 // recognize array_specifier
John Kessenichd5ed0b62016-07-04 17:32:45 -0600330 TArraySizes* arraySizes = nullptr;
331 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600332
John Kesseniche82061d2016-09-27 14:38:57 -0600333 // Fix arrayness in the variableType
334 if (declaredType.isImplicitlySizedArray()) {
335 // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
336 // of different sizes, for this case sharing the shallow copy of arrayness
337 // with the parseType oversubscribes it, so get a deep copy of the arrayness.
338 variableType.newArraySizes(declaredType.getArraySizes());
339 }
340 if (arraySizes || variableType.isArray()) {
341 // In the most general case, arrayness is potentially coming both from the
342 // declared type and from the variable: "int[] a[];" or just one or the other.
343 // Merge it all to the variableType, so all arrayness is part of the variableType.
344 parseContext.arrayDimMerge(variableType, arraySizes);
345 }
346
LoopDawg4886f692016-06-29 10:58:58 -0600347 // samplers accept immediate sampler state
John Kesseniche82061d2016-09-27 14:38:57 -0600348 if (variableType.getBasicType() == EbtSampler) {
LoopDawg4886f692016-06-29 10:58:58 -0600349 if (! acceptSamplerState())
350 return false;
351 }
352
John Kessenichd5ed0b62016-07-04 17:32:45 -0600353 // post_decls
John Kesseniche82061d2016-09-27 14:38:57 -0600354 acceptPostDecls(variableType.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600355
356 // EQUAL assignment_expression
357 TIntermTyped* expressionNode = nullptr;
358 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600359 if (typedefDecl)
360 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600361 if (! acceptAssignmentExpression(expressionNode)) {
362 expected("initializer");
363 return false;
364 }
365 }
366
John Kessenich5e69ec62016-07-05 00:02:40 -0600367 if (typedefDecl)
John Kesseniche82061d2016-09-27 14:38:57 -0600368 parseContext.declareTypedef(idToken.loc, *idToken.string, variableType, arraySizes);
369 else if (variableType.getBasicType() == EbtBlock)
370 parseContext.declareBlock(idToken.loc, variableType, idToken.string);
John Kessenich5e69ec62016-07-05 00:02:40 -0600371 else {
372 // Declare the variable and add any initializer code to the AST.
373 // The top-level node is always made into an aggregate, as that's
374 // historically how the AST has been.
375 node = intermediate.growAggregate(node,
John Kesseniche82061d2016-09-27 14:38:57 -0600376 parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
377 expressionNode),
John Kessenich5e69ec62016-07-05 00:02:40 -0600378 idToken.loc);
379 }
John Kessenich5f934b02016-03-13 17:58:25 -0600380 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600381
382 if (acceptTokenClass(EHTokComma)) {
383 list = true;
384 continue;
385 }
386 };
387
388 // The top-level node is a sequence.
389 if (node != nullptr)
390 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700391
John Kessenich078d7f22016-03-14 10:02:11 -0600392 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600393 if (! acceptTokenClass(EHTokSemicolon)) {
394 expected(";");
395 return false;
396 }
397
John Kesseniche01a9bc2016-03-12 20:11:22 -0700398 return true;
399}
400
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600401// control_declaration
402// : fully_specified_type identifier EQUAL expression
403//
404bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
405{
406 node = nullptr;
407
408 // fully_specified_type
409 TType type;
410 if (! acceptFullySpecifiedType(type))
411 return false;
412
413 // identifier
414 HlslToken idToken;
415 if (! acceptIdentifier(idToken)) {
416 expected("identifier");
417 return false;
418 }
419
420 // EQUAL
421 TIntermTyped* expressionNode = nullptr;
422 if (! acceptTokenClass(EHTokAssign)) {
423 expected("=");
424 return false;
425 }
426
427 // expression
428 if (! acceptExpression(expressionNode)) {
429 expected("initializer");
430 return false;
431 }
432
John Kesseniche82061d2016-09-27 14:38:57 -0600433 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600434
435 return true;
436}
437
John Kessenich87142c72016-03-12 20:24:24 -0700438// fully_specified_type
439// : type_specifier
440// | type_qualifier type_specifier
441//
442bool HlslGrammar::acceptFullySpecifiedType(TType& type)
443{
444 // type_qualifier
445 TQualifier qualifier;
446 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600447 if (! acceptQualifier(qualifier))
448 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600449 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700450
451 // type_specifier
452 if (! acceptType(type))
453 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600454 if (type.getBasicType() == EbtBlock) {
455 // the type was a block, which set some parts of the qualifier
John Kessenich34e7ee72016-09-16 17:10:39 -0600456 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600457 // further, it can create an anonymous instance of the block
458 if (peekTokenClass(EHTokSemicolon))
459 parseContext.declareBlock(loc, type);
460 } else
461 type.getQualifier() = qualifier;
John Kessenich87142c72016-03-12 20:24:24 -0700462
463 return true;
464}
465
John Kessenich630dd7d2016-06-12 23:52:12 -0600466// type_qualifier
467// : qualifier qualifier ...
468//
469// Zero or more of these, so this can't return false.
470//
John Kessenichb9e39122016-08-17 10:22:08 -0600471bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700472{
John Kessenich630dd7d2016-06-12 23:52:12 -0600473 do {
474 switch (peek()) {
475 case EHTokStatic:
476 // normal glslang default
477 break;
478 case EHTokExtern:
479 // TODO: no meaning in glslang?
480 break;
481 case EHTokShared:
482 // TODO: hint
483 break;
484 case EHTokGroupShared:
485 qualifier.storage = EvqShared;
486 break;
487 case EHTokUniform:
488 qualifier.storage = EvqUniform;
489 break;
490 case EHTokConst:
491 qualifier.storage = EvqConst;
492 break;
493 case EHTokVolatile:
494 qualifier.volatil = true;
495 break;
496 case EHTokLinear:
John Kessenich630dd7d2016-06-12 23:52:12 -0600497 qualifier.smooth = true;
498 break;
499 case EHTokCentroid:
500 qualifier.centroid = true;
501 break;
502 case EHTokNointerpolation:
503 qualifier.flat = true;
504 break;
505 case EHTokNoperspective:
506 qualifier.nopersp = true;
507 break;
508 case EHTokSample:
509 qualifier.sample = true;
510 break;
511 case EHTokRowMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600512 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600513 break;
514 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600515 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600516 break;
517 case EHTokPrecise:
518 qualifier.noContraction = true;
519 break;
LoopDawg9249c702016-07-12 20:44:32 -0600520 case EHTokIn:
521 qualifier.storage = EvqIn;
522 break;
523 case EHTokOut:
524 qualifier.storage = EvqOut;
525 break;
526 case EHTokInOut:
527 qualifier.storage = EvqInOut;
528 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600529 case EHTokLayout:
530 if (! acceptLayoutQualifierList(qualifier))
531 return false;
532 continue;
John Kessenich630dd7d2016-06-12 23:52:12 -0600533 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600534 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600535 }
536 advanceToken();
537 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700538}
539
John Kessenichb9e39122016-08-17 10:22:08 -0600540// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600541// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600542//
543// layout_qualifier
544// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600545// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600546//
547// Zero or more of these, so this can't return false.
548//
549bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
550{
551 if (! acceptTokenClass(EHTokLayout))
552 return false;
553
554 // LEFT_PAREN
555 if (! acceptTokenClass(EHTokLeftParen))
556 return false;
557
558 do {
559 // identifier
560 HlslToken idToken;
561 if (! acceptIdentifier(idToken))
562 break;
563
564 // EQUAL expression
565 if (acceptTokenClass(EHTokAssign)) {
566 TIntermTyped* expr;
567 if (! acceptConditionalExpression(expr)) {
568 expected("expression");
569 return false;
570 }
571 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
572 } else
573 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
574
575 // COMMA
576 if (! acceptTokenClass(EHTokComma))
577 break;
578 } while (true);
579
580 // RIGHT_PAREN
581 if (! acceptTokenClass(EHTokRightParen)) {
582 expected(")");
583 return false;
584 }
585
586 return true;
587}
588
LoopDawg6daaa4f2016-06-23 19:13:48 -0600589// template_type
590// : FLOAT
591// | DOUBLE
592// | INT
593// | DWORD
594// | UINT
595// | BOOL
596//
597bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
598{
599 switch (peek()) {
600 case EHTokFloat:
601 basicType = EbtFloat;
602 break;
603 case EHTokDouble:
604 basicType = EbtDouble;
605 break;
606 case EHTokInt:
607 case EHTokDword:
608 basicType = EbtInt;
609 break;
610 case EHTokUint:
611 basicType = EbtUint;
612 break;
613 case EHTokBool:
614 basicType = EbtBool;
615 break;
616 default:
617 return false;
618 }
619
620 advanceToken();
621
622 return true;
623}
624
625// vector_template_type
626// : VECTOR
627// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
628//
629bool HlslGrammar::acceptVectorTemplateType(TType& type)
630{
631 if (! acceptTokenClass(EHTokVector))
632 return false;
633
634 if (! acceptTokenClass(EHTokLeftAngle)) {
635 // in HLSL, 'vector' alone means float4.
636 new(&type) TType(EbtFloat, EvqTemporary, 4);
637 return true;
638 }
639
640 TBasicType basicType;
641 if (! acceptTemplateType(basicType)) {
642 expected("scalar type");
643 return false;
644 }
645
646 // COMMA
647 if (! acceptTokenClass(EHTokComma)) {
648 expected(",");
649 return false;
650 }
651
652 // integer
653 if (! peekTokenClass(EHTokIntConstant)) {
654 expected("literal integer");
655 return false;
656 }
657
658 TIntermTyped* vecSize;
659 if (! acceptLiteral(vecSize))
660 return false;
661
662 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
663
664 new(&type) TType(basicType, EvqTemporary, vecSizeI);
665
666 if (vecSizeI == 1)
667 type.makeVector();
668
669 if (!acceptTokenClass(EHTokRightAngle)) {
670 expected("right angle bracket");
671 return false;
672 }
673
674 return true;
675}
676
677// matrix_template_type
678// : MATRIX
679// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
680//
681bool HlslGrammar::acceptMatrixTemplateType(TType& type)
682{
683 if (! acceptTokenClass(EHTokMatrix))
684 return false;
685
686 if (! acceptTokenClass(EHTokLeftAngle)) {
687 // in HLSL, 'matrix' alone means float4x4.
688 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
689 return true;
690 }
691
692 TBasicType basicType;
693 if (! acceptTemplateType(basicType)) {
694 expected("scalar type");
695 return false;
696 }
697
698 // COMMA
699 if (! acceptTokenClass(EHTokComma)) {
700 expected(",");
701 return false;
702 }
703
704 // integer rows
705 if (! peekTokenClass(EHTokIntConstant)) {
706 expected("literal integer");
707 return false;
708 }
709
710 TIntermTyped* rows;
711 if (! acceptLiteral(rows))
712 return false;
713
714 // COMMA
715 if (! acceptTokenClass(EHTokComma)) {
716 expected(",");
717 return false;
718 }
719
720 // integer cols
721 if (! peekTokenClass(EHTokIntConstant)) {
722 expected("literal integer");
723 return false;
724 }
725
726 TIntermTyped* cols;
727 if (! acceptLiteral(cols))
728 return false;
729
730 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600731 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
732 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600733
734 if (!acceptTokenClass(EHTokRightAngle)) {
735 expected("right angle bracket");
736 return false;
737 }
738
739 return true;
740}
741
John Kessenicha1e2d492016-09-20 13:22:58 -0600742// annotations
743// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600744//
John Kessenicha1e2d492016-09-20 13:22:58 -0600745bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600746{
John Kessenicha1e2d492016-09-20 13:22:58 -0600747 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600748 return false;
749
John Kessenicha1e2d492016-09-20 13:22:58 -0600750 // note that we are nesting a name space
751 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600752
753 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
754 do {
755 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
756 while (acceptTokenClass(EHTokSemicolon))
757 ;
758
759 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600760 break;
John Kessenich86f71382016-09-19 20:23:18 -0600761
762 // declaration
763 TIntermNode* node;
764 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600765 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600766 return false;
767 }
768 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600769
770 parseContext.unnestAnnotations();
771 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600772}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600773
LoopDawg4886f692016-06-29 10:58:58 -0600774// sampler_type
775// : SAMPLER
776// | SAMPLER1D
777// | SAMPLER2D
778// | SAMPLER3D
779// | SAMPLERCUBE
780// | SAMPLERSTATE
781// | SAMPLERCOMPARISONSTATE
782bool HlslGrammar::acceptSamplerType(TType& type)
783{
784 // read sampler type
785 const EHlslTokenClass samplerType = peek();
786
LoopDawga78b0292016-07-19 14:28:05 -0600787 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600788 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600789
LoopDawga78b0292016-07-19 14:28:05 -0600790 bool isShadow = false;
791
LoopDawg4886f692016-06-29 10:58:58 -0600792 switch (samplerType) {
793 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600794 case EHTokSampler1d: /*dim = Esd1D*/; break;
795 case EHTokSampler2d: /*dim = Esd2D*/; break;
796 case EHTokSampler3d: /*dim = Esd3D*/; break;
797 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600798 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600799 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600800 default:
801 return false; // not a sampler declaration
802 }
803
804 advanceToken(); // consume the sampler type keyword
805
806 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600807
808 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600809 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600810
811 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
812
813 return true;
814}
815
816// texture_type
817// | BUFFER
818// | TEXTURE1D
819// | TEXTURE1DARRAY
820// | TEXTURE2D
821// | TEXTURE2DARRAY
822// | TEXTURE3D
823// | TEXTURECUBE
824// | TEXTURECUBEARRAY
825// | TEXTURE2DMS
826// | TEXTURE2DMSARRAY
827bool HlslGrammar::acceptTextureType(TType& type)
828{
829 const EHlslTokenClass textureType = peek();
830
831 TSamplerDim dim = EsdNone;
832 bool array = false;
833 bool ms = false;
834
835 switch (textureType) {
836 case EHTokBuffer: dim = EsdBuffer; break;
837 case EHTokTexture1d: dim = Esd1D; break;
838 case EHTokTexture1darray: dim = Esd1D; array = true; break;
839 case EHTokTexture2d: dim = Esd2D; break;
840 case EHTokTexture2darray: dim = Esd2D; array = true; break;
841 case EHTokTexture3d: dim = Esd3D; break;
842 case EHTokTextureCube: dim = EsdCube; break;
843 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
844 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
845 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
846 default:
847 return false; // not a texture declaration
848 }
849
850 advanceToken(); // consume the texture object keyword
851
852 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
853
854 TIntermTyped* msCount = nullptr;
855
856 // texture type: required for multisample types!
857 if (acceptTokenClass(EHTokLeftAngle)) {
858 if (! acceptType(txType)) {
859 expected("scalar or vector type");
860 return false;
861 }
862
863 const TBasicType basicRetType = txType.getBasicType() ;
864
865 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
866 unimplemented("basic type in texture");
867 return false;
868 }
869
steve-lunargd53f7172016-07-27 15:46:48 -0600870 // Buffers can handle small mats if they fit in 4 components
871 if (dim == EsdBuffer && txType.isMatrix()) {
872 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
873 expected("components < 4 in matrix buffer type");
874 return false;
875 }
876
877 // TODO: except we don't handle it yet...
878 unimplemented("matrix type in buffer");
879 return false;
880 }
881
LoopDawg4886f692016-06-29 10:58:58 -0600882 if (!txType.isScalar() && !txType.isVector()) {
883 expected("scalar or vector type");
884 return false;
885 }
886
887 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
888 // TODO: handle vec2/3 types
889 expected("vector size not yet supported in texture type");
890 return false;
891 }
892
893 if (ms && acceptTokenClass(EHTokComma)) {
894 // read sample count for multisample types, if given
895 if (! peekTokenClass(EHTokIntConstant)) {
896 expected("multisample count");
897 return false;
898 }
899
900 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
901 return false;
902 }
903
904 if (! acceptTokenClass(EHTokRightAngle)) {
905 expected("right angle bracket");
906 return false;
907 }
908 } else if (ms) {
909 expected("texture type for multisample");
910 return false;
911 }
912
913 TArraySizes* arraySizes = nullptr;
914 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
915
916 TSampler sampler;
steve-lunargd53f7172016-07-27 15:46:48 -0600917
918 // Buffers are combined.
919 if (dim == EsdBuffer) {
920 sampler.set(txType.getBasicType(), dim, array);
921 } else {
922 // DX10 textures are separated. TODO: DX9.
923 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
924 }
LoopDawg4886f692016-06-29 10:58:58 -0600925
926 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
927
928 return true;
929}
930
931
John Kessenich87142c72016-03-12 20:24:24 -0700932// If token is for a type, update 'type' with the type information,
933// and return true and advance.
934// Otherwise, return false, and don't advance
935bool HlslGrammar::acceptType(TType& type)
936{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600937 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600938 case EHTokVector:
939 return acceptVectorTemplateType(type);
940 break;
941
942 case EHTokMatrix:
943 return acceptMatrixTemplateType(type);
944 break;
945
LoopDawg4886f692016-06-29 10:58:58 -0600946 case EHTokSampler: // fall through
947 case EHTokSampler1d: // ...
948 case EHTokSampler2d: // ...
949 case EHTokSampler3d: // ...
950 case EHTokSamplerCube: // ...
951 case EHTokSamplerState: // ...
952 case EHTokSamplerComparisonState: // ...
953 return acceptSamplerType(type);
954 break;
955
956 case EHTokBuffer: // fall through
957 case EHTokTexture1d: // ...
958 case EHTokTexture1darray: // ...
959 case EHTokTexture2d: // ...
960 case EHTokTexture2darray: // ...
961 case EHTokTexture3d: // ...
962 case EHTokTextureCube: // ...
963 case EHTokTextureCubearray: // ...
964 case EHTokTexture2DMS: // ...
965 case EHTokTexture2DMSarray: // ...
966 return acceptTextureType(type);
967 break;
968
John Kesseniche6e74942016-06-11 16:43:14 -0600969 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600970 case EHTokCBuffer:
971 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600972 return acceptStruct(type);
973 break;
974
975 case EHTokIdentifier:
976 // An identifier could be for a user-defined type.
977 // Note we cache the symbol table lookup, to save for a later rule
978 // when this is not a type.
979 token.symbol = parseContext.symbolTable.find(*token.string);
980 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
981 type.shallowCopy(token.symbol->getType());
982 advanceToken();
983 return true;
984 } else
985 return false;
986
John Kessenich71351de2016-06-08 12:50:56 -0600987 case EHTokVoid:
988 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700989 break;
John Kessenich71351de2016-06-08 12:50:56 -0600990
John Kessenicha1e2d492016-09-20 13:22:58 -0600991 case EHTokString:
992 new(&type) TType(EbtString);
993 break;
994
John Kessenich87142c72016-03-12 20:24:24 -0700995 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600996 new(&type) TType(EbtFloat);
997 break;
John Kessenich87142c72016-03-12 20:24:24 -0700998 case EHTokFloat1:
999 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -06001000 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001001 break;
John Kessenich87142c72016-03-12 20:24:24 -07001002 case EHTokFloat2:
1003 new(&type) TType(EbtFloat, EvqTemporary, 2);
1004 break;
1005 case EHTokFloat3:
1006 new(&type) TType(EbtFloat, EvqTemporary, 3);
1007 break;
1008 case EHTokFloat4:
1009 new(&type) TType(EbtFloat, EvqTemporary, 4);
1010 break;
1011
John Kessenich71351de2016-06-08 12:50:56 -06001012 case EHTokDouble:
1013 new(&type) TType(EbtDouble);
1014 break;
1015 case EHTokDouble1:
1016 new(&type) TType(EbtDouble);
1017 type.makeVector();
1018 break;
1019 case EHTokDouble2:
1020 new(&type) TType(EbtDouble, EvqTemporary, 2);
1021 break;
1022 case EHTokDouble3:
1023 new(&type) TType(EbtDouble, EvqTemporary, 3);
1024 break;
1025 case EHTokDouble4:
1026 new(&type) TType(EbtDouble, EvqTemporary, 4);
1027 break;
1028
1029 case EHTokInt:
1030 case EHTokDword:
1031 new(&type) TType(EbtInt);
1032 break;
1033 case EHTokInt1:
1034 new(&type) TType(EbtInt);
1035 type.makeVector();
1036 break;
John Kessenich87142c72016-03-12 20:24:24 -07001037 case EHTokInt2:
1038 new(&type) TType(EbtInt, EvqTemporary, 2);
1039 break;
1040 case EHTokInt3:
1041 new(&type) TType(EbtInt, EvqTemporary, 3);
1042 break;
1043 case EHTokInt4:
1044 new(&type) TType(EbtInt, EvqTemporary, 4);
1045 break;
1046
John Kessenich71351de2016-06-08 12:50:56 -06001047 case EHTokUint:
1048 new(&type) TType(EbtUint);
1049 break;
1050 case EHTokUint1:
1051 new(&type) TType(EbtUint);
1052 type.makeVector();
1053 break;
1054 case EHTokUint2:
1055 new(&type) TType(EbtUint, EvqTemporary, 2);
1056 break;
1057 case EHTokUint3:
1058 new(&type) TType(EbtUint, EvqTemporary, 3);
1059 break;
1060 case EHTokUint4:
1061 new(&type) TType(EbtUint, EvqTemporary, 4);
1062 break;
1063
LoopDawg6daaa4f2016-06-23 19:13:48 -06001064
John Kessenich71351de2016-06-08 12:50:56 -06001065 case EHTokBool:
1066 new(&type) TType(EbtBool);
1067 break;
1068 case EHTokBool1:
1069 new(&type) TType(EbtBool);
1070 type.makeVector();
1071 break;
John Kessenich87142c72016-03-12 20:24:24 -07001072 case EHTokBool2:
1073 new(&type) TType(EbtBool, EvqTemporary, 2);
1074 break;
1075 case EHTokBool3:
1076 new(&type) TType(EbtBool, EvqTemporary, 3);
1077 break;
1078 case EHTokBool4:
1079 new(&type) TType(EbtBool, EvqTemporary, 4);
1080 break;
1081
John Kessenich0133c122016-05-20 12:17:26 -06001082 case EHTokInt1x1:
1083 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1084 break;
1085 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001086 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001087 break;
1088 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001089 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001090 break;
1091 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001092 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001093 break;
1094 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001095 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001096 break;
1097 case EHTokInt2x2:
1098 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1099 break;
1100 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001101 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001102 break;
1103 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001104 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001105 break;
1106 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001107 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001108 break;
1109 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001110 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001111 break;
1112 case EHTokInt3x3:
1113 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1114 break;
1115 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001116 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001117 break;
1118 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001119 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001120 break;
1121 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001122 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001123 break;
1124 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001125 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001126 break;
1127 case EHTokInt4x4:
1128 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1129 break;
1130
John Kessenich71351de2016-06-08 12:50:56 -06001131 case EHTokUint1x1:
1132 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1133 break;
1134 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001135 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001136 break;
1137 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001138 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001139 break;
1140 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001141 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001142 break;
1143 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001144 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001145 break;
1146 case EHTokUint2x2:
1147 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1148 break;
1149 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001150 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001151 break;
1152 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001153 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001154 break;
1155 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001156 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001157 break;
1158 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001159 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001160 break;
1161 case EHTokUint3x3:
1162 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1163 break;
1164 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001165 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001166 break;
1167 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001168 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001169 break;
1170 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001171 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001172 break;
1173 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001174 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001175 break;
1176 case EHTokUint4x4:
1177 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1178 break;
1179
1180 case EHTokBool1x1:
1181 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1182 break;
1183 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001184 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001185 break;
1186 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001187 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001188 break;
1189 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001190 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001191 break;
1192 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001193 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001194 break;
1195 case EHTokBool2x2:
1196 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1197 break;
1198 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001199 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001200 break;
1201 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001202 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001203 break;
1204 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001205 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001206 break;
1207 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001208 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001209 break;
1210 case EHTokBool3x3:
1211 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1212 break;
1213 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001214 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001215 break;
1216 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001217 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001218 break;
1219 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001220 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001221 break;
1222 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001223 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001224 break;
1225 case EHTokBool4x4:
1226 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1227 break;
1228
John Kessenich0133c122016-05-20 12:17:26 -06001229 case EHTokFloat1x1:
1230 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1231 break;
1232 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001233 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001234 break;
1235 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001236 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001237 break;
1238 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001239 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001240 break;
1241 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001242 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001243 break;
John Kessenich87142c72016-03-12 20:24:24 -07001244 case EHTokFloat2x2:
1245 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1246 break;
1247 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001248 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001249 break;
1250 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001251 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001252 break;
John Kessenich0133c122016-05-20 12:17:26 -06001253 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001254 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001255 break;
John Kessenich87142c72016-03-12 20:24:24 -07001256 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001257 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001258 break;
1259 case EHTokFloat3x3:
1260 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1261 break;
1262 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001263 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001264 break;
John Kessenich0133c122016-05-20 12:17:26 -06001265 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001266 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001267 break;
John Kessenich87142c72016-03-12 20:24:24 -07001268 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001269 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001270 break;
1271 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001272 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001273 break;
1274 case EHTokFloat4x4:
1275 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1276 break;
1277
John Kessenich0133c122016-05-20 12:17:26 -06001278 case EHTokDouble1x1:
1279 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1280 break;
1281 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001282 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001283 break;
1284 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001285 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001286 break;
1287 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001288 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001289 break;
1290 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001291 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001292 break;
1293 case EHTokDouble2x2:
1294 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1295 break;
1296 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001297 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001298 break;
1299 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001300 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001301 break;
1302 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001303 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001304 break;
1305 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001306 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001307 break;
1308 case EHTokDouble3x3:
1309 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1310 break;
1311 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001312 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001313 break;
1314 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001315 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001316 break;
1317 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001318 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001319 break;
1320 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001321 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001322 break;
1323 case EHTokDouble4x4:
1324 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1325 break;
1326
John Kessenich87142c72016-03-12 20:24:24 -07001327 default:
1328 return false;
1329 }
1330
1331 advanceToken();
1332
1333 return true;
1334}
1335
John Kesseniche6e74942016-06-11 16:43:14 -06001336// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001337// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1338// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1339//
1340// struct_type
1341// : STRUCT
1342// | CBUFFER
1343// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001344//
1345bool HlslGrammar::acceptStruct(TType& type)
1346{
John Kessenichb804de62016-09-05 12:19:18 -06001347 // This storage qualifier will tell us whether it's an AST
1348 // block type or just a generic structure type.
1349 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001350
1351 // CBUFFER
1352 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001353 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001354 // TBUFFER
1355 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001356 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001357 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001358 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001359 return false;
1360
1361 // IDENTIFIER
1362 TString structName = "";
1363 if (peekTokenClass(EHTokIdentifier)) {
1364 structName = *token.string;
1365 advanceToken();
1366 }
1367
John Kessenich3d157c52016-07-25 16:05:33 -06001368 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001369 TQualifier postDeclQualifier;
1370 postDeclQualifier.clear();
1371 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001372
John Kesseniche6e74942016-06-11 16:43:14 -06001373 // LEFT_BRACE
1374 if (! acceptTokenClass(EHTokLeftBrace)) {
1375 expected("{");
1376 return false;
1377 }
1378
1379 // struct_declaration_list
1380 TTypeList* typeList;
1381 if (! acceptStructDeclarationList(typeList)) {
1382 expected("struct member declarations");
1383 return false;
1384 }
1385
1386 // RIGHT_BRACE
1387 if (! acceptTokenClass(EHTokRightBrace)) {
1388 expected("}");
1389 return false;
1390 }
1391
1392 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001393 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001394 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001395 else {
John Kessenich7735b942016-09-05 12:40:06 -06001396 postDeclQualifier.storage = storageQualifier;
1397 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001398 }
John Kesseniche6e74942016-06-11 16:43:14 -06001399
John Kessenich3d157c52016-07-25 16:05:33 -06001400 // If it was named, which means the type can be reused later, add
1401 // it to the symbol table. (Unless it's a block, in which
1402 // case the name is not a type.)
1403 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001404 TVariable* userTypeDef = new TVariable(&structName, type, true);
1405 if (! parseContext.symbolTable.insert(*userTypeDef))
1406 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1407 }
1408
1409 return true;
1410}
1411
1412// struct_declaration_list
1413// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1414//
1415// struct_declaration
1416// : fully_specified_type struct_declarator COMMA struct_declarator ...
1417//
1418// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001419// : IDENTIFIER post_decls
1420// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001421//
1422bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1423{
1424 typeList = new TTypeList();
1425
1426 do {
1427 // success on seeing the RIGHT_BRACE coming up
1428 if (peekTokenClass(EHTokRightBrace))
1429 return true;
1430
1431 // struct_declaration
1432
1433 // fully_specified_type
1434 TType memberType;
1435 if (! acceptFullySpecifiedType(memberType)) {
1436 expected("member type");
1437 return false;
1438 }
1439
1440 // struct_declarator COMMA struct_declarator ...
1441 do {
1442 // peek IDENTIFIER
1443 if (! peekTokenClass(EHTokIdentifier)) {
1444 expected("member name");
1445 return false;
1446 }
1447
1448 // add it to the list of members
1449 TTypeLoc member = { new TType(EbtVoid), token.loc };
1450 member.type->shallowCopy(memberType);
1451 member.type->setFieldName(*token.string);
1452 typeList->push_back(member);
1453
1454 // accept IDENTIFIER
1455 advanceToken();
1456
1457 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001458 TArraySizes* arraySizes = nullptr;
1459 acceptArraySpecifier(arraySizes);
1460 if (arraySizes)
1461 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001462
John Kessenich7735b942016-09-05 12:40:06 -06001463 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001464
John Kesseniche6e74942016-06-11 16:43:14 -06001465 // success on seeing the SEMICOLON coming up
1466 if (peekTokenClass(EHTokSemicolon))
1467 break;
1468
1469 // COMMA
1470 if (! acceptTokenClass(EHTokComma)) {
1471 expected(",");
1472 return false;
1473 }
1474
1475 } while (true);
1476
1477 // SEMI_COLON
1478 if (! acceptTokenClass(EHTokSemicolon)) {
1479 expected(";");
1480 return false;
1481 }
1482
1483 } while (true);
1484}
1485
John Kessenich5f934b02016-03-13 17:58:25 -06001486// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001487// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001488// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001489//
1490bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1491{
John Kessenich078d7f22016-03-14 10:02:11 -06001492 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001493 if (! acceptTokenClass(EHTokLeftParen))
1494 return false;
1495
John Kessenich71351de2016-06-08 12:50:56 -06001496 // VOID RIGHT_PAREN
1497 if (! acceptTokenClass(EHTokVoid)) {
1498 do {
1499 // parameter_declaration
1500 if (! acceptParameterDeclaration(function))
1501 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001502
John Kessenich71351de2016-06-08 12:50:56 -06001503 // COMMA
1504 if (! acceptTokenClass(EHTokComma))
1505 break;
1506 } while (true);
1507 }
John Kessenich5f934b02016-03-13 17:58:25 -06001508
John Kessenich078d7f22016-03-14 10:02:11 -06001509 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001510 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001511 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001512 return false;
1513 }
1514
1515 return true;
1516}
1517
1518// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001519// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001520// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001521//
1522bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1523{
1524 // fully_specified_type
1525 TType* type = new TType;
1526 if (! acceptFullySpecifiedType(*type))
1527 return false;
1528
1529 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001530 HlslToken idToken;
1531 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001532
John Kessenich19b92ff2016-06-19 11:50:34 -06001533 // array_specifier
1534 TArraySizes* arraySizes = nullptr;
1535 acceptArraySpecifier(arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001536 if (arraySizes) {
1537 if (arraySizes->isImplicit()) {
1538 parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
1539 return false;
1540 }
1541
John Kessenich19b92ff2016-06-19 11:50:34 -06001542 type->newArraySizes(*arraySizes);
steve-lunarg265c0612016-09-27 10:57:35 -06001543 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001544
1545 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001546 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001547
John Kessenich5aa59e22016-06-17 15:50:47 -06001548 parseContext.paramFix(*type);
1549
John Kessenichaecd4972016-03-14 10:46:34 -06001550 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001551 function.addParameter(param);
1552
1553 return true;
1554}
1555
1556// Do the work to create the function definition in addition to
1557// parsing the body (compound_statement).
1558bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1559{
John Kessenicha3051662016-09-02 19:13:36 -06001560 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001561 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001562
John Kessenich077e0522016-06-09 02:02:17 -06001563 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001564 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001565
1566 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001567 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001568 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001569 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001570 return true;
1571 }
1572
1573 return false;
1574}
1575
John Kessenich0d2b6de2016-06-05 11:23:11 -06001576// Accept an expression with parenthesis around it, where
1577// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001578// syntactically required ones like in "if ( expression )".
1579//
1580// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001581//
1582// Note this one is not set up to be speculative; as it gives
1583// errors if not found.
1584//
1585bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1586{
1587 // LEFT_PAREN
1588 if (! acceptTokenClass(EHTokLeftParen))
1589 expected("(");
1590
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001591 bool decl = false;
1592 TIntermNode* declNode = nullptr;
1593 decl = acceptControlDeclaration(declNode);
1594 if (decl) {
1595 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1596 expected("initialized declaration");
1597 return false;
1598 } else
1599 expression = declNode->getAsTyped();
1600 } else {
1601 // no declaration
1602 if (! acceptExpression(expression)) {
1603 expected("expression");
1604 return false;
1605 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001606 }
1607
1608 // RIGHT_PAREN
1609 if (! acceptTokenClass(EHTokRightParen))
1610 expected(")");
1611
1612 return true;
1613}
1614
John Kessenich34fb0362016-05-03 23:17:20 -06001615// The top-level full expression recognizer.
1616//
John Kessenich87142c72016-03-12 20:24:24 -07001617// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001618// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001619//
1620bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1621{
LoopDawgef764a22016-06-03 09:17:51 -06001622 node = nullptr;
1623
John Kessenich34fb0362016-05-03 23:17:20 -06001624 // assignment_expression
1625 if (! acceptAssignmentExpression(node))
1626 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001627
John Kessenich34fb0362016-05-03 23:17:20 -06001628 if (! peekTokenClass(EHTokComma))
1629 return true;
1630
1631 do {
1632 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001633 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001634 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001635
John Kessenich34fb0362016-05-03 23:17:20 -06001636 // ... assignment_expression
1637 TIntermTyped* rightNode = nullptr;
1638 if (! acceptAssignmentExpression(rightNode)) {
1639 expected("assignment expression");
1640 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001641 }
1642
John Kessenich34fb0362016-05-03 23:17:20 -06001643 node = intermediate.addComma(node, rightNode, loc);
1644
1645 if (! peekTokenClass(EHTokComma))
1646 return true;
1647 } while (true);
1648}
1649
John Kessenich07354242016-07-01 19:58:06 -06001650// initializer
1651// : LEFT_BRACE initializer_list RIGHT_BRACE
1652//
1653// initializer_list
1654// : assignment_expression COMMA assignment_expression COMMA ...
1655//
1656bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1657{
1658 // LEFT_BRACE
1659 if (! acceptTokenClass(EHTokLeftBrace))
1660 return false;
1661
1662 // initializer_list
1663 TSourceLoc loc = token.loc;
1664 node = nullptr;
1665 do {
1666 // assignment_expression
1667 TIntermTyped* expr;
1668 if (! acceptAssignmentExpression(expr)) {
1669 expected("assignment expression in initializer list");
1670 return false;
1671 }
1672 node = intermediate.growAggregate(node, expr, loc);
1673
1674 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001675 if (acceptTokenClass(EHTokComma)) {
1676 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1677 return true;
John Kessenich07354242016-07-01 19:58:06 -06001678 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001679 }
John Kessenich07354242016-07-01 19:58:06 -06001680
1681 // RIGHT_BRACE
1682 if (acceptTokenClass(EHTokRightBrace))
1683 return true;
1684
1685 expected(", or }");
1686 return false;
1687 } while (true);
1688}
1689
John Kessenich34fb0362016-05-03 23:17:20 -06001690// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001691// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001692//
1693// a op (b op (c op d))
1694//
1695// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001696// : initializer
1697// | conditional_expression
1698// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001699//
1700bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1701{
John Kessenich07354242016-07-01 19:58:06 -06001702 // initializer
1703 if (peekTokenClass(EHTokLeftBrace)) {
1704 if (acceptInitializer(node))
1705 return true;
1706
1707 expected("initializer");
1708 return false;
1709 }
1710
John Kessenich00957f82016-07-27 10:39:57 -06001711 // conditional_expression
1712 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001713 return false;
1714
John Kessenich07354242016-07-01 19:58:06 -06001715 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001716 TOperator assignOp = HlslOpMap::assignment(peek());
1717 if (assignOp == EOpNull)
1718 return true;
1719
John Kessenich00957f82016-07-27 10:39:57 -06001720 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001721 TSourceLoc loc = token.loc;
1722 advanceToken();
1723
John Kessenich00957f82016-07-27 10:39:57 -06001724 // conditional_expression assign_op conditional_expression ...
1725 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001726 // gets the right-to-left associativity.
1727 TIntermTyped* rightNode = nullptr;
1728 if (! acceptAssignmentExpression(rightNode)) {
1729 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001730 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001731 }
1732
John Kessenichd21baed2016-09-16 03:05:12 -06001733 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
John Kessenichfea226b2016-07-28 17:53:56 -06001734 if (node == nullptr) {
1735 parseContext.error(loc, "could not create assignment", "", "");
1736 return false;
1737 }
John Kessenich34fb0362016-05-03 23:17:20 -06001738
1739 if (! peekTokenClass(EHTokComma))
1740 return true;
1741
1742 return true;
1743}
1744
John Kessenich00957f82016-07-27 10:39:57 -06001745// Accept a conditional expression, which associates right-to-left,
1746// accomplished by the "true" expression calling down to lower
1747// precedence levels than this level.
1748//
1749// conditional_expression
1750// : binary_expression
1751// | binary_expression QUESTION expression COLON assignment_expression
1752//
1753bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1754{
1755 // binary_expression
1756 if (! acceptBinaryExpression(node, PlLogicalOr))
1757 return false;
1758
1759 if (! acceptTokenClass(EHTokQuestion))
1760 return true;
1761
1762 TIntermTyped* trueNode = nullptr;
1763 if (! acceptExpression(trueNode)) {
1764 expected("expression after ?");
1765 return false;
1766 }
1767 TSourceLoc loc = token.loc;
1768
1769 if (! acceptTokenClass(EHTokColon)) {
1770 expected(":");
1771 return false;
1772 }
1773
1774 TIntermTyped* falseNode = nullptr;
1775 if (! acceptAssignmentExpression(falseNode)) {
1776 expected("expression after :");
1777 return false;
1778 }
1779
1780 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1781
1782 return true;
1783}
1784
John Kessenich34fb0362016-05-03 23:17:20 -06001785// Accept a binary expression, for binary operations that
1786// associate left-to-right. This is, it is implicit, for example
1787//
1788// ((a op b) op c) op d
1789//
1790// binary_expression
1791// : expression op expression op expression ...
1792//
1793// where 'expression' is the next higher level in precedence.
1794//
1795bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1796{
1797 if (precedenceLevel > PlMul)
1798 return acceptUnaryExpression(node);
1799
1800 // assignment_expression
1801 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1802 return false;
1803
John Kessenich34fb0362016-05-03 23:17:20 -06001804 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001805 TOperator op = HlslOpMap::binary(peek());
1806 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1807 if (tokenLevel < precedenceLevel)
1808 return true;
1809
John Kessenich34fb0362016-05-03 23:17:20 -06001810 // ... op
1811 TSourceLoc loc = token.loc;
1812 advanceToken();
1813
1814 // ... expression
1815 TIntermTyped* rightNode = nullptr;
1816 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1817 expected("expression");
1818 return false;
1819 }
1820
1821 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001822 if (node == nullptr) {
1823 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1824 return false;
1825 }
John Kessenich34fb0362016-05-03 23:17:20 -06001826 } while (true);
1827}
1828
1829// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001830// : (type) unary_expression
1831// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001832// | - unary_expression
1833// | ! unary_expression
1834// | ~ unary_expression
1835// | ++ unary_expression
1836// | -- unary_expression
1837// | postfix_expression
1838//
1839bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1840{
John Kessenich1cc1a282016-06-03 16:55:49 -06001841 // (type) unary_expression
1842 // Have to look two steps ahead, because this could be, e.g., a
1843 // postfix_expression instead, since that also starts with at "(".
1844 if (acceptTokenClass(EHTokLeftParen)) {
1845 TType castType;
1846 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001847 if (acceptTokenClass(EHTokRightParen)) {
1848 // We've matched "(type)" now, get the expression to cast
1849 TSourceLoc loc = token.loc;
1850 if (! acceptUnaryExpression(node))
1851 return false;
1852
1853 // Hook it up like a constructor
1854 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1855 if (constructorFunction == nullptr) {
1856 expected("type that can be constructed");
1857 return false;
1858 }
1859 TIntermTyped* arguments = nullptr;
1860 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1861 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1862
1863 return true;
1864 } else {
1865 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
1866 // the '(int' part. We must back up twice.
1867 recedeToken();
1868 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06001869 }
John Kessenich1cc1a282016-06-03 16:55:49 -06001870 } else {
1871 // This isn't a type cast, but it still started "(", so if it is a
1872 // unary expression, it can only be a postfix_expression, so try that.
1873 // Back it up first.
1874 recedeToken();
1875 return acceptPostfixExpression(node);
1876 }
1877 }
1878
1879 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001880 TOperator unaryOp = HlslOpMap::preUnary(peek());
1881
John Kessenich1cc1a282016-06-03 16:55:49 -06001882 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001883 if (unaryOp == EOpNull)
1884 return acceptPostfixExpression(node);
1885
1886 // op unary_expression
1887 TSourceLoc loc = token.loc;
1888 advanceToken();
1889 if (! acceptUnaryExpression(node))
1890 return false;
1891
1892 // + is a no-op
1893 if (unaryOp == EOpAdd)
1894 return true;
1895
1896 node = intermediate.addUnaryMath(unaryOp, node, loc);
1897
1898 return node != nullptr;
1899}
1900
1901// postfix_expression
1902// : LEFT_PAREN expression RIGHT_PAREN
1903// | literal
1904// | constructor
1905// | identifier
1906// | function_call
1907// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1908// | postfix_expression DOT IDENTIFIER
1909// | postfix_expression INC_OP
1910// | postfix_expression DEC_OP
1911//
1912bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1913{
1914 // Not implemented as self-recursive:
1915 // The logical "right recursion" is done with an loop at the end
1916
1917 // idToken will pick up either a variable or a function name in a function call
1918 HlslToken idToken;
1919
John Kessenich21472ae2016-06-04 11:46:33 -06001920 // Find something before the postfix operations, as they can't operate
1921 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001922 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001923 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001924 if (! acceptExpression(node)) {
1925 expected("expression");
1926 return false;
1927 }
1928 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001929 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001930 return false;
1931 }
John Kessenich34fb0362016-05-03 23:17:20 -06001932 } else if (acceptLiteral(node)) {
1933 // literal (nothing else to do yet), go on to the
1934 } else if (acceptConstructor(node)) {
1935 // constructor (nothing else to do yet)
1936 } else if (acceptIdentifier(idToken)) {
1937 // identifier or function_call name
1938 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001939 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001940 } else if (acceptFunctionCall(idToken, node)) {
1941 // function_call (nothing else to do yet)
1942 } else {
1943 expected("function call arguments");
1944 return false;
1945 }
John Kessenich21472ae2016-06-04 11:46:33 -06001946 } else {
1947 // nothing found, can't post operate
1948 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001949 }
1950
John Kessenich21472ae2016-06-04 11:46:33 -06001951 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001952 do {
1953 TSourceLoc loc = token.loc;
1954 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001955
John Kessenich34fb0362016-05-03 23:17:20 -06001956 // Consume only a valid post-unary operator, otherwise we are done.
1957 switch (postOp) {
1958 case EOpIndexDirectStruct:
1959 case EOpIndexIndirect:
1960 case EOpPostIncrement:
1961 case EOpPostDecrement:
1962 advanceToken();
1963 break;
1964 default:
1965 return true;
1966 }
John Kessenich87142c72016-03-12 20:24:24 -07001967
John Kessenich34fb0362016-05-03 23:17:20 -06001968 // We have a valid post-unary operator, process it.
1969 switch (postOp) {
1970 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001971 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001972 // DOT IDENTIFIER
1973 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001974 HlslToken field;
1975 if (! acceptIdentifier(field)) {
1976 expected("swizzle or member");
1977 return false;
1978 }
LoopDawg4886f692016-06-29 10:58:58 -06001979
1980 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001981 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001982
1983 // In the event of a method node, we look for an open paren and accept the function call.
1984 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1985 if (! acceptFunctionCall(field, node, base)) {
1986 expected("function parameters");
1987 return false;
1988 }
1989 }
1990
John Kessenich34fb0362016-05-03 23:17:20 -06001991 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001992 }
John Kessenich34fb0362016-05-03 23:17:20 -06001993 case EOpIndexIndirect:
1994 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001995 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001996 TIntermTyped* indexNode = nullptr;
1997 if (! acceptExpression(indexNode) ||
1998 ! peekTokenClass(EHTokRightBracket)) {
1999 expected("expression followed by ']'");
2000 return false;
2001 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002002 advanceToken();
2003 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
2004 break;
John Kessenich34fb0362016-05-03 23:17:20 -06002005 }
2006 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002007 // INC_OP
2008 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002009 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002010 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002011 node = intermediate.addUnaryMath(postOp, node, loc);
2012 break;
2013 default:
2014 assert(0);
2015 break;
2016 }
2017 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002018}
2019
John Kessenichd016be12016-03-13 11:24:20 -06002020// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002021// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002022//
2023bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2024{
2025 // type
2026 TType type;
2027 if (acceptType(type)) {
2028 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2029 if (constructorFunction == nullptr)
2030 return false;
2031
2032 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002033 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002034 if (! acceptArguments(constructorFunction, arguments)) {
2035 expected("constructor arguments");
2036 return false;
2037 }
2038
2039 // hook it up
2040 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2041
2042 return true;
2043 }
2044
2045 return false;
2046}
2047
John Kessenich34fb0362016-05-03 23:17:20 -06002048// The function_call identifier was already recognized, and passed in as idToken.
2049//
2050// function_call
2051// : [idToken] arguments
2052//
LoopDawg4886f692016-06-29 10:58:58 -06002053bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002054{
John Kessenich4678ca92016-05-13 09:33:42 -06002055 // arguments
2056 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2057 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002058
2059 // methods have an implicit first argument of the calling object.
2060 if (base != nullptr)
2061 parseContext.handleFunctionArgument(function, arguments, base);
2062
John Kessenich4678ca92016-05-13 09:33:42 -06002063 if (! acceptArguments(function, arguments))
2064 return false;
2065
2066 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2067
2068 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002069}
2070
John Kessenich87142c72016-03-12 20:24:24 -07002071// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002072// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002073//
John Kessenichd016be12016-03-13 11:24:20 -06002074// The arguments are pushed onto the 'function' argument list and
2075// onto the 'arguments' aggregate.
2076//
John Kessenich4678ca92016-05-13 09:33:42 -06002077bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002078{
John Kessenich078d7f22016-03-14 10:02:11 -06002079 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002080 if (! acceptTokenClass(EHTokLeftParen))
2081 return false;
2082
2083 do {
John Kessenichd016be12016-03-13 11:24:20 -06002084 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002085 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002086 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002087 break;
John Kessenichd016be12016-03-13 11:24:20 -06002088
2089 // hook it up
2090 parseContext.handleFunctionArgument(function, arguments, arg);
2091
John Kessenich078d7f22016-03-14 10:02:11 -06002092 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002093 if (! acceptTokenClass(EHTokComma))
2094 break;
2095 } while (true);
2096
John Kessenich078d7f22016-03-14 10:02:11 -06002097 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002098 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002099 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002100 return false;
2101 }
2102
2103 return true;
2104}
2105
2106bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2107{
2108 switch (token.tokenClass) {
2109 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002110 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002111 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002112 case EHTokUintConstant:
2113 node = intermediate.addConstantUnion(token.u, token.loc, true);
2114 break;
John Kessenich87142c72016-03-12 20:24:24 -07002115 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002116 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002117 break;
2118 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002119 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002120 break;
2121 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002122 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002123 break;
John Kessenich86f71382016-09-19 20:23:18 -06002124 case EHTokStringConstant:
2125 node = nullptr;
2126 break;
John Kessenich87142c72016-03-12 20:24:24 -07002127
2128 default:
2129 return false;
2130 }
2131
2132 advanceToken();
2133
2134 return true;
2135}
2136
John Kessenich5f934b02016-03-13 17:58:25 -06002137// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002138// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002139//
John Kessenich21472ae2016-06-04 11:46:33 -06002140bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002141{
John Kessenich21472ae2016-06-04 11:46:33 -06002142 TIntermAggregate* compoundStatement = nullptr;
2143
John Kessenich34fb0362016-05-03 23:17:20 -06002144 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002145 if (! acceptTokenClass(EHTokLeftBrace))
2146 return false;
2147
2148 // statement statement ...
2149 TIntermNode* statement = nullptr;
2150 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002151 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2152 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2153 branch->getFlowOp() == EOpDefault)) {
2154 // hook up individual subsequences within a switch statement
2155 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2156 compoundStatement = nullptr;
2157 } else {
2158 // hook it up to the growing compound statement
2159 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2160 }
John Kessenich5f934b02016-03-13 17:58:25 -06002161 }
John Kessenich34fb0362016-05-03 23:17:20 -06002162 if (compoundStatement)
2163 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002164
John Kessenich21472ae2016-06-04 11:46:33 -06002165 retStatement = compoundStatement;
2166
John Kessenich34fb0362016-05-03 23:17:20 -06002167 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002168 return acceptTokenClass(EHTokRightBrace);
2169}
2170
John Kessenich0d2b6de2016-06-05 11:23:11 -06002171bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2172{
2173 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002174 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002175 parseContext.popScope();
2176
2177 return result;
2178}
2179
John Kessenich077e0522016-06-09 02:02:17 -06002180bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002181{
John Kessenich077e0522016-06-09 02:02:17 -06002182 parseContext.pushScope();
2183 bool result = acceptCompoundStatement(statement);
2184 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002185
2186 return result;
2187}
2188
John Kessenich5f934b02016-03-13 17:58:25 -06002189// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002190// : attributes attributed_statement
2191//
2192// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002193// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002194// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002195// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002196// | declaration_statement
2197// | selection_statement
2198// | switch_statement
2199// | case_label
2200// | iteration_statement
2201// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002202//
2203bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2204{
John Kessenich21472ae2016-06-04 11:46:33 -06002205 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002206
John Kessenich21472ae2016-06-04 11:46:33 -06002207 // attributes
2208 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002209
John Kessenich21472ae2016-06-04 11:46:33 -06002210 // attributed_statement
2211 switch (peek()) {
2212 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002213 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002214
John Kessenich21472ae2016-06-04 11:46:33 -06002215 case EHTokIf:
2216 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002217
John Kessenich21472ae2016-06-04 11:46:33 -06002218 case EHTokSwitch:
2219 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002220
John Kessenich21472ae2016-06-04 11:46:33 -06002221 case EHTokFor:
2222 case EHTokDo:
2223 case EHTokWhile:
2224 return acceptIterationStatement(statement);
2225
2226 case EHTokContinue:
2227 case EHTokBreak:
2228 case EHTokDiscard:
2229 case EHTokReturn:
2230 return acceptJumpStatement(statement);
2231
2232 case EHTokCase:
2233 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002234 case EHTokDefault:
2235 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002236
2237 case EHTokSemicolon:
2238 return acceptTokenClass(EHTokSemicolon);
2239
2240 case EHTokRightBrace:
2241 // Performance: not strictly necessary, but stops a bunch of hunting early,
2242 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002243 return false;
2244
John Kessenich21472ae2016-06-04 11:46:33 -06002245 default:
2246 {
2247 // declaration
2248 if (acceptDeclaration(statement))
2249 return true;
2250
2251 // expression
2252 TIntermTyped* node;
2253 if (acceptExpression(node))
2254 statement = node;
2255 else
2256 return false;
2257
2258 // SEMICOLON (following an expression)
2259 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002260 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002261 return false;
2262 }
2263 }
2264 }
2265
John Kessenich5f934b02016-03-13 17:58:25 -06002266 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002267}
2268
John Kessenich21472ae2016-06-04 11:46:33 -06002269// attributes
2270// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2271//
2272// attribute:
2273// : UNROLL
2274// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2275// | FASTOPT
2276// | ALLOW_UAV_CONDITION
2277// | BRANCH
2278// | FLATTEN
2279// | FORCECASE
2280// | CALL
2281//
2282void HlslGrammar::acceptAttributes()
2283{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002284 // For now, accept the [ XXX(X) ] syntax, but drop.
2285 // TODO: subset to correct set? Pass on?
2286 do {
2287 // LEFT_BRACKET?
2288 if (! acceptTokenClass(EHTokLeftBracket))
2289 return;
2290
2291 // attribute
2292 if (peekTokenClass(EHTokIdentifier)) {
2293 // 'token.string' is the attribute
2294 advanceToken();
2295 } else if (! peekTokenClass(EHTokRightBracket)) {
2296 expected("identifier");
2297 advanceToken();
2298 }
2299
2300 // (x)
2301 if (acceptTokenClass(EHTokLeftParen)) {
2302 TIntermTyped* node;
2303 if (! acceptLiteral(node))
2304 expected("literal");
2305 // 'node' has the literal in it
2306 if (! acceptTokenClass(EHTokRightParen))
2307 expected(")");
2308 }
2309
2310 // RIGHT_BRACKET
2311 if (acceptTokenClass(EHTokRightBracket))
2312 continue;
2313
2314 expected("]");
2315 return;
2316
2317 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002318}
2319
John Kessenich0d2b6de2016-06-05 11:23:11 -06002320// selection_statement
2321// : IF LEFT_PAREN expression RIGHT_PAREN statement
2322// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2323//
John Kessenich21472ae2016-06-04 11:46:33 -06002324bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2325{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002326 TSourceLoc loc = token.loc;
2327
2328 // IF
2329 if (! acceptTokenClass(EHTokIf))
2330 return false;
2331
2332 // so that something declared in the condition is scoped to the lifetimes
2333 // of the then-else statements
2334 parseContext.pushScope();
2335
2336 // LEFT_PAREN expression RIGHT_PAREN
2337 TIntermTyped* condition;
2338 if (! acceptParenExpression(condition))
2339 return false;
2340
2341 // create the child statements
2342 TIntermNodePair thenElse = { nullptr, nullptr };
2343
2344 // then statement
2345 if (! acceptScopedStatement(thenElse.node1)) {
2346 expected("then statement");
2347 return false;
2348 }
2349
2350 // ELSE
2351 if (acceptTokenClass(EHTokElse)) {
2352 // else statement
2353 if (! acceptScopedStatement(thenElse.node2)) {
2354 expected("else statement");
2355 return false;
2356 }
2357 }
2358
2359 // Put the pieces together
2360 statement = intermediate.addSelection(condition, thenElse, loc);
2361 parseContext.popScope();
2362
2363 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002364}
2365
John Kessenichd02dc5d2016-07-01 00:04:11 -06002366// switch_statement
2367// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2368//
John Kessenich21472ae2016-06-04 11:46:33 -06002369bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2370{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002371 // SWITCH
2372 TSourceLoc loc = token.loc;
2373 if (! acceptTokenClass(EHTokSwitch))
2374 return false;
2375
2376 // LEFT_PAREN expression RIGHT_PAREN
2377 parseContext.pushScope();
2378 TIntermTyped* switchExpression;
2379 if (! acceptParenExpression(switchExpression)) {
2380 parseContext.popScope();
2381 return false;
2382 }
2383
2384 // compound_statement
2385 parseContext.pushSwitchSequence(new TIntermSequence);
2386 bool statementOkay = acceptCompoundStatement(statement);
2387 if (statementOkay)
2388 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2389
2390 parseContext.popSwitchSequence();
2391 parseContext.popScope();
2392
2393 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002394}
2395
John Kessenich119f8f62016-06-05 15:44:07 -06002396// iteration_statement
2397// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2398// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2399// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2400//
2401// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002402bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2403{
John Kessenich119f8f62016-06-05 15:44:07 -06002404 TSourceLoc loc = token.loc;
2405 TIntermTyped* condition = nullptr;
2406
2407 EHlslTokenClass loop = peek();
2408 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2409
2410 // WHILE or DO or FOR
2411 advanceToken();
2412
2413 switch (loop) {
2414 case EHTokWhile:
2415 // so that something declared in the condition is scoped to the lifetime
2416 // of the while sub-statement
2417 parseContext.pushScope();
2418 parseContext.nestLooping();
2419
2420 // LEFT_PAREN condition RIGHT_PAREN
2421 if (! acceptParenExpression(condition))
2422 return false;
2423
2424 // statement
2425 if (! acceptScopedStatement(statement)) {
2426 expected("while sub-statement");
2427 return false;
2428 }
2429
2430 parseContext.unnestLooping();
2431 parseContext.popScope();
2432
2433 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2434
2435 return true;
2436
2437 case EHTokDo:
2438 parseContext.nestLooping();
2439
2440 if (! acceptTokenClass(EHTokLeftBrace))
2441 expected("{");
2442
2443 // statement
2444 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2445 expected("do sub-statement");
2446 return false;
2447 }
2448
2449 if (! acceptTokenClass(EHTokRightBrace))
2450 expected("}");
2451
2452 // WHILE
2453 if (! acceptTokenClass(EHTokWhile)) {
2454 expected("while");
2455 return false;
2456 }
2457
2458 // LEFT_PAREN condition RIGHT_PAREN
2459 TIntermTyped* condition;
2460 if (! acceptParenExpression(condition))
2461 return false;
2462
2463 if (! acceptTokenClass(EHTokSemicolon))
2464 expected(";");
2465
2466 parseContext.unnestLooping();
2467
2468 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2469
2470 return true;
2471
2472 case EHTokFor:
2473 {
2474 // LEFT_PAREN
2475 if (! acceptTokenClass(EHTokLeftParen))
2476 expected("(");
2477
2478 // so that something declared in the condition is scoped to the lifetime
2479 // of the for sub-statement
2480 parseContext.pushScope();
2481
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002482 // initializer
2483 TIntermNode* initNode = nullptr;
2484 if (! acceptControlDeclaration(initNode)) {
2485 TIntermTyped* initExpr = nullptr;
2486 acceptExpression(initExpr);
2487 initNode = initExpr;
2488 }
2489 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002490 if (! acceptTokenClass(EHTokSemicolon))
2491 expected(";");
2492
2493 parseContext.nestLooping();
2494
2495 // condition SEMI_COLON
2496 acceptExpression(condition);
2497 if (! acceptTokenClass(EHTokSemicolon))
2498 expected(";");
2499
2500 // iterator SEMI_COLON
2501 TIntermTyped* iterator = nullptr;
2502 acceptExpression(iterator);
2503 if (! acceptTokenClass(EHTokRightParen))
2504 expected(")");
2505
2506 // statement
2507 if (! acceptScopedStatement(statement)) {
2508 expected("for sub-statement");
2509 return false;
2510 }
2511
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002512 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002513
2514 parseContext.popScope();
2515 parseContext.unnestLooping();
2516
2517 return true;
2518 }
2519
2520 default:
2521 return false;
2522 }
John Kessenich21472ae2016-06-04 11:46:33 -06002523}
2524
2525// jump_statement
2526// : CONTINUE SEMICOLON
2527// | BREAK SEMICOLON
2528// | DISCARD SEMICOLON
2529// | RETURN SEMICOLON
2530// | RETURN expression SEMICOLON
2531//
2532bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2533{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002534 EHlslTokenClass jump = peek();
2535 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002536 case EHTokContinue:
2537 case EHTokBreak:
2538 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002539 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002540 advanceToken();
2541 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002542 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002543 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002544 return false;
2545 }
John Kessenich21472ae2016-06-04 11:46:33 -06002546
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002547 switch (jump) {
2548 case EHTokContinue:
2549 statement = intermediate.addBranch(EOpContinue, token.loc);
2550 break;
2551 case EHTokBreak:
2552 statement = intermediate.addBranch(EOpBreak, token.loc);
2553 break;
2554 case EHTokDiscard:
2555 statement = intermediate.addBranch(EOpKill, token.loc);
2556 break;
2557
2558 case EHTokReturn:
2559 {
2560 // expression
2561 TIntermTyped* node;
2562 if (acceptExpression(node)) {
2563 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002564 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002565 } else
2566 statement = intermediate.addBranch(EOpReturn, token.loc);
2567 break;
2568 }
2569
2570 default:
2571 assert(0);
2572 return false;
2573 }
2574
2575 // SEMICOLON
2576 if (! acceptTokenClass(EHTokSemicolon))
2577 expected(";");
2578
2579 return true;
2580}
John Kessenich21472ae2016-06-04 11:46:33 -06002581
John Kessenichd02dc5d2016-07-01 00:04:11 -06002582// case_label
2583// : CASE expression COLON
2584//
John Kessenich21472ae2016-06-04 11:46:33 -06002585bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2586{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002587 TSourceLoc loc = token.loc;
2588 if (! acceptTokenClass(EHTokCase))
2589 return false;
2590
2591 TIntermTyped* expression;
2592 if (! acceptExpression(expression)) {
2593 expected("case expression");
2594 return false;
2595 }
2596
2597 if (! acceptTokenClass(EHTokColon)) {
2598 expected(":");
2599 return false;
2600 }
2601
2602 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2603
2604 return true;
2605}
2606
2607// default_label
2608// : DEFAULT COLON
2609//
2610bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2611{
2612 TSourceLoc loc = token.loc;
2613 if (! acceptTokenClass(EHTokDefault))
2614 return false;
2615
2616 if (! acceptTokenClass(EHTokColon)) {
2617 expected(":");
2618 return false;
2619 }
2620
2621 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2622
2623 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002624}
2625
John Kessenich19b92ff2016-06-19 11:50:34 -06002626// array_specifier
2627// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
steve-lunarg265c0612016-09-27 10:57:35 -06002628// : LEFT_BRACKET RGHT_BRACKET post_decls // optional
John Kessenich19b92ff2016-06-19 11:50:34 -06002629//
2630void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2631{
2632 arraySizes = nullptr;
2633
2634 if (! acceptTokenClass(EHTokLeftBracket))
2635 return;
2636
2637 TSourceLoc loc = token.loc;
steve-lunarg265c0612016-09-27 10:57:35 -06002638 TIntermTyped* sizeExpr = nullptr;
2639
2640 // Array sizing expression is optional. If ommitted, array is implicitly sized.
2641 const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
John Kessenich19b92ff2016-06-19 11:50:34 -06002642
2643 if (! acceptTokenClass(EHTokRightBracket)) {
2644 expected("]");
2645 return;
2646 }
2647
John Kessenich19b92ff2016-06-19 11:50:34 -06002648 arraySizes = new TArraySizes;
steve-lunarg265c0612016-09-27 10:57:35 -06002649
2650 if (hasArraySize) {
2651 TArraySize arraySize;
2652 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2653 arraySizes->addInnerSize(arraySize);
2654 } else {
2655 arraySizes->addInnerSize(); // implicitly sized
2656 }
John Kessenich19b92ff2016-06-19 11:50:34 -06002657}
2658
John Kessenich630dd7d2016-06-12 23:52:12 -06002659// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002660// : COLON semantic // optional
2661// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2662// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002663// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002664// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002665//
John Kessenich7735b942016-09-05 12:40:06 -06002666void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002667{
John Kessenich630dd7d2016-06-12 23:52:12 -06002668 do {
2669 // COLON
2670 if (acceptTokenClass(EHTokColon)) {
2671 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002672 if (peekTokenClass(EHTokLayout))
2673 acceptLayoutQualifierList(qualifier);
2674 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002675 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002676 if (! acceptTokenClass(EHTokLeftParen)) {
2677 expected("(");
2678 return;
2679 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002680 HlslToken locationToken;
2681 if (! acceptIdentifier(locationToken)) {
2682 expected("c[subcomponent][.component]");
2683 return;
2684 }
2685 HlslToken componentToken;
2686 if (acceptTokenClass(EHTokDot)) {
2687 if (! acceptIdentifier(componentToken)) {
2688 expected("component");
2689 return;
2690 }
2691 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002692 if (! acceptTokenClass(EHTokRightParen)) {
2693 expected(")");
2694 break;
2695 }
John Kessenich7735b942016-09-05 12:40:06 -06002696 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002697 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002698 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002699 return;
2700 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002701 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2702 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002703 if (! acceptTokenClass(EHTokLeftParen)) {
2704 expected("(");
2705 return;
2706 }
John Kessenichb38f0712016-07-30 10:29:54 -06002707 HlslToken registerDesc; // for Type#
2708 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002709 if (! acceptIdentifier(registerDesc)) {
2710 expected("register number description");
2711 return;
2712 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002713 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2714 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002715 // Then we didn't really see the registerDesc yet, it was
2716 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002717 profile = registerDesc;
2718 if (! acceptIdentifier(registerDesc)) {
2719 expected("register number description");
2720 return;
2721 }
2722 }
John Kessenichb38f0712016-07-30 10:29:54 -06002723 int subComponent = 0;
2724 if (acceptTokenClass(EHTokLeftBracket)) {
2725 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2726 if (! peekTokenClass(EHTokIntConstant)) {
2727 expected("literal integer");
2728 return;
2729 }
2730 subComponent = token.i;
2731 advanceToken();
2732 if (! acceptTokenClass(EHTokRightBracket)) {
2733 expected("]");
2734 break;
2735 }
2736 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002737 // (COMMA SPACEN)opt
2738 HlslToken spaceDesc;
2739 if (acceptTokenClass(EHTokComma)) {
2740 if (! acceptIdentifier(spaceDesc)) {
2741 expected ("space identifier");
2742 return;
2743 }
2744 }
2745 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002746 if (! acceptTokenClass(EHTokRightParen)) {
2747 expected(")");
2748 break;
2749 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002750 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002751 } else {
2752 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002753 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002754 }
John Kessenicha1e2d492016-09-20 13:22:58 -06002755 } else if (peekTokenClass(EHTokLeftAngle))
2756 acceptAnnotations(qualifier);
2757 else
John Kessenich630dd7d2016-06-12 23:52:12 -06002758 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002759
John Kessenich630dd7d2016-06-12 23:52:12 -06002760 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002761}
2762
John Kesseniche01a9bc2016-03-12 20:11:22 -07002763} // end namespace glslang