blob: 7d2f0afeff3f3fbd8760ad2c07cf0947ae09d42d [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 Kessenich87142c72016-03-12 20:24:24 -0700274 TType type;
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
283 // if (acceptSamplerDeclarationDX9(type))
284 // return true;
LoopDawg4886f692016-06-29 10:58:58 -0600285
286 // fully_specified_type
John Kessenich87142c72016-03-12 20:24:24 -0700287 if (! acceptFullySpecifiedType(type))
288 return false;
LoopDawg4886f692016-06-29 10:58:58 -0600289
290 if (type.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) {
291 if (type.getBasicType() == EbtSampler) {
292 // 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.
295 type.getQualifier().storage = EvqUniform;
296 } else {
297 type.getQualifier().storage = EvqGlobal;
298 }
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 Kessenich9e079532016-09-02 20:05:19 -0600305 TFunction& function = *new TFunction(idToken.string, type);
306 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 {
323 // a variable declaration
John Kessenich5f934b02016-03-13 17:58:25 -0600324
John Kessenichd5ed0b62016-07-04 17:32:45 -0600325 // array_specifier
326 TArraySizes* arraySizes = nullptr;
327 acceptArraySpecifier(arraySizes);
John Kessenich5f934b02016-03-13 17:58:25 -0600328
LoopDawg4886f692016-06-29 10:58:58 -0600329 // samplers accept immediate sampler state
330 if (type.getBasicType() == EbtSampler) {
331 if (! acceptSamplerState())
332 return false;
333 }
334
John Kessenichd5ed0b62016-07-04 17:32:45 -0600335 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -0600336 acceptPostDecls(type.getQualifier());
John Kessenichd5ed0b62016-07-04 17:32:45 -0600337
338 // EQUAL assignment_expression
339 TIntermTyped* expressionNode = nullptr;
340 if (acceptTokenClass(EHTokAssign)) {
John Kessenich5e69ec62016-07-05 00:02:40 -0600341 if (typedefDecl)
342 parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
John Kessenichd5ed0b62016-07-04 17:32:45 -0600343 if (! acceptAssignmentExpression(expressionNode)) {
344 expected("initializer");
345 return false;
346 }
347 }
348
John Kessenich5e69ec62016-07-05 00:02:40 -0600349 if (typedefDecl)
350 parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
John Kessenich3d157c52016-07-25 16:05:33 -0600351 else if (type.getBasicType() == EbtBlock)
352 parseContext.declareBlock(idToken.loc, type, idToken.string);
John Kessenich5e69ec62016-07-05 00:02:40 -0600353 else {
354 // Declare the variable and add any initializer code to the AST.
355 // The top-level node is always made into an aggregate, as that's
356 // historically how the AST has been.
357 node = intermediate.growAggregate(node,
358 parseContext.declareVariable(idToken.loc, *idToken.string, type,
359 arraySizes, expressionNode),
360 idToken.loc);
361 }
John Kessenich5f934b02016-03-13 17:58:25 -0600362 }
John Kessenichd5ed0b62016-07-04 17:32:45 -0600363
364 if (acceptTokenClass(EHTokComma)) {
365 list = true;
366 continue;
367 }
368 };
369
370 // The top-level node is a sequence.
371 if (node != nullptr)
372 node->getAsAggregate()->setOperator(EOpSequence);
John Kessenich87142c72016-03-12 20:24:24 -0700373
John Kessenich078d7f22016-03-14 10:02:11 -0600374 // SEMICOLON
John Kessenichd5ed0b62016-07-04 17:32:45 -0600375 if (! acceptTokenClass(EHTokSemicolon)) {
376 expected(";");
377 return false;
378 }
379
John Kesseniche01a9bc2016-03-12 20:11:22 -0700380 return true;
381}
382
John Kessenich5bc4d9a2016-06-20 01:22:38 -0600383// control_declaration
384// : fully_specified_type identifier EQUAL expression
385//
386bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
387{
388 node = nullptr;
389
390 // fully_specified_type
391 TType type;
392 if (! acceptFullySpecifiedType(type))
393 return false;
394
395 // identifier
396 HlslToken idToken;
397 if (! acceptIdentifier(idToken)) {
398 expected("identifier");
399 return false;
400 }
401
402 // EQUAL
403 TIntermTyped* expressionNode = nullptr;
404 if (! acceptTokenClass(EHTokAssign)) {
405 expected("=");
406 return false;
407 }
408
409 // expression
410 if (! acceptExpression(expressionNode)) {
411 expected("initializer");
412 return false;
413 }
414
415 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
416
417 return true;
418}
419
John Kessenich87142c72016-03-12 20:24:24 -0700420// fully_specified_type
421// : type_specifier
422// | type_qualifier type_specifier
423//
424bool HlslGrammar::acceptFullySpecifiedType(TType& type)
425{
426 // type_qualifier
427 TQualifier qualifier;
428 qualifier.clear();
John Kessenichb9e39122016-08-17 10:22:08 -0600429 if (! acceptQualifier(qualifier))
430 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600431 TSourceLoc loc = token.loc;
John Kessenich87142c72016-03-12 20:24:24 -0700432
433 // type_specifier
434 if (! acceptType(type))
435 return false;
John Kessenich3d157c52016-07-25 16:05:33 -0600436 if (type.getBasicType() == EbtBlock) {
437 // the type was a block, which set some parts of the qualifier
438 parseContext.mergeQualifiers(loc, type.getQualifier(), qualifier, true);
439 // further, it can create an anonymous instance of the block
440 if (peekTokenClass(EHTokSemicolon))
441 parseContext.declareBlock(loc, type);
442 } else
443 type.getQualifier() = qualifier;
John Kessenich87142c72016-03-12 20:24:24 -0700444
445 return true;
446}
447
John Kessenich630dd7d2016-06-12 23:52:12 -0600448// type_qualifier
449// : qualifier qualifier ...
450//
451// Zero or more of these, so this can't return false.
452//
John Kessenichb9e39122016-08-17 10:22:08 -0600453bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
John Kessenich87142c72016-03-12 20:24:24 -0700454{
John Kessenich630dd7d2016-06-12 23:52:12 -0600455 do {
456 switch (peek()) {
457 case EHTokStatic:
458 // normal glslang default
459 break;
460 case EHTokExtern:
461 // TODO: no meaning in glslang?
462 break;
463 case EHTokShared:
464 // TODO: hint
465 break;
466 case EHTokGroupShared:
467 qualifier.storage = EvqShared;
468 break;
469 case EHTokUniform:
470 qualifier.storage = EvqUniform;
471 break;
472 case EHTokConst:
473 qualifier.storage = EvqConst;
474 break;
475 case EHTokVolatile:
476 qualifier.volatil = true;
477 break;
478 case EHTokLinear:
479 qualifier.storage = EvqVaryingIn;
480 qualifier.smooth = true;
481 break;
482 case EHTokCentroid:
483 qualifier.centroid = true;
484 break;
485 case EHTokNointerpolation:
486 qualifier.flat = true;
487 break;
488 case EHTokNoperspective:
489 qualifier.nopersp = true;
490 break;
491 case EHTokSample:
492 qualifier.sample = true;
493 break;
494 case EHTokRowMajor:
495 qualifier.layoutMatrix = ElmRowMajor;
496 break;
497 case EHTokColumnMajor:
498 qualifier.layoutMatrix = ElmColumnMajor;
499 break;
500 case EHTokPrecise:
501 qualifier.noContraction = true;
502 break;
LoopDawg9249c702016-07-12 20:44:32 -0600503 case EHTokIn:
504 qualifier.storage = EvqIn;
505 break;
506 case EHTokOut:
507 qualifier.storage = EvqOut;
508 break;
509 case EHTokInOut:
510 qualifier.storage = EvqInOut;
511 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600512 case EHTokLayout:
513 if (! acceptLayoutQualifierList(qualifier))
514 return false;
515 continue;
John Kessenich630dd7d2016-06-12 23:52:12 -0600516 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600517 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600518 }
519 advanceToken();
520 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700521}
522
John Kessenichb9e39122016-08-17 10:22:08 -0600523// layout_qualifier_list
524// : LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
525//
526// layout_qualifier
527// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600528// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600529//
530// Zero or more of these, so this can't return false.
531//
532bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
533{
534 if (! acceptTokenClass(EHTokLayout))
535 return false;
536
537 // LEFT_PAREN
538 if (! acceptTokenClass(EHTokLeftParen))
539 return false;
540
541 do {
542 // identifier
543 HlslToken idToken;
544 if (! acceptIdentifier(idToken))
545 break;
546
547 // EQUAL expression
548 if (acceptTokenClass(EHTokAssign)) {
549 TIntermTyped* expr;
550 if (! acceptConditionalExpression(expr)) {
551 expected("expression");
552 return false;
553 }
554 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
555 } else
556 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
557
558 // COMMA
559 if (! acceptTokenClass(EHTokComma))
560 break;
561 } while (true);
562
563 // RIGHT_PAREN
564 if (! acceptTokenClass(EHTokRightParen)) {
565 expected(")");
566 return false;
567 }
568
569 return true;
570}
571
LoopDawg6daaa4f2016-06-23 19:13:48 -0600572// template_type
573// : FLOAT
574// | DOUBLE
575// | INT
576// | DWORD
577// | UINT
578// | BOOL
579//
580bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
581{
582 switch (peek()) {
583 case EHTokFloat:
584 basicType = EbtFloat;
585 break;
586 case EHTokDouble:
587 basicType = EbtDouble;
588 break;
589 case EHTokInt:
590 case EHTokDword:
591 basicType = EbtInt;
592 break;
593 case EHTokUint:
594 basicType = EbtUint;
595 break;
596 case EHTokBool:
597 basicType = EbtBool;
598 break;
599 default:
600 return false;
601 }
602
603 advanceToken();
604
605 return true;
606}
607
608// vector_template_type
609// : VECTOR
610// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
611//
612bool HlslGrammar::acceptVectorTemplateType(TType& type)
613{
614 if (! acceptTokenClass(EHTokVector))
615 return false;
616
617 if (! acceptTokenClass(EHTokLeftAngle)) {
618 // in HLSL, 'vector' alone means float4.
619 new(&type) TType(EbtFloat, EvqTemporary, 4);
620 return true;
621 }
622
623 TBasicType basicType;
624 if (! acceptTemplateType(basicType)) {
625 expected("scalar type");
626 return false;
627 }
628
629 // COMMA
630 if (! acceptTokenClass(EHTokComma)) {
631 expected(",");
632 return false;
633 }
634
635 // integer
636 if (! peekTokenClass(EHTokIntConstant)) {
637 expected("literal integer");
638 return false;
639 }
640
641 TIntermTyped* vecSize;
642 if (! acceptLiteral(vecSize))
643 return false;
644
645 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
646
647 new(&type) TType(basicType, EvqTemporary, vecSizeI);
648
649 if (vecSizeI == 1)
650 type.makeVector();
651
652 if (!acceptTokenClass(EHTokRightAngle)) {
653 expected("right angle bracket");
654 return false;
655 }
656
657 return true;
658}
659
660// matrix_template_type
661// : MATRIX
662// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
663//
664bool HlslGrammar::acceptMatrixTemplateType(TType& type)
665{
666 if (! acceptTokenClass(EHTokMatrix))
667 return false;
668
669 if (! acceptTokenClass(EHTokLeftAngle)) {
670 // in HLSL, 'matrix' alone means float4x4.
671 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
672 return true;
673 }
674
675 TBasicType basicType;
676 if (! acceptTemplateType(basicType)) {
677 expected("scalar type");
678 return false;
679 }
680
681 // COMMA
682 if (! acceptTokenClass(EHTokComma)) {
683 expected(",");
684 return false;
685 }
686
687 // integer rows
688 if (! peekTokenClass(EHTokIntConstant)) {
689 expected("literal integer");
690 return false;
691 }
692
693 TIntermTyped* rows;
694 if (! acceptLiteral(rows))
695 return false;
696
697 // COMMA
698 if (! acceptTokenClass(EHTokComma)) {
699 expected(",");
700 return false;
701 }
702
703 // integer cols
704 if (! peekTokenClass(EHTokIntConstant)) {
705 expected("literal integer");
706 return false;
707 }
708
709 TIntermTyped* cols;
710 if (! acceptLiteral(cols))
711 return false;
712
713 new(&type) TType(basicType, EvqTemporary, 0,
714 cols->getAsConstantUnion()->getConstArray()[0].getIConst(),
715 rows->getAsConstantUnion()->getConstArray()[0].getIConst());
716
717 if (!acceptTokenClass(EHTokRightAngle)) {
718 expected("right angle bracket");
719 return false;
720 }
721
722 return true;
723}
724
725
LoopDawg4886f692016-06-29 10:58:58 -0600726// sampler_type
727// : SAMPLER
728// | SAMPLER1D
729// | SAMPLER2D
730// | SAMPLER3D
731// | SAMPLERCUBE
732// | SAMPLERSTATE
733// | SAMPLERCOMPARISONSTATE
734bool HlslGrammar::acceptSamplerType(TType& type)
735{
736 // read sampler type
737 const EHlslTokenClass samplerType = peek();
738
LoopDawga78b0292016-07-19 14:28:05 -0600739 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600740 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600741
LoopDawga78b0292016-07-19 14:28:05 -0600742 bool isShadow = false;
743
LoopDawg4886f692016-06-29 10:58:58 -0600744 switch (samplerType) {
745 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600746 case EHTokSampler1d: /*dim = Esd1D*/; break;
747 case EHTokSampler2d: /*dim = Esd2D*/; break;
748 case EHTokSampler3d: /*dim = Esd3D*/; break;
749 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600750 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600751 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600752 default:
753 return false; // not a sampler declaration
754 }
755
756 advanceToken(); // consume the sampler type keyword
757
758 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600759
760 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600761 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600762
763 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
764
765 return true;
766}
767
768// texture_type
769// | BUFFER
770// | TEXTURE1D
771// | TEXTURE1DARRAY
772// | TEXTURE2D
773// | TEXTURE2DARRAY
774// | TEXTURE3D
775// | TEXTURECUBE
776// | TEXTURECUBEARRAY
777// | TEXTURE2DMS
778// | TEXTURE2DMSARRAY
779bool HlslGrammar::acceptTextureType(TType& type)
780{
781 const EHlslTokenClass textureType = peek();
782
783 TSamplerDim dim = EsdNone;
784 bool array = false;
785 bool ms = false;
786
787 switch (textureType) {
788 case EHTokBuffer: dim = EsdBuffer; break;
789 case EHTokTexture1d: dim = Esd1D; break;
790 case EHTokTexture1darray: dim = Esd1D; array = true; break;
791 case EHTokTexture2d: dim = Esd2D; break;
792 case EHTokTexture2darray: dim = Esd2D; array = true; break;
793 case EHTokTexture3d: dim = Esd3D; break;
794 case EHTokTextureCube: dim = EsdCube; break;
795 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
796 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
797 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
798 default:
799 return false; // not a texture declaration
800 }
801
802 advanceToken(); // consume the texture object keyword
803
804 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
805
806 TIntermTyped* msCount = nullptr;
807
808 // texture type: required for multisample types!
809 if (acceptTokenClass(EHTokLeftAngle)) {
810 if (! acceptType(txType)) {
811 expected("scalar or vector type");
812 return false;
813 }
814
815 const TBasicType basicRetType = txType.getBasicType() ;
816
817 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
818 unimplemented("basic type in texture");
819 return false;
820 }
821
steve-lunargd53f7172016-07-27 15:46:48 -0600822 // Buffers can handle small mats if they fit in 4 components
823 if (dim == EsdBuffer && txType.isMatrix()) {
824 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
825 expected("components < 4 in matrix buffer type");
826 return false;
827 }
828
829 // TODO: except we don't handle it yet...
830 unimplemented("matrix type in buffer");
831 return false;
832 }
833
LoopDawg4886f692016-06-29 10:58:58 -0600834 if (!txType.isScalar() && !txType.isVector()) {
835 expected("scalar or vector type");
836 return false;
837 }
838
839 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
840 // TODO: handle vec2/3 types
841 expected("vector size not yet supported in texture type");
842 return false;
843 }
844
845 if (ms && acceptTokenClass(EHTokComma)) {
846 // read sample count for multisample types, if given
847 if (! peekTokenClass(EHTokIntConstant)) {
848 expected("multisample count");
849 return false;
850 }
851
852 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
853 return false;
854 }
855
856 if (! acceptTokenClass(EHTokRightAngle)) {
857 expected("right angle bracket");
858 return false;
859 }
860 } else if (ms) {
861 expected("texture type for multisample");
862 return false;
863 }
864
865 TArraySizes* arraySizes = nullptr;
866 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
867
868 TSampler sampler;
steve-lunargd53f7172016-07-27 15:46:48 -0600869
870 // Buffers are combined.
871 if (dim == EsdBuffer) {
872 sampler.set(txType.getBasicType(), dim, array);
873 } else {
874 // DX10 textures are separated. TODO: DX9.
875 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
876 }
LoopDawg4886f692016-06-29 10:58:58 -0600877
878 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
879
880 return true;
881}
882
883
John Kessenich87142c72016-03-12 20:24:24 -0700884// If token is for a type, update 'type' with the type information,
885// and return true and advance.
886// Otherwise, return false, and don't advance
887bool HlslGrammar::acceptType(TType& type)
888{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600889 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600890 case EHTokVector:
891 return acceptVectorTemplateType(type);
892 break;
893
894 case EHTokMatrix:
895 return acceptMatrixTemplateType(type);
896 break;
897
LoopDawg4886f692016-06-29 10:58:58 -0600898 case EHTokSampler: // fall through
899 case EHTokSampler1d: // ...
900 case EHTokSampler2d: // ...
901 case EHTokSampler3d: // ...
902 case EHTokSamplerCube: // ...
903 case EHTokSamplerState: // ...
904 case EHTokSamplerComparisonState: // ...
905 return acceptSamplerType(type);
906 break;
907
908 case EHTokBuffer: // fall through
909 case EHTokTexture1d: // ...
910 case EHTokTexture1darray: // ...
911 case EHTokTexture2d: // ...
912 case EHTokTexture2darray: // ...
913 case EHTokTexture3d: // ...
914 case EHTokTextureCube: // ...
915 case EHTokTextureCubearray: // ...
916 case EHTokTexture2DMS: // ...
917 case EHTokTexture2DMSarray: // ...
918 return acceptTextureType(type);
919 break;
920
John Kesseniche6e74942016-06-11 16:43:14 -0600921 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600922 case EHTokCBuffer:
923 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600924 return acceptStruct(type);
925 break;
926
927 case EHTokIdentifier:
928 // An identifier could be for a user-defined type.
929 // Note we cache the symbol table lookup, to save for a later rule
930 // when this is not a type.
931 token.symbol = parseContext.symbolTable.find(*token.string);
932 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
933 type.shallowCopy(token.symbol->getType());
934 advanceToken();
935 return true;
936 } else
937 return false;
938
John Kessenich71351de2016-06-08 12:50:56 -0600939 case EHTokVoid:
940 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700941 break;
John Kessenich71351de2016-06-08 12:50:56 -0600942
John Kessenich87142c72016-03-12 20:24:24 -0700943 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600944 new(&type) TType(EbtFloat);
945 break;
John Kessenich87142c72016-03-12 20:24:24 -0700946 case EHTokFloat1:
947 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600948 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700949 break;
John Kessenich87142c72016-03-12 20:24:24 -0700950 case EHTokFloat2:
951 new(&type) TType(EbtFloat, EvqTemporary, 2);
952 break;
953 case EHTokFloat3:
954 new(&type) TType(EbtFloat, EvqTemporary, 3);
955 break;
956 case EHTokFloat4:
957 new(&type) TType(EbtFloat, EvqTemporary, 4);
958 break;
959
John Kessenich71351de2016-06-08 12:50:56 -0600960 case EHTokDouble:
961 new(&type) TType(EbtDouble);
962 break;
963 case EHTokDouble1:
964 new(&type) TType(EbtDouble);
965 type.makeVector();
966 break;
967 case EHTokDouble2:
968 new(&type) TType(EbtDouble, EvqTemporary, 2);
969 break;
970 case EHTokDouble3:
971 new(&type) TType(EbtDouble, EvqTemporary, 3);
972 break;
973 case EHTokDouble4:
974 new(&type) TType(EbtDouble, EvqTemporary, 4);
975 break;
976
977 case EHTokInt:
978 case EHTokDword:
979 new(&type) TType(EbtInt);
980 break;
981 case EHTokInt1:
982 new(&type) TType(EbtInt);
983 type.makeVector();
984 break;
John Kessenich87142c72016-03-12 20:24:24 -0700985 case EHTokInt2:
986 new(&type) TType(EbtInt, EvqTemporary, 2);
987 break;
988 case EHTokInt3:
989 new(&type) TType(EbtInt, EvqTemporary, 3);
990 break;
991 case EHTokInt4:
992 new(&type) TType(EbtInt, EvqTemporary, 4);
993 break;
994
John Kessenich71351de2016-06-08 12:50:56 -0600995 case EHTokUint:
996 new(&type) TType(EbtUint);
997 break;
998 case EHTokUint1:
999 new(&type) TType(EbtUint);
1000 type.makeVector();
1001 break;
1002 case EHTokUint2:
1003 new(&type) TType(EbtUint, EvqTemporary, 2);
1004 break;
1005 case EHTokUint3:
1006 new(&type) TType(EbtUint, EvqTemporary, 3);
1007 break;
1008 case EHTokUint4:
1009 new(&type) TType(EbtUint, EvqTemporary, 4);
1010 break;
1011
LoopDawg6daaa4f2016-06-23 19:13:48 -06001012
John Kessenich71351de2016-06-08 12:50:56 -06001013 case EHTokBool:
1014 new(&type) TType(EbtBool);
1015 break;
1016 case EHTokBool1:
1017 new(&type) TType(EbtBool);
1018 type.makeVector();
1019 break;
John Kessenich87142c72016-03-12 20:24:24 -07001020 case EHTokBool2:
1021 new(&type) TType(EbtBool, EvqTemporary, 2);
1022 break;
1023 case EHTokBool3:
1024 new(&type) TType(EbtBool, EvqTemporary, 3);
1025 break;
1026 case EHTokBool4:
1027 new(&type) TType(EbtBool, EvqTemporary, 4);
1028 break;
1029
John Kessenich0133c122016-05-20 12:17:26 -06001030 case EHTokInt1x1:
1031 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1032 break;
1033 case EHTokInt1x2:
1034 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
1035 break;
1036 case EHTokInt1x3:
1037 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
1038 break;
1039 case EHTokInt1x4:
1040 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
1041 break;
1042 case EHTokInt2x1:
1043 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
1044 break;
1045 case EHTokInt2x2:
1046 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1047 break;
1048 case EHTokInt2x3:
1049 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
1050 break;
1051 case EHTokInt2x4:
1052 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
1053 break;
1054 case EHTokInt3x1:
1055 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
1056 break;
1057 case EHTokInt3x2:
1058 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
1059 break;
1060 case EHTokInt3x3:
1061 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1062 break;
1063 case EHTokInt3x4:
1064 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
1065 break;
1066 case EHTokInt4x1:
1067 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
1068 break;
1069 case EHTokInt4x2:
1070 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
1071 break;
1072 case EHTokInt4x3:
1073 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
1074 break;
1075 case EHTokInt4x4:
1076 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1077 break;
1078
John Kessenich71351de2016-06-08 12:50:56 -06001079 case EHTokUint1x1:
1080 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1081 break;
1082 case EHTokUint1x2:
1083 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
1084 break;
1085 case EHTokUint1x3:
1086 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
1087 break;
1088 case EHTokUint1x4:
1089 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
1090 break;
1091 case EHTokUint2x1:
1092 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
1093 break;
1094 case EHTokUint2x2:
1095 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1096 break;
1097 case EHTokUint2x3:
1098 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
1099 break;
1100 case EHTokUint2x4:
1101 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
1102 break;
1103 case EHTokUint3x1:
1104 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
1105 break;
1106 case EHTokUint3x2:
1107 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
1108 break;
1109 case EHTokUint3x3:
1110 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1111 break;
1112 case EHTokUint3x4:
1113 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
1114 break;
1115 case EHTokUint4x1:
1116 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
1117 break;
1118 case EHTokUint4x2:
1119 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
1120 break;
1121 case EHTokUint4x3:
1122 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
1123 break;
1124 case EHTokUint4x4:
1125 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1126 break;
1127
1128 case EHTokBool1x1:
1129 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1130 break;
1131 case EHTokBool1x2:
1132 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
1133 break;
1134 case EHTokBool1x3:
1135 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
1136 break;
1137 case EHTokBool1x4:
1138 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
1139 break;
1140 case EHTokBool2x1:
1141 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
1142 break;
1143 case EHTokBool2x2:
1144 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1145 break;
1146 case EHTokBool2x3:
1147 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
1148 break;
1149 case EHTokBool2x4:
1150 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
1151 break;
1152 case EHTokBool3x1:
1153 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
1154 break;
1155 case EHTokBool3x2:
1156 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
1157 break;
1158 case EHTokBool3x3:
1159 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1160 break;
1161 case EHTokBool3x4:
1162 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
1163 break;
1164 case EHTokBool4x1:
1165 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
1166 break;
1167 case EHTokBool4x2:
1168 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
1169 break;
1170 case EHTokBool4x3:
1171 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
1172 break;
1173 case EHTokBool4x4:
1174 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1175 break;
1176
John Kessenich0133c122016-05-20 12:17:26 -06001177 case EHTokFloat1x1:
1178 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1179 break;
1180 case EHTokFloat1x2:
1181 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
1182 break;
1183 case EHTokFloat1x3:
1184 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
1185 break;
1186 case EHTokFloat1x4:
1187 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
1188 break;
1189 case EHTokFloat2x1:
1190 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
1191 break;
John Kessenich87142c72016-03-12 20:24:24 -07001192 case EHTokFloat2x2:
1193 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1194 break;
1195 case EHTokFloat2x3:
1196 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
1197 break;
1198 case EHTokFloat2x4:
1199 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
1200 break;
John Kessenich0133c122016-05-20 12:17:26 -06001201 case EHTokFloat3x1:
1202 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
1203 break;
John Kessenich87142c72016-03-12 20:24:24 -07001204 case EHTokFloat3x2:
1205 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
1206 break;
1207 case EHTokFloat3x3:
1208 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1209 break;
1210 case EHTokFloat3x4:
1211 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
1212 break;
John Kessenich0133c122016-05-20 12:17:26 -06001213 case EHTokFloat4x1:
1214 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
1215 break;
John Kessenich87142c72016-03-12 20:24:24 -07001216 case EHTokFloat4x2:
1217 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
1218 break;
1219 case EHTokFloat4x3:
1220 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
1221 break;
1222 case EHTokFloat4x4:
1223 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1224 break;
1225
John Kessenich0133c122016-05-20 12:17:26 -06001226 case EHTokDouble1x1:
1227 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1228 break;
1229 case EHTokDouble1x2:
1230 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
1231 break;
1232 case EHTokDouble1x3:
1233 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
1234 break;
1235 case EHTokDouble1x4:
1236 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
1237 break;
1238 case EHTokDouble2x1:
1239 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
1240 break;
1241 case EHTokDouble2x2:
1242 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1243 break;
1244 case EHTokDouble2x3:
1245 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
1246 break;
1247 case EHTokDouble2x4:
1248 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
1249 break;
1250 case EHTokDouble3x1:
1251 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
1252 break;
1253 case EHTokDouble3x2:
1254 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
1255 break;
1256 case EHTokDouble3x3:
1257 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1258 break;
1259 case EHTokDouble3x4:
1260 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
1261 break;
1262 case EHTokDouble4x1:
1263 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
1264 break;
1265 case EHTokDouble4x2:
1266 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
1267 break;
1268 case EHTokDouble4x3:
1269 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
1270 break;
1271 case EHTokDouble4x4:
1272 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1273 break;
1274
John Kessenich87142c72016-03-12 20:24:24 -07001275 default:
1276 return false;
1277 }
1278
1279 advanceToken();
1280
1281 return true;
1282}
1283
John Kesseniche6e74942016-06-11 16:43:14 -06001284// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001285// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1286// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1287//
1288// struct_type
1289// : STRUCT
1290// | CBUFFER
1291// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001292//
1293bool HlslGrammar::acceptStruct(TType& type)
1294{
John Kessenichb804de62016-09-05 12:19:18 -06001295 // This storage qualifier will tell us whether it's an AST
1296 // block type or just a generic structure type.
1297 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001298
1299 // CBUFFER
1300 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001301 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001302 // TBUFFER
1303 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001304 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001305 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001306 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001307 return false;
1308
1309 // IDENTIFIER
1310 TString structName = "";
1311 if (peekTokenClass(EHTokIdentifier)) {
1312 structName = *token.string;
1313 advanceToken();
1314 }
1315
John Kessenich3d157c52016-07-25 16:05:33 -06001316 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001317 TQualifier postDeclQualifier;
1318 postDeclQualifier.clear();
1319 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001320
John Kesseniche6e74942016-06-11 16:43:14 -06001321 // LEFT_BRACE
1322 if (! acceptTokenClass(EHTokLeftBrace)) {
1323 expected("{");
1324 return false;
1325 }
1326
1327 // struct_declaration_list
1328 TTypeList* typeList;
1329 if (! acceptStructDeclarationList(typeList)) {
1330 expected("struct member declarations");
1331 return false;
1332 }
1333
1334 // RIGHT_BRACE
1335 if (! acceptTokenClass(EHTokRightBrace)) {
1336 expected("}");
1337 return false;
1338 }
1339
1340 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001341 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001342 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001343 else {
John Kessenich7735b942016-09-05 12:40:06 -06001344 postDeclQualifier.storage = storageQualifier;
1345 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001346 }
John Kesseniche6e74942016-06-11 16:43:14 -06001347
John Kessenich3d157c52016-07-25 16:05:33 -06001348 // If it was named, which means the type can be reused later, add
1349 // it to the symbol table. (Unless it's a block, in which
1350 // case the name is not a type.)
1351 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001352 TVariable* userTypeDef = new TVariable(&structName, type, true);
1353 if (! parseContext.symbolTable.insert(*userTypeDef))
1354 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1355 }
1356
1357 return true;
1358}
1359
1360// struct_declaration_list
1361// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1362//
1363// struct_declaration
1364// : fully_specified_type struct_declarator COMMA struct_declarator ...
1365//
1366// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001367// : IDENTIFIER post_decls
1368// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001369//
1370bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1371{
1372 typeList = new TTypeList();
1373
1374 do {
1375 // success on seeing the RIGHT_BRACE coming up
1376 if (peekTokenClass(EHTokRightBrace))
1377 return true;
1378
1379 // struct_declaration
1380
1381 // fully_specified_type
1382 TType memberType;
1383 if (! acceptFullySpecifiedType(memberType)) {
1384 expected("member type");
1385 return false;
1386 }
1387
1388 // struct_declarator COMMA struct_declarator ...
1389 do {
1390 // peek IDENTIFIER
1391 if (! peekTokenClass(EHTokIdentifier)) {
1392 expected("member name");
1393 return false;
1394 }
1395
1396 // add it to the list of members
1397 TTypeLoc member = { new TType(EbtVoid), token.loc };
1398 member.type->shallowCopy(memberType);
1399 member.type->setFieldName(*token.string);
1400 typeList->push_back(member);
1401
1402 // accept IDENTIFIER
1403 advanceToken();
1404
1405 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001406 TArraySizes* arraySizes = nullptr;
1407 acceptArraySpecifier(arraySizes);
1408 if (arraySizes)
1409 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001410
John Kessenich7735b942016-09-05 12:40:06 -06001411 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001412
John Kesseniche6e74942016-06-11 16:43:14 -06001413 // success on seeing the SEMICOLON coming up
1414 if (peekTokenClass(EHTokSemicolon))
1415 break;
1416
1417 // COMMA
1418 if (! acceptTokenClass(EHTokComma)) {
1419 expected(",");
1420 return false;
1421 }
1422
1423 } while (true);
1424
1425 // SEMI_COLON
1426 if (! acceptTokenClass(EHTokSemicolon)) {
1427 expected(";");
1428 return false;
1429 }
1430
1431 } while (true);
1432}
1433
John Kessenich5f934b02016-03-13 17:58:25 -06001434// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001435// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001436// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001437//
1438bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1439{
John Kessenich078d7f22016-03-14 10:02:11 -06001440 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001441 if (! acceptTokenClass(EHTokLeftParen))
1442 return false;
1443
John Kessenich71351de2016-06-08 12:50:56 -06001444 // VOID RIGHT_PAREN
1445 if (! acceptTokenClass(EHTokVoid)) {
1446 do {
1447 // parameter_declaration
1448 if (! acceptParameterDeclaration(function))
1449 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001450
John Kessenich71351de2016-06-08 12:50:56 -06001451 // COMMA
1452 if (! acceptTokenClass(EHTokComma))
1453 break;
1454 } while (true);
1455 }
John Kessenich5f934b02016-03-13 17:58:25 -06001456
John Kessenich078d7f22016-03-14 10:02:11 -06001457 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001458 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001459 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001460 return false;
1461 }
1462
1463 return true;
1464}
1465
1466// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001467// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001468// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001469//
1470bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1471{
1472 // fully_specified_type
1473 TType* type = new TType;
1474 if (! acceptFullySpecifiedType(*type))
1475 return false;
1476
1477 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001478 HlslToken idToken;
1479 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001480
John Kessenich19b92ff2016-06-19 11:50:34 -06001481 // array_specifier
1482 TArraySizes* arraySizes = nullptr;
1483 acceptArraySpecifier(arraySizes);
1484 if (arraySizes)
1485 type->newArraySizes(*arraySizes);
1486
1487 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001488 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001489
John Kessenich5aa59e22016-06-17 15:50:47 -06001490 parseContext.paramFix(*type);
1491
John Kessenichaecd4972016-03-14 10:46:34 -06001492 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001493 function.addParameter(param);
1494
1495 return true;
1496}
1497
1498// Do the work to create the function definition in addition to
1499// parsing the body (compound_statement).
1500bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1501{
John Kessenicha3051662016-09-02 19:13:36 -06001502 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001503 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001504
John Kessenich077e0522016-06-09 02:02:17 -06001505 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001506 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001507
1508 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001509 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001510 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001511 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001512 return true;
1513 }
1514
1515 return false;
1516}
1517
John Kessenich0d2b6de2016-06-05 11:23:11 -06001518// Accept an expression with parenthesis around it, where
1519// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001520// syntactically required ones like in "if ( expression )".
1521//
1522// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001523//
1524// Note this one is not set up to be speculative; as it gives
1525// errors if not found.
1526//
1527bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1528{
1529 // LEFT_PAREN
1530 if (! acceptTokenClass(EHTokLeftParen))
1531 expected("(");
1532
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001533 bool decl = false;
1534 TIntermNode* declNode = nullptr;
1535 decl = acceptControlDeclaration(declNode);
1536 if (decl) {
1537 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1538 expected("initialized declaration");
1539 return false;
1540 } else
1541 expression = declNode->getAsTyped();
1542 } else {
1543 // no declaration
1544 if (! acceptExpression(expression)) {
1545 expected("expression");
1546 return false;
1547 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001548 }
1549
1550 // RIGHT_PAREN
1551 if (! acceptTokenClass(EHTokRightParen))
1552 expected(")");
1553
1554 return true;
1555}
1556
John Kessenich34fb0362016-05-03 23:17:20 -06001557// The top-level full expression recognizer.
1558//
John Kessenich87142c72016-03-12 20:24:24 -07001559// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001560// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001561//
1562bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1563{
LoopDawgef764a22016-06-03 09:17:51 -06001564 node = nullptr;
1565
John Kessenich34fb0362016-05-03 23:17:20 -06001566 // assignment_expression
1567 if (! acceptAssignmentExpression(node))
1568 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001569
John Kessenich34fb0362016-05-03 23:17:20 -06001570 if (! peekTokenClass(EHTokComma))
1571 return true;
1572
1573 do {
1574 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001575 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001576 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001577
John Kessenich34fb0362016-05-03 23:17:20 -06001578 // ... assignment_expression
1579 TIntermTyped* rightNode = nullptr;
1580 if (! acceptAssignmentExpression(rightNode)) {
1581 expected("assignment expression");
1582 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001583 }
1584
John Kessenich34fb0362016-05-03 23:17:20 -06001585 node = intermediate.addComma(node, rightNode, loc);
1586
1587 if (! peekTokenClass(EHTokComma))
1588 return true;
1589 } while (true);
1590}
1591
John Kessenich07354242016-07-01 19:58:06 -06001592// initializer
1593// : LEFT_BRACE initializer_list RIGHT_BRACE
1594//
1595// initializer_list
1596// : assignment_expression COMMA assignment_expression COMMA ...
1597//
1598bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1599{
1600 // LEFT_BRACE
1601 if (! acceptTokenClass(EHTokLeftBrace))
1602 return false;
1603
1604 // initializer_list
1605 TSourceLoc loc = token.loc;
1606 node = nullptr;
1607 do {
1608 // assignment_expression
1609 TIntermTyped* expr;
1610 if (! acceptAssignmentExpression(expr)) {
1611 expected("assignment expression in initializer list");
1612 return false;
1613 }
1614 node = intermediate.growAggregate(node, expr, loc);
1615
1616 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001617 if (acceptTokenClass(EHTokComma)) {
1618 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1619 return true;
John Kessenich07354242016-07-01 19:58:06 -06001620 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001621 }
John Kessenich07354242016-07-01 19:58:06 -06001622
1623 // RIGHT_BRACE
1624 if (acceptTokenClass(EHTokRightBrace))
1625 return true;
1626
1627 expected(", or }");
1628 return false;
1629 } while (true);
1630}
1631
John Kessenich34fb0362016-05-03 23:17:20 -06001632// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001633// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001634//
1635// a op (b op (c op d))
1636//
1637// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001638// : initializer
1639// | conditional_expression
1640// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001641//
1642bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1643{
John Kessenich07354242016-07-01 19:58:06 -06001644 // initializer
1645 if (peekTokenClass(EHTokLeftBrace)) {
1646 if (acceptInitializer(node))
1647 return true;
1648
1649 expected("initializer");
1650 return false;
1651 }
1652
John Kessenich00957f82016-07-27 10:39:57 -06001653 // conditional_expression
1654 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001655 return false;
1656
John Kessenich07354242016-07-01 19:58:06 -06001657 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001658 TOperator assignOp = HlslOpMap::assignment(peek());
1659 if (assignOp == EOpNull)
1660 return true;
1661
John Kessenich00957f82016-07-27 10:39:57 -06001662 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001663 TSourceLoc loc = token.loc;
1664 advanceToken();
1665
John Kessenich00957f82016-07-27 10:39:57 -06001666 // conditional_expression assign_op conditional_expression ...
1667 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001668 // gets the right-to-left associativity.
1669 TIntermTyped* rightNode = nullptr;
1670 if (! acceptAssignmentExpression(rightNode)) {
1671 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001672 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001673 }
1674
John Kessenich34fb0362016-05-03 23:17:20 -06001675 node = intermediate.addAssign(assignOp, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001676 if (node == nullptr) {
1677 parseContext.error(loc, "could not create assignment", "", "");
1678 return false;
1679 }
John Kessenich34fb0362016-05-03 23:17:20 -06001680
1681 if (! peekTokenClass(EHTokComma))
1682 return true;
1683
1684 return true;
1685}
1686
John Kessenich00957f82016-07-27 10:39:57 -06001687// Accept a conditional expression, which associates right-to-left,
1688// accomplished by the "true" expression calling down to lower
1689// precedence levels than this level.
1690//
1691// conditional_expression
1692// : binary_expression
1693// | binary_expression QUESTION expression COLON assignment_expression
1694//
1695bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1696{
1697 // binary_expression
1698 if (! acceptBinaryExpression(node, PlLogicalOr))
1699 return false;
1700
1701 if (! acceptTokenClass(EHTokQuestion))
1702 return true;
1703
1704 TIntermTyped* trueNode = nullptr;
1705 if (! acceptExpression(trueNode)) {
1706 expected("expression after ?");
1707 return false;
1708 }
1709 TSourceLoc loc = token.loc;
1710
1711 if (! acceptTokenClass(EHTokColon)) {
1712 expected(":");
1713 return false;
1714 }
1715
1716 TIntermTyped* falseNode = nullptr;
1717 if (! acceptAssignmentExpression(falseNode)) {
1718 expected("expression after :");
1719 return false;
1720 }
1721
1722 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1723
1724 return true;
1725}
1726
John Kessenich34fb0362016-05-03 23:17:20 -06001727// Accept a binary expression, for binary operations that
1728// associate left-to-right. This is, it is implicit, for example
1729//
1730// ((a op b) op c) op d
1731//
1732// binary_expression
1733// : expression op expression op expression ...
1734//
1735// where 'expression' is the next higher level in precedence.
1736//
1737bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1738{
1739 if (precedenceLevel > PlMul)
1740 return acceptUnaryExpression(node);
1741
1742 // assignment_expression
1743 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1744 return false;
1745
John Kessenich34fb0362016-05-03 23:17:20 -06001746 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001747 TOperator op = HlslOpMap::binary(peek());
1748 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1749 if (tokenLevel < precedenceLevel)
1750 return true;
1751
John Kessenich34fb0362016-05-03 23:17:20 -06001752 // ... op
1753 TSourceLoc loc = token.loc;
1754 advanceToken();
1755
1756 // ... expression
1757 TIntermTyped* rightNode = nullptr;
1758 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1759 expected("expression");
1760 return false;
1761 }
1762
1763 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001764 if (node == nullptr) {
1765 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1766 return false;
1767 }
John Kessenich34fb0362016-05-03 23:17:20 -06001768 } while (true);
1769}
1770
1771// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001772// : (type) unary_expression
1773// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001774// | - unary_expression
1775// | ! unary_expression
1776// | ~ unary_expression
1777// | ++ unary_expression
1778// | -- unary_expression
1779// | postfix_expression
1780//
1781bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1782{
John Kessenich1cc1a282016-06-03 16:55:49 -06001783 // (type) unary_expression
1784 // Have to look two steps ahead, because this could be, e.g., a
1785 // postfix_expression instead, since that also starts with at "(".
1786 if (acceptTokenClass(EHTokLeftParen)) {
1787 TType castType;
1788 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001789 if (acceptTokenClass(EHTokRightParen)) {
1790 // We've matched "(type)" now, get the expression to cast
1791 TSourceLoc loc = token.loc;
1792 if (! acceptUnaryExpression(node))
1793 return false;
1794
1795 // Hook it up like a constructor
1796 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1797 if (constructorFunction == nullptr) {
1798 expected("type that can be constructed");
1799 return false;
1800 }
1801 TIntermTyped* arguments = nullptr;
1802 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1803 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1804
1805 return true;
1806 } else {
1807 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
1808 // the '(int' part. We must back up twice.
1809 recedeToken();
1810 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06001811 }
John Kessenich1cc1a282016-06-03 16:55:49 -06001812 } else {
1813 // This isn't a type cast, but it still started "(", so if it is a
1814 // unary expression, it can only be a postfix_expression, so try that.
1815 // Back it up first.
1816 recedeToken();
1817 return acceptPostfixExpression(node);
1818 }
1819 }
1820
1821 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001822 TOperator unaryOp = HlslOpMap::preUnary(peek());
1823
John Kessenich1cc1a282016-06-03 16:55:49 -06001824 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001825 if (unaryOp == EOpNull)
1826 return acceptPostfixExpression(node);
1827
1828 // op unary_expression
1829 TSourceLoc loc = token.loc;
1830 advanceToken();
1831 if (! acceptUnaryExpression(node))
1832 return false;
1833
1834 // + is a no-op
1835 if (unaryOp == EOpAdd)
1836 return true;
1837
1838 node = intermediate.addUnaryMath(unaryOp, node, loc);
1839
1840 return node != nullptr;
1841}
1842
1843// postfix_expression
1844// : LEFT_PAREN expression RIGHT_PAREN
1845// | literal
1846// | constructor
1847// | identifier
1848// | function_call
1849// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1850// | postfix_expression DOT IDENTIFIER
1851// | postfix_expression INC_OP
1852// | postfix_expression DEC_OP
1853//
1854bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1855{
1856 // Not implemented as self-recursive:
1857 // The logical "right recursion" is done with an loop at the end
1858
1859 // idToken will pick up either a variable or a function name in a function call
1860 HlslToken idToken;
1861
John Kessenich21472ae2016-06-04 11:46:33 -06001862 // Find something before the postfix operations, as they can't operate
1863 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001864 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001865 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001866 if (! acceptExpression(node)) {
1867 expected("expression");
1868 return false;
1869 }
1870 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001871 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001872 return false;
1873 }
John Kessenich34fb0362016-05-03 23:17:20 -06001874 } else if (acceptLiteral(node)) {
1875 // literal (nothing else to do yet), go on to the
1876 } else if (acceptConstructor(node)) {
1877 // constructor (nothing else to do yet)
1878 } else if (acceptIdentifier(idToken)) {
1879 // identifier or function_call name
1880 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001881 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001882 } else if (acceptFunctionCall(idToken, node)) {
1883 // function_call (nothing else to do yet)
1884 } else {
1885 expected("function call arguments");
1886 return false;
1887 }
John Kessenich21472ae2016-06-04 11:46:33 -06001888 } else {
1889 // nothing found, can't post operate
1890 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001891 }
1892
John Kessenich21472ae2016-06-04 11:46:33 -06001893 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001894 do {
1895 TSourceLoc loc = token.loc;
1896 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001897
John Kessenich34fb0362016-05-03 23:17:20 -06001898 // Consume only a valid post-unary operator, otherwise we are done.
1899 switch (postOp) {
1900 case EOpIndexDirectStruct:
1901 case EOpIndexIndirect:
1902 case EOpPostIncrement:
1903 case EOpPostDecrement:
1904 advanceToken();
1905 break;
1906 default:
1907 return true;
1908 }
John Kessenich87142c72016-03-12 20:24:24 -07001909
John Kessenich34fb0362016-05-03 23:17:20 -06001910 // We have a valid post-unary operator, process it.
1911 switch (postOp) {
1912 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001913 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001914 // DOT IDENTIFIER
1915 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001916 HlslToken field;
1917 if (! acceptIdentifier(field)) {
1918 expected("swizzle or member");
1919 return false;
1920 }
LoopDawg4886f692016-06-29 10:58:58 -06001921
1922 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001923 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001924
1925 // In the event of a method node, we look for an open paren and accept the function call.
1926 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1927 if (! acceptFunctionCall(field, node, base)) {
1928 expected("function parameters");
1929 return false;
1930 }
1931 }
1932
John Kessenich34fb0362016-05-03 23:17:20 -06001933 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001934 }
John Kessenich34fb0362016-05-03 23:17:20 -06001935 case EOpIndexIndirect:
1936 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001937 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001938 TIntermTyped* indexNode = nullptr;
1939 if (! acceptExpression(indexNode) ||
1940 ! peekTokenClass(EHTokRightBracket)) {
1941 expected("expression followed by ']'");
1942 return false;
1943 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001944 advanceToken();
1945 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1946 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001947 }
1948 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001949 // INC_OP
1950 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001951 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001952 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001953 node = intermediate.addUnaryMath(postOp, node, loc);
1954 break;
1955 default:
1956 assert(0);
1957 break;
1958 }
1959 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001960}
1961
John Kessenichd016be12016-03-13 11:24:20 -06001962// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001963// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001964//
1965bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1966{
1967 // type
1968 TType type;
1969 if (acceptType(type)) {
1970 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1971 if (constructorFunction == nullptr)
1972 return false;
1973
1974 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001975 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001976 if (! acceptArguments(constructorFunction, arguments)) {
1977 expected("constructor arguments");
1978 return false;
1979 }
1980
1981 // hook it up
1982 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1983
1984 return true;
1985 }
1986
1987 return false;
1988}
1989
John Kessenich34fb0362016-05-03 23:17:20 -06001990// The function_call identifier was already recognized, and passed in as idToken.
1991//
1992// function_call
1993// : [idToken] arguments
1994//
LoopDawg4886f692016-06-29 10:58:58 -06001995bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06001996{
John Kessenich4678ca92016-05-13 09:33:42 -06001997 // arguments
1998 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1999 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002000
2001 // methods have an implicit first argument of the calling object.
2002 if (base != nullptr)
2003 parseContext.handleFunctionArgument(function, arguments, base);
2004
John Kessenich4678ca92016-05-13 09:33:42 -06002005 if (! acceptArguments(function, arguments))
2006 return false;
2007
2008 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2009
2010 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002011}
2012
John Kessenich87142c72016-03-12 20:24:24 -07002013// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002014// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002015//
John Kessenichd016be12016-03-13 11:24:20 -06002016// The arguments are pushed onto the 'function' argument list and
2017// onto the 'arguments' aggregate.
2018//
John Kessenich4678ca92016-05-13 09:33:42 -06002019bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002020{
John Kessenich078d7f22016-03-14 10:02:11 -06002021 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002022 if (! acceptTokenClass(EHTokLeftParen))
2023 return false;
2024
2025 do {
John Kessenichd016be12016-03-13 11:24:20 -06002026 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002027 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002028 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002029 break;
John Kessenichd016be12016-03-13 11:24:20 -06002030
2031 // hook it up
2032 parseContext.handleFunctionArgument(function, arguments, arg);
2033
John Kessenich078d7f22016-03-14 10:02:11 -06002034 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002035 if (! acceptTokenClass(EHTokComma))
2036 break;
2037 } while (true);
2038
John Kessenich078d7f22016-03-14 10:02:11 -06002039 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002040 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002041 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002042 return false;
2043 }
2044
2045 return true;
2046}
2047
2048bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2049{
2050 switch (token.tokenClass) {
2051 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002052 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002053 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002054 case EHTokUintConstant:
2055 node = intermediate.addConstantUnion(token.u, token.loc, true);
2056 break;
John Kessenich87142c72016-03-12 20:24:24 -07002057 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002058 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002059 break;
2060 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002061 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002062 break;
2063 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002064 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002065 break;
2066
2067 default:
2068 return false;
2069 }
2070
2071 advanceToken();
2072
2073 return true;
2074}
2075
John Kessenich5f934b02016-03-13 17:58:25 -06002076// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002077// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002078//
John Kessenich21472ae2016-06-04 11:46:33 -06002079bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002080{
John Kessenich21472ae2016-06-04 11:46:33 -06002081 TIntermAggregate* compoundStatement = nullptr;
2082
John Kessenich34fb0362016-05-03 23:17:20 -06002083 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002084 if (! acceptTokenClass(EHTokLeftBrace))
2085 return false;
2086
2087 // statement statement ...
2088 TIntermNode* statement = nullptr;
2089 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002090 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2091 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2092 branch->getFlowOp() == EOpDefault)) {
2093 // hook up individual subsequences within a switch statement
2094 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2095 compoundStatement = nullptr;
2096 } else {
2097 // hook it up to the growing compound statement
2098 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2099 }
John Kessenich5f934b02016-03-13 17:58:25 -06002100 }
John Kessenich34fb0362016-05-03 23:17:20 -06002101 if (compoundStatement)
2102 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002103
John Kessenich21472ae2016-06-04 11:46:33 -06002104 retStatement = compoundStatement;
2105
John Kessenich34fb0362016-05-03 23:17:20 -06002106 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002107 return acceptTokenClass(EHTokRightBrace);
2108}
2109
John Kessenich0d2b6de2016-06-05 11:23:11 -06002110bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2111{
2112 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002113 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002114 parseContext.popScope();
2115
2116 return result;
2117}
2118
John Kessenich077e0522016-06-09 02:02:17 -06002119bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002120{
John Kessenich077e0522016-06-09 02:02:17 -06002121 parseContext.pushScope();
2122 bool result = acceptCompoundStatement(statement);
2123 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002124
2125 return result;
2126}
2127
John Kessenich5f934b02016-03-13 17:58:25 -06002128// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002129// : attributes attributed_statement
2130//
2131// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002132// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002133// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002134// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002135// | declaration_statement
2136// | selection_statement
2137// | switch_statement
2138// | case_label
2139// | iteration_statement
2140// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002141//
2142bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2143{
John Kessenich21472ae2016-06-04 11:46:33 -06002144 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002145
John Kessenich21472ae2016-06-04 11:46:33 -06002146 // attributes
2147 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002148
John Kessenich21472ae2016-06-04 11:46:33 -06002149 // attributed_statement
2150 switch (peek()) {
2151 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002152 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002153
John Kessenich21472ae2016-06-04 11:46:33 -06002154 case EHTokIf:
2155 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002156
John Kessenich21472ae2016-06-04 11:46:33 -06002157 case EHTokSwitch:
2158 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002159
John Kessenich21472ae2016-06-04 11:46:33 -06002160 case EHTokFor:
2161 case EHTokDo:
2162 case EHTokWhile:
2163 return acceptIterationStatement(statement);
2164
2165 case EHTokContinue:
2166 case EHTokBreak:
2167 case EHTokDiscard:
2168 case EHTokReturn:
2169 return acceptJumpStatement(statement);
2170
2171 case EHTokCase:
2172 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002173 case EHTokDefault:
2174 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002175
2176 case EHTokSemicolon:
2177 return acceptTokenClass(EHTokSemicolon);
2178
2179 case EHTokRightBrace:
2180 // Performance: not strictly necessary, but stops a bunch of hunting early,
2181 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002182 return false;
2183
John Kessenich21472ae2016-06-04 11:46:33 -06002184 default:
2185 {
2186 // declaration
2187 if (acceptDeclaration(statement))
2188 return true;
2189
2190 // expression
2191 TIntermTyped* node;
2192 if (acceptExpression(node))
2193 statement = node;
2194 else
2195 return false;
2196
2197 // SEMICOLON (following an expression)
2198 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002199 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002200 return false;
2201 }
2202 }
2203 }
2204
John Kessenich5f934b02016-03-13 17:58:25 -06002205 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002206}
2207
John Kessenich21472ae2016-06-04 11:46:33 -06002208// attributes
2209// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2210//
2211// attribute:
2212// : UNROLL
2213// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2214// | FASTOPT
2215// | ALLOW_UAV_CONDITION
2216// | BRANCH
2217// | FLATTEN
2218// | FORCECASE
2219// | CALL
2220//
2221void HlslGrammar::acceptAttributes()
2222{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002223 // For now, accept the [ XXX(X) ] syntax, but drop.
2224 // TODO: subset to correct set? Pass on?
2225 do {
2226 // LEFT_BRACKET?
2227 if (! acceptTokenClass(EHTokLeftBracket))
2228 return;
2229
2230 // attribute
2231 if (peekTokenClass(EHTokIdentifier)) {
2232 // 'token.string' is the attribute
2233 advanceToken();
2234 } else if (! peekTokenClass(EHTokRightBracket)) {
2235 expected("identifier");
2236 advanceToken();
2237 }
2238
2239 // (x)
2240 if (acceptTokenClass(EHTokLeftParen)) {
2241 TIntermTyped* node;
2242 if (! acceptLiteral(node))
2243 expected("literal");
2244 // 'node' has the literal in it
2245 if (! acceptTokenClass(EHTokRightParen))
2246 expected(")");
2247 }
2248
2249 // RIGHT_BRACKET
2250 if (acceptTokenClass(EHTokRightBracket))
2251 continue;
2252
2253 expected("]");
2254 return;
2255
2256 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002257}
2258
John Kessenich0d2b6de2016-06-05 11:23:11 -06002259// selection_statement
2260// : IF LEFT_PAREN expression RIGHT_PAREN statement
2261// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2262//
John Kessenich21472ae2016-06-04 11:46:33 -06002263bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2264{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002265 TSourceLoc loc = token.loc;
2266
2267 // IF
2268 if (! acceptTokenClass(EHTokIf))
2269 return false;
2270
2271 // so that something declared in the condition is scoped to the lifetimes
2272 // of the then-else statements
2273 parseContext.pushScope();
2274
2275 // LEFT_PAREN expression RIGHT_PAREN
2276 TIntermTyped* condition;
2277 if (! acceptParenExpression(condition))
2278 return false;
2279
2280 // create the child statements
2281 TIntermNodePair thenElse = { nullptr, nullptr };
2282
2283 // then statement
2284 if (! acceptScopedStatement(thenElse.node1)) {
2285 expected("then statement");
2286 return false;
2287 }
2288
2289 // ELSE
2290 if (acceptTokenClass(EHTokElse)) {
2291 // else statement
2292 if (! acceptScopedStatement(thenElse.node2)) {
2293 expected("else statement");
2294 return false;
2295 }
2296 }
2297
2298 // Put the pieces together
2299 statement = intermediate.addSelection(condition, thenElse, loc);
2300 parseContext.popScope();
2301
2302 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002303}
2304
John Kessenichd02dc5d2016-07-01 00:04:11 -06002305// switch_statement
2306// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2307//
John Kessenich21472ae2016-06-04 11:46:33 -06002308bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2309{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002310 // SWITCH
2311 TSourceLoc loc = token.loc;
2312 if (! acceptTokenClass(EHTokSwitch))
2313 return false;
2314
2315 // LEFT_PAREN expression RIGHT_PAREN
2316 parseContext.pushScope();
2317 TIntermTyped* switchExpression;
2318 if (! acceptParenExpression(switchExpression)) {
2319 parseContext.popScope();
2320 return false;
2321 }
2322
2323 // compound_statement
2324 parseContext.pushSwitchSequence(new TIntermSequence);
2325 bool statementOkay = acceptCompoundStatement(statement);
2326 if (statementOkay)
2327 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2328
2329 parseContext.popSwitchSequence();
2330 parseContext.popScope();
2331
2332 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002333}
2334
John Kessenich119f8f62016-06-05 15:44:07 -06002335// iteration_statement
2336// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2337// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2338// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2339//
2340// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002341bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2342{
John Kessenich119f8f62016-06-05 15:44:07 -06002343 TSourceLoc loc = token.loc;
2344 TIntermTyped* condition = nullptr;
2345
2346 EHlslTokenClass loop = peek();
2347 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2348
2349 // WHILE or DO or FOR
2350 advanceToken();
2351
2352 switch (loop) {
2353 case EHTokWhile:
2354 // so that something declared in the condition is scoped to the lifetime
2355 // of the while sub-statement
2356 parseContext.pushScope();
2357 parseContext.nestLooping();
2358
2359 // LEFT_PAREN condition RIGHT_PAREN
2360 if (! acceptParenExpression(condition))
2361 return false;
2362
2363 // statement
2364 if (! acceptScopedStatement(statement)) {
2365 expected("while sub-statement");
2366 return false;
2367 }
2368
2369 parseContext.unnestLooping();
2370 parseContext.popScope();
2371
2372 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2373
2374 return true;
2375
2376 case EHTokDo:
2377 parseContext.nestLooping();
2378
2379 if (! acceptTokenClass(EHTokLeftBrace))
2380 expected("{");
2381
2382 // statement
2383 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2384 expected("do sub-statement");
2385 return false;
2386 }
2387
2388 if (! acceptTokenClass(EHTokRightBrace))
2389 expected("}");
2390
2391 // WHILE
2392 if (! acceptTokenClass(EHTokWhile)) {
2393 expected("while");
2394 return false;
2395 }
2396
2397 // LEFT_PAREN condition RIGHT_PAREN
2398 TIntermTyped* condition;
2399 if (! acceptParenExpression(condition))
2400 return false;
2401
2402 if (! acceptTokenClass(EHTokSemicolon))
2403 expected(";");
2404
2405 parseContext.unnestLooping();
2406
2407 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2408
2409 return true;
2410
2411 case EHTokFor:
2412 {
2413 // LEFT_PAREN
2414 if (! acceptTokenClass(EHTokLeftParen))
2415 expected("(");
2416
2417 // so that something declared in the condition is scoped to the lifetime
2418 // of the for sub-statement
2419 parseContext.pushScope();
2420
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002421 // initializer
2422 TIntermNode* initNode = nullptr;
2423 if (! acceptControlDeclaration(initNode)) {
2424 TIntermTyped* initExpr = nullptr;
2425 acceptExpression(initExpr);
2426 initNode = initExpr;
2427 }
2428 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002429 if (! acceptTokenClass(EHTokSemicolon))
2430 expected(";");
2431
2432 parseContext.nestLooping();
2433
2434 // condition SEMI_COLON
2435 acceptExpression(condition);
2436 if (! acceptTokenClass(EHTokSemicolon))
2437 expected(";");
2438
2439 // iterator SEMI_COLON
2440 TIntermTyped* iterator = nullptr;
2441 acceptExpression(iterator);
2442 if (! acceptTokenClass(EHTokRightParen))
2443 expected(")");
2444
2445 // statement
2446 if (! acceptScopedStatement(statement)) {
2447 expected("for sub-statement");
2448 return false;
2449 }
2450
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002451 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002452
2453 parseContext.popScope();
2454 parseContext.unnestLooping();
2455
2456 return true;
2457 }
2458
2459 default:
2460 return false;
2461 }
John Kessenich21472ae2016-06-04 11:46:33 -06002462}
2463
2464// jump_statement
2465// : CONTINUE SEMICOLON
2466// | BREAK SEMICOLON
2467// | DISCARD SEMICOLON
2468// | RETURN SEMICOLON
2469// | RETURN expression SEMICOLON
2470//
2471bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2472{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002473 EHlslTokenClass jump = peek();
2474 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002475 case EHTokContinue:
2476 case EHTokBreak:
2477 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002478 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002479 advanceToken();
2480 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002481 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002482 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002483 return false;
2484 }
John Kessenich21472ae2016-06-04 11:46:33 -06002485
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002486 switch (jump) {
2487 case EHTokContinue:
2488 statement = intermediate.addBranch(EOpContinue, token.loc);
2489 break;
2490 case EHTokBreak:
2491 statement = intermediate.addBranch(EOpBreak, token.loc);
2492 break;
2493 case EHTokDiscard:
2494 statement = intermediate.addBranch(EOpKill, token.loc);
2495 break;
2496
2497 case EHTokReturn:
2498 {
2499 // expression
2500 TIntermTyped* node;
2501 if (acceptExpression(node)) {
2502 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002503 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002504 } else
2505 statement = intermediate.addBranch(EOpReturn, token.loc);
2506 break;
2507 }
2508
2509 default:
2510 assert(0);
2511 return false;
2512 }
2513
2514 // SEMICOLON
2515 if (! acceptTokenClass(EHTokSemicolon))
2516 expected(";");
2517
2518 return true;
2519}
John Kessenich21472ae2016-06-04 11:46:33 -06002520
John Kessenichd02dc5d2016-07-01 00:04:11 -06002521// case_label
2522// : CASE expression COLON
2523//
John Kessenich21472ae2016-06-04 11:46:33 -06002524bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2525{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002526 TSourceLoc loc = token.loc;
2527 if (! acceptTokenClass(EHTokCase))
2528 return false;
2529
2530 TIntermTyped* expression;
2531 if (! acceptExpression(expression)) {
2532 expected("case expression");
2533 return false;
2534 }
2535
2536 if (! acceptTokenClass(EHTokColon)) {
2537 expected(":");
2538 return false;
2539 }
2540
2541 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2542
2543 return true;
2544}
2545
2546// default_label
2547// : DEFAULT COLON
2548//
2549bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2550{
2551 TSourceLoc loc = token.loc;
2552 if (! acceptTokenClass(EHTokDefault))
2553 return false;
2554
2555 if (! acceptTokenClass(EHTokColon)) {
2556 expected(":");
2557 return false;
2558 }
2559
2560 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2561
2562 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002563}
2564
John Kessenich19b92ff2016-06-19 11:50:34 -06002565// array_specifier
2566// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
2567//
2568void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2569{
2570 arraySizes = nullptr;
2571
2572 if (! acceptTokenClass(EHTokLeftBracket))
2573 return;
2574
2575 TSourceLoc loc = token.loc;
2576 TIntermTyped* sizeExpr;
2577 if (! acceptAssignmentExpression(sizeExpr)) {
2578 expected("array-sizing expression");
2579 return;
2580 }
2581
2582 if (! acceptTokenClass(EHTokRightBracket)) {
2583 expected("]");
2584 return;
2585 }
2586
2587 TArraySize arraySize;
2588 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2589 arraySizes = new TArraySizes;
2590 arraySizes->addInnerSize(arraySize);
2591}
2592
John Kessenich630dd7d2016-06-12 23:52:12 -06002593// post_decls
John Kessenichb38f0712016-07-30 10:29:54 -06002594// : COLON semantic // optional
2595// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2596// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt RIGHT_PAREN // optional
2597// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002598//
John Kessenich7735b942016-09-05 12:40:06 -06002599void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002600{
John Kessenich630dd7d2016-06-12 23:52:12 -06002601 do {
2602 // COLON
2603 if (acceptTokenClass(EHTokColon)) {
2604 HlslToken idToken;
2605 if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002606 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002607 if (! acceptTokenClass(EHTokLeftParen)) {
2608 expected("(");
2609 return;
2610 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002611 HlslToken locationToken;
2612 if (! acceptIdentifier(locationToken)) {
2613 expected("c[subcomponent][.component]");
2614 return;
2615 }
2616 HlslToken componentToken;
2617 if (acceptTokenClass(EHTokDot)) {
2618 if (! acceptIdentifier(componentToken)) {
2619 expected("component");
2620 return;
2621 }
2622 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002623 if (! acceptTokenClass(EHTokRightParen)) {
2624 expected(")");
2625 break;
2626 }
John Kessenich7735b942016-09-05 12:40:06 -06002627 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002628 } else if (! acceptIdentifier(idToken)) {
2629 expected("semantic or packoffset or register");
2630 return;
2631 } else if (*idToken.string == "register") {
John Kessenichb38f0712016-07-30 10:29:54 -06002632 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002633 if (! acceptTokenClass(EHTokLeftParen)) {
2634 expected("(");
2635 return;
2636 }
John Kessenichb38f0712016-07-30 10:29:54 -06002637 HlslToken registerDesc; // for Type#
2638 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002639 if (! acceptIdentifier(registerDesc)) {
2640 expected("register number description");
2641 return;
2642 }
John Kessenich96e9f472016-07-29 14:28:39 -06002643 if (acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002644 // Then we didn't really see the registerDesc yet, it was
2645 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002646 profile = registerDesc;
2647 if (! acceptIdentifier(registerDesc)) {
2648 expected("register number description");
2649 return;
2650 }
2651 }
John Kessenichb38f0712016-07-30 10:29:54 -06002652 int subComponent = 0;
2653 if (acceptTokenClass(EHTokLeftBracket)) {
2654 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2655 if (! peekTokenClass(EHTokIntConstant)) {
2656 expected("literal integer");
2657 return;
2658 }
2659 subComponent = token.i;
2660 advanceToken();
2661 if (! acceptTokenClass(EHTokRightBracket)) {
2662 expected("]");
2663 break;
2664 }
2665 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002666 if (! acceptTokenClass(EHTokRightParen)) {
2667 expected(")");
2668 break;
2669 }
John Kessenich7735b942016-09-05 12:40:06 -06002670 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent);
John Kessenich630dd7d2016-06-12 23:52:12 -06002671 } else {
2672 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002673 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002674 }
2675 } else if (acceptTokenClass(EHTokLeftAngle)) {
2676 // TODO: process annotations, just accepting them for now
2677 do {
2678 if (peekTokenClass(EHTokNone))
2679 return;
2680 if (acceptTokenClass(EHTokRightAngle))
2681 break;
2682 advanceToken();
2683 } while (true);
2684 } else
2685 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002686
John Kessenich630dd7d2016-06-12 23:52:12 -06002687 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002688}
2689
John Kesseniche01a9bc2016-03-12 20:11:22 -07002690} // end namespace glslang