blob: 0762514589dded85b144940ff5446fde74b9972b [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
John Kessenich34e7ee72016-09-16 17:10:39 -0600438 parseContext.mergeQualifiers(type.getQualifier(), qualifier);
John Kessenich3d157c52016-07-25 16:05:33 -0600439 // 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:
John Kessenich630dd7d2016-06-12 23:52:12 -0600479 qualifier.smooth = true;
480 break;
481 case EHTokCentroid:
482 qualifier.centroid = true;
483 break;
484 case EHTokNointerpolation:
485 qualifier.flat = true;
486 break;
487 case EHTokNoperspective:
488 qualifier.nopersp = true;
489 break;
490 case EHTokSample:
491 qualifier.sample = true;
492 break;
493 case EHTokRowMajor:
494 qualifier.layoutMatrix = ElmRowMajor;
495 break;
496 case EHTokColumnMajor:
497 qualifier.layoutMatrix = ElmColumnMajor;
498 break;
499 case EHTokPrecise:
500 qualifier.noContraction = true;
501 break;
LoopDawg9249c702016-07-12 20:44:32 -0600502 case EHTokIn:
503 qualifier.storage = EvqIn;
504 break;
505 case EHTokOut:
506 qualifier.storage = EvqOut;
507 break;
508 case EHTokInOut:
509 qualifier.storage = EvqInOut;
510 break;
John Kessenichb9e39122016-08-17 10:22:08 -0600511 case EHTokLayout:
512 if (! acceptLayoutQualifierList(qualifier))
513 return false;
514 continue;
John Kessenich630dd7d2016-06-12 23:52:12 -0600515 default:
John Kessenichb9e39122016-08-17 10:22:08 -0600516 return true;
John Kessenich630dd7d2016-06-12 23:52:12 -0600517 }
518 advanceToken();
519 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700520}
521
John Kessenichb9e39122016-08-17 10:22:08 -0600522// layout_qualifier_list
John Kesseniche3218e22016-09-05 14:37:03 -0600523// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
John Kessenichb9e39122016-08-17 10:22:08 -0600524//
525// layout_qualifier
526// : identifier
John Kessenich841db352016-09-02 21:12:23 -0600527// | identifier EQUAL expression
John Kessenichb9e39122016-08-17 10:22:08 -0600528//
529// Zero or more of these, so this can't return false.
530//
531bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
532{
533 if (! acceptTokenClass(EHTokLayout))
534 return false;
535
536 // LEFT_PAREN
537 if (! acceptTokenClass(EHTokLeftParen))
538 return false;
539
540 do {
541 // identifier
542 HlslToken idToken;
543 if (! acceptIdentifier(idToken))
544 break;
545
546 // EQUAL expression
547 if (acceptTokenClass(EHTokAssign)) {
548 TIntermTyped* expr;
549 if (! acceptConditionalExpression(expr)) {
550 expected("expression");
551 return false;
552 }
553 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
554 } else
555 parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
556
557 // COMMA
558 if (! acceptTokenClass(EHTokComma))
559 break;
560 } while (true);
561
562 // RIGHT_PAREN
563 if (! acceptTokenClass(EHTokRightParen)) {
564 expected(")");
565 return false;
566 }
567
568 return true;
569}
570
LoopDawg6daaa4f2016-06-23 19:13:48 -0600571// template_type
572// : FLOAT
573// | DOUBLE
574// | INT
575// | DWORD
576// | UINT
577// | BOOL
578//
579bool HlslGrammar::acceptTemplateType(TBasicType& basicType)
580{
581 switch (peek()) {
582 case EHTokFloat:
583 basicType = EbtFloat;
584 break;
585 case EHTokDouble:
586 basicType = EbtDouble;
587 break;
588 case EHTokInt:
589 case EHTokDword:
590 basicType = EbtInt;
591 break;
592 case EHTokUint:
593 basicType = EbtUint;
594 break;
595 case EHTokBool:
596 basicType = EbtBool;
597 break;
598 default:
599 return false;
600 }
601
602 advanceToken();
603
604 return true;
605}
606
607// vector_template_type
608// : VECTOR
609// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
610//
611bool HlslGrammar::acceptVectorTemplateType(TType& type)
612{
613 if (! acceptTokenClass(EHTokVector))
614 return false;
615
616 if (! acceptTokenClass(EHTokLeftAngle)) {
617 // in HLSL, 'vector' alone means float4.
618 new(&type) TType(EbtFloat, EvqTemporary, 4);
619 return true;
620 }
621
622 TBasicType basicType;
623 if (! acceptTemplateType(basicType)) {
624 expected("scalar type");
625 return false;
626 }
627
628 // COMMA
629 if (! acceptTokenClass(EHTokComma)) {
630 expected(",");
631 return false;
632 }
633
634 // integer
635 if (! peekTokenClass(EHTokIntConstant)) {
636 expected("literal integer");
637 return false;
638 }
639
640 TIntermTyped* vecSize;
641 if (! acceptLiteral(vecSize))
642 return false;
643
644 const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
645
646 new(&type) TType(basicType, EvqTemporary, vecSizeI);
647
648 if (vecSizeI == 1)
649 type.makeVector();
650
651 if (!acceptTokenClass(EHTokRightAngle)) {
652 expected("right angle bracket");
653 return false;
654 }
655
656 return true;
657}
658
659// matrix_template_type
660// : MATRIX
661// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
662//
663bool HlslGrammar::acceptMatrixTemplateType(TType& type)
664{
665 if (! acceptTokenClass(EHTokMatrix))
666 return false;
667
668 if (! acceptTokenClass(EHTokLeftAngle)) {
669 // in HLSL, 'matrix' alone means float4x4.
670 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
671 return true;
672 }
673
674 TBasicType basicType;
675 if (! acceptTemplateType(basicType)) {
676 expected("scalar type");
677 return false;
678 }
679
680 // COMMA
681 if (! acceptTokenClass(EHTokComma)) {
682 expected(",");
683 return false;
684 }
685
686 // integer rows
687 if (! peekTokenClass(EHTokIntConstant)) {
688 expected("literal integer");
689 return false;
690 }
691
692 TIntermTyped* rows;
693 if (! acceptLiteral(rows))
694 return false;
695
696 // COMMA
697 if (! acceptTokenClass(EHTokComma)) {
698 expected(",");
699 return false;
700 }
701
702 // integer cols
703 if (! peekTokenClass(EHTokIntConstant)) {
704 expected("literal integer");
705 return false;
706 }
707
708 TIntermTyped* cols;
709 if (! acceptLiteral(cols))
710 return false;
711
712 new(&type) TType(basicType, EvqTemporary, 0,
steve-lunarg297ae212016-08-24 14:36:13 -0600713 rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
714 cols->getAsConstantUnion()->getConstArray()[0].getIConst());
LoopDawg6daaa4f2016-06-23 19:13:48 -0600715
716 if (!acceptTokenClass(EHTokRightAngle)) {
717 expected("right angle bracket");
718 return false;
719 }
720
721 return true;
722}
723
John Kessenich86f71382016-09-19 20:23:18 -0600724// string_template_type
725// : STRING
726// | STRING identifier LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
727//
728bool HlslGrammar::acceptStringTemplateType(TType& type)
729{
730 // STRING
731 if (! acceptTokenClass(EHTokString))
732 return false;
733
734 // no matter what happens next, we recognized a string type
735 new(&type) TType(EbtString);
736
737 // identifier LEFT_ANGLE, or not?
738 if (! acceptTokenClass(EHTokIdentifier)) {
739 expected("identifier following 'string'");
740 return false;
741 }
742
743 if (! peekTokenClass(EHTokLeftAngle)) {
744 // then it must be the non-template version, back up and let
745 // normal declaration code handle it
746
747 // recede the identifier
748 recedeToken();
749 return true;
750 }
751
752 // move past the LEFT_ANGLE
753 advanceToken();
754
755 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
756 do {
757 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
758 while (acceptTokenClass(EHTokSemicolon))
759 ;
760
761 if (acceptTokenClass(EHTokRightAngle))
762 return true;
763
764 // declaration
765 TIntermNode* node;
766 if (! acceptDeclaration(node)) {
767 expected("declaration in string list");
768 return false;
769 }
770 } while (true);
771}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600772
LoopDawg4886f692016-06-29 10:58:58 -0600773// sampler_type
774// : SAMPLER
775// | SAMPLER1D
776// | SAMPLER2D
777// | SAMPLER3D
778// | SAMPLERCUBE
779// | SAMPLERSTATE
780// | SAMPLERCOMPARISONSTATE
781bool HlslGrammar::acceptSamplerType(TType& type)
782{
783 // read sampler type
784 const EHlslTokenClass samplerType = peek();
785
LoopDawga78b0292016-07-19 14:28:05 -0600786 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600787 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600788
LoopDawga78b0292016-07-19 14:28:05 -0600789 bool isShadow = false;
790
LoopDawg4886f692016-06-29 10:58:58 -0600791 switch (samplerType) {
792 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600793 case EHTokSampler1d: /*dim = Esd1D*/; break;
794 case EHTokSampler2d: /*dim = Esd2D*/; break;
795 case EHTokSampler3d: /*dim = Esd3D*/; break;
796 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600797 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600798 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600799 default:
800 return false; // not a sampler declaration
801 }
802
803 advanceToken(); // consume the sampler type keyword
804
805 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600806
807 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600808 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600809
810 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
811
812 return true;
813}
814
815// texture_type
816// | BUFFER
817// | TEXTURE1D
818// | TEXTURE1DARRAY
819// | TEXTURE2D
820// | TEXTURE2DARRAY
821// | TEXTURE3D
822// | TEXTURECUBE
823// | TEXTURECUBEARRAY
824// | TEXTURE2DMS
825// | TEXTURE2DMSARRAY
826bool HlslGrammar::acceptTextureType(TType& type)
827{
828 const EHlslTokenClass textureType = peek();
829
830 TSamplerDim dim = EsdNone;
831 bool array = false;
832 bool ms = false;
833
834 switch (textureType) {
835 case EHTokBuffer: dim = EsdBuffer; break;
836 case EHTokTexture1d: dim = Esd1D; break;
837 case EHTokTexture1darray: dim = Esd1D; array = true; break;
838 case EHTokTexture2d: dim = Esd2D; break;
839 case EHTokTexture2darray: dim = Esd2D; array = true; break;
840 case EHTokTexture3d: dim = Esd3D; break;
841 case EHTokTextureCube: dim = EsdCube; break;
842 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
843 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
844 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
845 default:
846 return false; // not a texture declaration
847 }
848
849 advanceToken(); // consume the texture object keyword
850
851 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
852
853 TIntermTyped* msCount = nullptr;
854
855 // texture type: required for multisample types!
856 if (acceptTokenClass(EHTokLeftAngle)) {
857 if (! acceptType(txType)) {
858 expected("scalar or vector type");
859 return false;
860 }
861
862 const TBasicType basicRetType = txType.getBasicType() ;
863
864 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
865 unimplemented("basic type in texture");
866 return false;
867 }
868
steve-lunargd53f7172016-07-27 15:46:48 -0600869 // Buffers can handle small mats if they fit in 4 components
870 if (dim == EsdBuffer && txType.isMatrix()) {
871 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
872 expected("components < 4 in matrix buffer type");
873 return false;
874 }
875
876 // TODO: except we don't handle it yet...
877 unimplemented("matrix type in buffer");
878 return false;
879 }
880
LoopDawg4886f692016-06-29 10:58:58 -0600881 if (!txType.isScalar() && !txType.isVector()) {
882 expected("scalar or vector type");
883 return false;
884 }
885
886 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
887 // TODO: handle vec2/3 types
888 expected("vector size not yet supported in texture type");
889 return false;
890 }
891
892 if (ms && acceptTokenClass(EHTokComma)) {
893 // read sample count for multisample types, if given
894 if (! peekTokenClass(EHTokIntConstant)) {
895 expected("multisample count");
896 return false;
897 }
898
899 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
900 return false;
901 }
902
903 if (! acceptTokenClass(EHTokRightAngle)) {
904 expected("right angle bracket");
905 return false;
906 }
907 } else if (ms) {
908 expected("texture type for multisample");
909 return false;
910 }
911
912 TArraySizes* arraySizes = nullptr;
913 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
914
915 TSampler sampler;
steve-lunargd53f7172016-07-27 15:46:48 -0600916
917 // Buffers are combined.
918 if (dim == EsdBuffer) {
919 sampler.set(txType.getBasicType(), dim, array);
920 } else {
921 // DX10 textures are separated. TODO: DX9.
922 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
923 }
LoopDawg4886f692016-06-29 10:58:58 -0600924
925 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
926
927 return true;
928}
929
930
John Kessenich87142c72016-03-12 20:24:24 -0700931// If token is for a type, update 'type' with the type information,
932// and return true and advance.
933// Otherwise, return false, and don't advance
934bool HlslGrammar::acceptType(TType& type)
935{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600936 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600937 case EHTokVector:
938 return acceptVectorTemplateType(type);
939 break;
940
941 case EHTokMatrix:
942 return acceptMatrixTemplateType(type);
943 break;
944
John Kessenich86f71382016-09-19 20:23:18 -0600945 case EHTokString:
946 return acceptStringTemplateType(type);
947 break;
948
LoopDawg4886f692016-06-29 10:58:58 -0600949 case EHTokSampler: // fall through
950 case EHTokSampler1d: // ...
951 case EHTokSampler2d: // ...
952 case EHTokSampler3d: // ...
953 case EHTokSamplerCube: // ...
954 case EHTokSamplerState: // ...
955 case EHTokSamplerComparisonState: // ...
956 return acceptSamplerType(type);
957 break;
958
959 case EHTokBuffer: // fall through
960 case EHTokTexture1d: // ...
961 case EHTokTexture1darray: // ...
962 case EHTokTexture2d: // ...
963 case EHTokTexture2darray: // ...
964 case EHTokTexture3d: // ...
965 case EHTokTextureCube: // ...
966 case EHTokTextureCubearray: // ...
967 case EHTokTexture2DMS: // ...
968 case EHTokTexture2DMSarray: // ...
969 return acceptTextureType(type);
970 break;
971
John Kesseniche6e74942016-06-11 16:43:14 -0600972 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600973 case EHTokCBuffer:
974 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600975 return acceptStruct(type);
976 break;
977
978 case EHTokIdentifier:
979 // An identifier could be for a user-defined type.
980 // Note we cache the symbol table lookup, to save for a later rule
981 // when this is not a type.
982 token.symbol = parseContext.symbolTable.find(*token.string);
983 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
984 type.shallowCopy(token.symbol->getType());
985 advanceToken();
986 return true;
987 } else
988 return false;
989
John Kessenich71351de2016-06-08 12:50:56 -0600990 case EHTokVoid:
991 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700992 break;
John Kessenich71351de2016-06-08 12:50:56 -0600993
John Kessenich87142c72016-03-12 20:24:24 -0700994 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600995 new(&type) TType(EbtFloat);
996 break;
John Kessenich87142c72016-03-12 20:24:24 -0700997 case EHTokFloat1:
998 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600999 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -07001000 break;
John Kessenich87142c72016-03-12 20:24:24 -07001001 case EHTokFloat2:
1002 new(&type) TType(EbtFloat, EvqTemporary, 2);
1003 break;
1004 case EHTokFloat3:
1005 new(&type) TType(EbtFloat, EvqTemporary, 3);
1006 break;
1007 case EHTokFloat4:
1008 new(&type) TType(EbtFloat, EvqTemporary, 4);
1009 break;
1010
John Kessenich71351de2016-06-08 12:50:56 -06001011 case EHTokDouble:
1012 new(&type) TType(EbtDouble);
1013 break;
1014 case EHTokDouble1:
1015 new(&type) TType(EbtDouble);
1016 type.makeVector();
1017 break;
1018 case EHTokDouble2:
1019 new(&type) TType(EbtDouble, EvqTemporary, 2);
1020 break;
1021 case EHTokDouble3:
1022 new(&type) TType(EbtDouble, EvqTemporary, 3);
1023 break;
1024 case EHTokDouble4:
1025 new(&type) TType(EbtDouble, EvqTemporary, 4);
1026 break;
1027
1028 case EHTokInt:
1029 case EHTokDword:
1030 new(&type) TType(EbtInt);
1031 break;
1032 case EHTokInt1:
1033 new(&type) TType(EbtInt);
1034 type.makeVector();
1035 break;
John Kessenich87142c72016-03-12 20:24:24 -07001036 case EHTokInt2:
1037 new(&type) TType(EbtInt, EvqTemporary, 2);
1038 break;
1039 case EHTokInt3:
1040 new(&type) TType(EbtInt, EvqTemporary, 3);
1041 break;
1042 case EHTokInt4:
1043 new(&type) TType(EbtInt, EvqTemporary, 4);
1044 break;
1045
John Kessenich71351de2016-06-08 12:50:56 -06001046 case EHTokUint:
1047 new(&type) TType(EbtUint);
1048 break;
1049 case EHTokUint1:
1050 new(&type) TType(EbtUint);
1051 type.makeVector();
1052 break;
1053 case EHTokUint2:
1054 new(&type) TType(EbtUint, EvqTemporary, 2);
1055 break;
1056 case EHTokUint3:
1057 new(&type) TType(EbtUint, EvqTemporary, 3);
1058 break;
1059 case EHTokUint4:
1060 new(&type) TType(EbtUint, EvqTemporary, 4);
1061 break;
1062
LoopDawg6daaa4f2016-06-23 19:13:48 -06001063
John Kessenich71351de2016-06-08 12:50:56 -06001064 case EHTokBool:
1065 new(&type) TType(EbtBool);
1066 break;
1067 case EHTokBool1:
1068 new(&type) TType(EbtBool);
1069 type.makeVector();
1070 break;
John Kessenich87142c72016-03-12 20:24:24 -07001071 case EHTokBool2:
1072 new(&type) TType(EbtBool, EvqTemporary, 2);
1073 break;
1074 case EHTokBool3:
1075 new(&type) TType(EbtBool, EvqTemporary, 3);
1076 break;
1077 case EHTokBool4:
1078 new(&type) TType(EbtBool, EvqTemporary, 4);
1079 break;
1080
John Kessenich0133c122016-05-20 12:17:26 -06001081 case EHTokInt1x1:
1082 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1083 break;
1084 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001085 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001086 break;
1087 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001088 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001089 break;
1090 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001091 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001092 break;
1093 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001094 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001095 break;
1096 case EHTokInt2x2:
1097 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1098 break;
1099 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001100 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001101 break;
1102 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001103 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001104 break;
1105 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001106 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001107 break;
1108 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001109 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001110 break;
1111 case EHTokInt3x3:
1112 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1113 break;
1114 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001115 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001116 break;
1117 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001118 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001119 break;
1120 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001121 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001122 break;
1123 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001124 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001125 break;
1126 case EHTokInt4x4:
1127 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1128 break;
1129
John Kessenich71351de2016-06-08 12:50:56 -06001130 case EHTokUint1x1:
1131 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1132 break;
1133 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001134 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001135 break;
1136 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001137 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001138 break;
1139 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001140 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001141 break;
1142 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001143 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001144 break;
1145 case EHTokUint2x2:
1146 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1147 break;
1148 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001149 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001150 break;
1151 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001152 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001153 break;
1154 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001155 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001156 break;
1157 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001158 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001159 break;
1160 case EHTokUint3x3:
1161 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1162 break;
1163 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001164 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001165 break;
1166 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001167 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001168 break;
1169 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001170 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001171 break;
1172 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001173 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001174 break;
1175 case EHTokUint4x4:
1176 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1177 break;
1178
1179 case EHTokBool1x1:
1180 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1181 break;
1182 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001183 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001184 break;
1185 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001186 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001187 break;
1188 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001189 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001190 break;
1191 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001192 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001193 break;
1194 case EHTokBool2x2:
1195 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1196 break;
1197 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001198 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001199 break;
1200 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001201 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001202 break;
1203 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001204 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001205 break;
1206 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001207 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001208 break;
1209 case EHTokBool3x3:
1210 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1211 break;
1212 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001213 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001214 break;
1215 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001216 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001217 break;
1218 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001219 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001220 break;
1221 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001222 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001223 break;
1224 case EHTokBool4x4:
1225 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1226 break;
1227
John Kessenich0133c122016-05-20 12:17:26 -06001228 case EHTokFloat1x1:
1229 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1230 break;
1231 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001232 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001233 break;
1234 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001235 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001236 break;
1237 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001238 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001239 break;
1240 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001241 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001242 break;
John Kessenich87142c72016-03-12 20:24:24 -07001243 case EHTokFloat2x2:
1244 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1245 break;
1246 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001247 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001248 break;
1249 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001250 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001251 break;
John Kessenich0133c122016-05-20 12:17:26 -06001252 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001253 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001254 break;
John Kessenich87142c72016-03-12 20:24:24 -07001255 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001256 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001257 break;
1258 case EHTokFloat3x3:
1259 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1260 break;
1261 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001262 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001263 break;
John Kessenich0133c122016-05-20 12:17:26 -06001264 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001265 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001266 break;
John Kessenich87142c72016-03-12 20:24:24 -07001267 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001268 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001269 break;
1270 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001271 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001272 break;
1273 case EHTokFloat4x4:
1274 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1275 break;
1276
John Kessenich0133c122016-05-20 12:17:26 -06001277 case EHTokDouble1x1:
1278 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1279 break;
1280 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001281 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001282 break;
1283 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001284 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001285 break;
1286 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001287 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001288 break;
1289 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001290 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001291 break;
1292 case EHTokDouble2x2:
1293 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1294 break;
1295 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001296 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001297 break;
1298 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001299 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001300 break;
1301 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001302 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001303 break;
1304 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001305 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001306 break;
1307 case EHTokDouble3x3:
1308 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1309 break;
1310 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001311 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001312 break;
1313 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001314 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001315 break;
1316 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001317 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001318 break;
1319 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001320 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001321 break;
1322 case EHTokDouble4x4:
1323 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1324 break;
1325
John Kessenich87142c72016-03-12 20:24:24 -07001326 default:
1327 return false;
1328 }
1329
1330 advanceToken();
1331
1332 return true;
1333}
1334
John Kesseniche6e74942016-06-11 16:43:14 -06001335// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001336// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1337// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1338//
1339// struct_type
1340// : STRUCT
1341// | CBUFFER
1342// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001343//
1344bool HlslGrammar::acceptStruct(TType& type)
1345{
John Kessenichb804de62016-09-05 12:19:18 -06001346 // This storage qualifier will tell us whether it's an AST
1347 // block type or just a generic structure type.
1348 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001349
1350 // CBUFFER
1351 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001352 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001353 // TBUFFER
1354 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001355 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001356 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001357 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001358 return false;
1359
1360 // IDENTIFIER
1361 TString structName = "";
1362 if (peekTokenClass(EHTokIdentifier)) {
1363 structName = *token.string;
1364 advanceToken();
1365 }
1366
John Kessenich3d157c52016-07-25 16:05:33 -06001367 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001368 TQualifier postDeclQualifier;
1369 postDeclQualifier.clear();
1370 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001371
John Kesseniche6e74942016-06-11 16:43:14 -06001372 // LEFT_BRACE
1373 if (! acceptTokenClass(EHTokLeftBrace)) {
1374 expected("{");
1375 return false;
1376 }
1377
1378 // struct_declaration_list
1379 TTypeList* typeList;
1380 if (! acceptStructDeclarationList(typeList)) {
1381 expected("struct member declarations");
1382 return false;
1383 }
1384
1385 // RIGHT_BRACE
1386 if (! acceptTokenClass(EHTokRightBrace)) {
1387 expected("}");
1388 return false;
1389 }
1390
1391 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001392 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001393 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001394 else {
John Kessenich7735b942016-09-05 12:40:06 -06001395 postDeclQualifier.storage = storageQualifier;
1396 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001397 }
John Kesseniche6e74942016-06-11 16:43:14 -06001398
John Kessenich3d157c52016-07-25 16:05:33 -06001399 // If it was named, which means the type can be reused later, add
1400 // it to the symbol table. (Unless it's a block, in which
1401 // case the name is not a type.)
1402 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001403 TVariable* userTypeDef = new TVariable(&structName, type, true);
1404 if (! parseContext.symbolTable.insert(*userTypeDef))
1405 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1406 }
1407
1408 return true;
1409}
1410
1411// struct_declaration_list
1412// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1413//
1414// struct_declaration
1415// : fully_specified_type struct_declarator COMMA struct_declarator ...
1416//
1417// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001418// : IDENTIFIER post_decls
1419// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001420//
1421bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1422{
1423 typeList = new TTypeList();
1424
1425 do {
1426 // success on seeing the RIGHT_BRACE coming up
1427 if (peekTokenClass(EHTokRightBrace))
1428 return true;
1429
1430 // struct_declaration
1431
1432 // fully_specified_type
1433 TType memberType;
1434 if (! acceptFullySpecifiedType(memberType)) {
1435 expected("member type");
1436 return false;
1437 }
1438
1439 // struct_declarator COMMA struct_declarator ...
1440 do {
1441 // peek IDENTIFIER
1442 if (! peekTokenClass(EHTokIdentifier)) {
1443 expected("member name");
1444 return false;
1445 }
1446
1447 // add it to the list of members
1448 TTypeLoc member = { new TType(EbtVoid), token.loc };
1449 member.type->shallowCopy(memberType);
1450 member.type->setFieldName(*token.string);
1451 typeList->push_back(member);
1452
1453 // accept IDENTIFIER
1454 advanceToken();
1455
1456 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001457 TArraySizes* arraySizes = nullptr;
1458 acceptArraySpecifier(arraySizes);
1459 if (arraySizes)
1460 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001461
John Kessenich7735b942016-09-05 12:40:06 -06001462 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001463
John Kesseniche6e74942016-06-11 16:43:14 -06001464 // success on seeing the SEMICOLON coming up
1465 if (peekTokenClass(EHTokSemicolon))
1466 break;
1467
1468 // COMMA
1469 if (! acceptTokenClass(EHTokComma)) {
1470 expected(",");
1471 return false;
1472 }
1473
1474 } while (true);
1475
1476 // SEMI_COLON
1477 if (! acceptTokenClass(EHTokSemicolon)) {
1478 expected(";");
1479 return false;
1480 }
1481
1482 } while (true);
1483}
1484
John Kessenich5f934b02016-03-13 17:58:25 -06001485// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001486// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001487// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001488//
1489bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1490{
John Kessenich078d7f22016-03-14 10:02:11 -06001491 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001492 if (! acceptTokenClass(EHTokLeftParen))
1493 return false;
1494
John Kessenich71351de2016-06-08 12:50:56 -06001495 // VOID RIGHT_PAREN
1496 if (! acceptTokenClass(EHTokVoid)) {
1497 do {
1498 // parameter_declaration
1499 if (! acceptParameterDeclaration(function))
1500 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001501
John Kessenich71351de2016-06-08 12:50:56 -06001502 // COMMA
1503 if (! acceptTokenClass(EHTokComma))
1504 break;
1505 } while (true);
1506 }
John Kessenich5f934b02016-03-13 17:58:25 -06001507
John Kessenich078d7f22016-03-14 10:02:11 -06001508 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001509 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001510 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001511 return false;
1512 }
1513
1514 return true;
1515}
1516
1517// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001518// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001519// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001520//
1521bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1522{
1523 // fully_specified_type
1524 TType* type = new TType;
1525 if (! acceptFullySpecifiedType(*type))
1526 return false;
1527
1528 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001529 HlslToken idToken;
1530 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001531
John Kessenich19b92ff2016-06-19 11:50:34 -06001532 // array_specifier
1533 TArraySizes* arraySizes = nullptr;
1534 acceptArraySpecifier(arraySizes);
1535 if (arraySizes)
1536 type->newArraySizes(*arraySizes);
1537
1538 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001539 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001540
John Kessenich5aa59e22016-06-17 15:50:47 -06001541 parseContext.paramFix(*type);
1542
John Kessenichaecd4972016-03-14 10:46:34 -06001543 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001544 function.addParameter(param);
1545
1546 return true;
1547}
1548
1549// Do the work to create the function definition in addition to
1550// parsing the body (compound_statement).
1551bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1552{
John Kessenicha3051662016-09-02 19:13:36 -06001553 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001554 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001555
John Kessenich077e0522016-06-09 02:02:17 -06001556 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001557 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001558
1559 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001560 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001561 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001562 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001563 return true;
1564 }
1565
1566 return false;
1567}
1568
John Kessenich0d2b6de2016-06-05 11:23:11 -06001569// Accept an expression with parenthesis around it, where
1570// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001571// syntactically required ones like in "if ( expression )".
1572//
1573// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001574//
1575// Note this one is not set up to be speculative; as it gives
1576// errors if not found.
1577//
1578bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1579{
1580 // LEFT_PAREN
1581 if (! acceptTokenClass(EHTokLeftParen))
1582 expected("(");
1583
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001584 bool decl = false;
1585 TIntermNode* declNode = nullptr;
1586 decl = acceptControlDeclaration(declNode);
1587 if (decl) {
1588 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1589 expected("initialized declaration");
1590 return false;
1591 } else
1592 expression = declNode->getAsTyped();
1593 } else {
1594 // no declaration
1595 if (! acceptExpression(expression)) {
1596 expected("expression");
1597 return false;
1598 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001599 }
1600
1601 // RIGHT_PAREN
1602 if (! acceptTokenClass(EHTokRightParen))
1603 expected(")");
1604
1605 return true;
1606}
1607
John Kessenich34fb0362016-05-03 23:17:20 -06001608// The top-level full expression recognizer.
1609//
John Kessenich87142c72016-03-12 20:24:24 -07001610// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001611// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001612//
1613bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1614{
LoopDawgef764a22016-06-03 09:17:51 -06001615 node = nullptr;
1616
John Kessenich34fb0362016-05-03 23:17:20 -06001617 // assignment_expression
1618 if (! acceptAssignmentExpression(node))
1619 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001620
John Kessenich34fb0362016-05-03 23:17:20 -06001621 if (! peekTokenClass(EHTokComma))
1622 return true;
1623
1624 do {
1625 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001626 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001627 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001628
John Kessenich34fb0362016-05-03 23:17:20 -06001629 // ... assignment_expression
1630 TIntermTyped* rightNode = nullptr;
1631 if (! acceptAssignmentExpression(rightNode)) {
1632 expected("assignment expression");
1633 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001634 }
1635
John Kessenich34fb0362016-05-03 23:17:20 -06001636 node = intermediate.addComma(node, rightNode, loc);
1637
1638 if (! peekTokenClass(EHTokComma))
1639 return true;
1640 } while (true);
1641}
1642
John Kessenich07354242016-07-01 19:58:06 -06001643// initializer
1644// : LEFT_BRACE initializer_list RIGHT_BRACE
1645//
1646// initializer_list
1647// : assignment_expression COMMA assignment_expression COMMA ...
1648//
1649bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1650{
1651 // LEFT_BRACE
1652 if (! acceptTokenClass(EHTokLeftBrace))
1653 return false;
1654
1655 // initializer_list
1656 TSourceLoc loc = token.loc;
1657 node = nullptr;
1658 do {
1659 // assignment_expression
1660 TIntermTyped* expr;
1661 if (! acceptAssignmentExpression(expr)) {
1662 expected("assignment expression in initializer list");
1663 return false;
1664 }
1665 node = intermediate.growAggregate(node, expr, loc);
1666
1667 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001668 if (acceptTokenClass(EHTokComma)) {
1669 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1670 return true;
John Kessenich07354242016-07-01 19:58:06 -06001671 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001672 }
John Kessenich07354242016-07-01 19:58:06 -06001673
1674 // RIGHT_BRACE
1675 if (acceptTokenClass(EHTokRightBrace))
1676 return true;
1677
1678 expected(", or }");
1679 return false;
1680 } while (true);
1681}
1682
John Kessenich34fb0362016-05-03 23:17:20 -06001683// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001684// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001685//
1686// a op (b op (c op d))
1687//
1688// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001689// : initializer
1690// | conditional_expression
1691// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001692//
1693bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1694{
John Kessenich07354242016-07-01 19:58:06 -06001695 // initializer
1696 if (peekTokenClass(EHTokLeftBrace)) {
1697 if (acceptInitializer(node))
1698 return true;
1699
1700 expected("initializer");
1701 return false;
1702 }
1703
John Kessenich00957f82016-07-27 10:39:57 -06001704 // conditional_expression
1705 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001706 return false;
1707
John Kessenich07354242016-07-01 19:58:06 -06001708 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001709 TOperator assignOp = HlslOpMap::assignment(peek());
1710 if (assignOp == EOpNull)
1711 return true;
1712
John Kessenich00957f82016-07-27 10:39:57 -06001713 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001714 TSourceLoc loc = token.loc;
1715 advanceToken();
1716
John Kessenich00957f82016-07-27 10:39:57 -06001717 // conditional_expression assign_op conditional_expression ...
1718 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001719 // gets the right-to-left associativity.
1720 TIntermTyped* rightNode = nullptr;
1721 if (! acceptAssignmentExpression(rightNode)) {
1722 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001723 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001724 }
1725
John Kessenichd21baed2016-09-16 03:05:12 -06001726 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
John Kessenichfea226b2016-07-28 17:53:56 -06001727 if (node == nullptr) {
1728 parseContext.error(loc, "could not create assignment", "", "");
1729 return false;
1730 }
John Kessenich34fb0362016-05-03 23:17:20 -06001731
1732 if (! peekTokenClass(EHTokComma))
1733 return true;
1734
1735 return true;
1736}
1737
John Kessenich00957f82016-07-27 10:39:57 -06001738// Accept a conditional expression, which associates right-to-left,
1739// accomplished by the "true" expression calling down to lower
1740// precedence levels than this level.
1741//
1742// conditional_expression
1743// : binary_expression
1744// | binary_expression QUESTION expression COLON assignment_expression
1745//
1746bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1747{
1748 // binary_expression
1749 if (! acceptBinaryExpression(node, PlLogicalOr))
1750 return false;
1751
1752 if (! acceptTokenClass(EHTokQuestion))
1753 return true;
1754
1755 TIntermTyped* trueNode = nullptr;
1756 if (! acceptExpression(trueNode)) {
1757 expected("expression after ?");
1758 return false;
1759 }
1760 TSourceLoc loc = token.loc;
1761
1762 if (! acceptTokenClass(EHTokColon)) {
1763 expected(":");
1764 return false;
1765 }
1766
1767 TIntermTyped* falseNode = nullptr;
1768 if (! acceptAssignmentExpression(falseNode)) {
1769 expected("expression after :");
1770 return false;
1771 }
1772
1773 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1774
1775 return true;
1776}
1777
John Kessenich34fb0362016-05-03 23:17:20 -06001778// Accept a binary expression, for binary operations that
1779// associate left-to-right. This is, it is implicit, for example
1780//
1781// ((a op b) op c) op d
1782//
1783// binary_expression
1784// : expression op expression op expression ...
1785//
1786// where 'expression' is the next higher level in precedence.
1787//
1788bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1789{
1790 if (precedenceLevel > PlMul)
1791 return acceptUnaryExpression(node);
1792
1793 // assignment_expression
1794 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1795 return false;
1796
John Kessenich34fb0362016-05-03 23:17:20 -06001797 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001798 TOperator op = HlslOpMap::binary(peek());
1799 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1800 if (tokenLevel < precedenceLevel)
1801 return true;
1802
John Kessenich34fb0362016-05-03 23:17:20 -06001803 // ... op
1804 TSourceLoc loc = token.loc;
1805 advanceToken();
1806
1807 // ... expression
1808 TIntermTyped* rightNode = nullptr;
1809 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1810 expected("expression");
1811 return false;
1812 }
1813
1814 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001815 if (node == nullptr) {
1816 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1817 return false;
1818 }
John Kessenich34fb0362016-05-03 23:17:20 -06001819 } while (true);
1820}
1821
1822// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001823// : (type) unary_expression
1824// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001825// | - unary_expression
1826// | ! unary_expression
1827// | ~ unary_expression
1828// | ++ unary_expression
1829// | -- unary_expression
1830// | postfix_expression
1831//
1832bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1833{
John Kessenich1cc1a282016-06-03 16:55:49 -06001834 // (type) unary_expression
1835 // Have to look two steps ahead, because this could be, e.g., a
1836 // postfix_expression instead, since that also starts with at "(".
1837 if (acceptTokenClass(EHTokLeftParen)) {
1838 TType castType;
1839 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001840 if (acceptTokenClass(EHTokRightParen)) {
1841 // We've matched "(type)" now, get the expression to cast
1842 TSourceLoc loc = token.loc;
1843 if (! acceptUnaryExpression(node))
1844 return false;
1845
1846 // Hook it up like a constructor
1847 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1848 if (constructorFunction == nullptr) {
1849 expected("type that can be constructed");
1850 return false;
1851 }
1852 TIntermTyped* arguments = nullptr;
1853 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1854 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1855
1856 return true;
1857 } else {
1858 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
1859 // the '(int' part. We must back up twice.
1860 recedeToken();
1861 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06001862 }
John Kessenich1cc1a282016-06-03 16:55:49 -06001863 } else {
1864 // This isn't a type cast, but it still started "(", so if it is a
1865 // unary expression, it can only be a postfix_expression, so try that.
1866 // Back it up first.
1867 recedeToken();
1868 return acceptPostfixExpression(node);
1869 }
1870 }
1871
1872 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001873 TOperator unaryOp = HlslOpMap::preUnary(peek());
1874
John Kessenich1cc1a282016-06-03 16:55:49 -06001875 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001876 if (unaryOp == EOpNull)
1877 return acceptPostfixExpression(node);
1878
1879 // op unary_expression
1880 TSourceLoc loc = token.loc;
1881 advanceToken();
1882 if (! acceptUnaryExpression(node))
1883 return false;
1884
1885 // + is a no-op
1886 if (unaryOp == EOpAdd)
1887 return true;
1888
1889 node = intermediate.addUnaryMath(unaryOp, node, loc);
1890
1891 return node != nullptr;
1892}
1893
1894// postfix_expression
1895// : LEFT_PAREN expression RIGHT_PAREN
1896// | literal
1897// | constructor
1898// | identifier
1899// | function_call
1900// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1901// | postfix_expression DOT IDENTIFIER
1902// | postfix_expression INC_OP
1903// | postfix_expression DEC_OP
1904//
1905bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1906{
1907 // Not implemented as self-recursive:
1908 // The logical "right recursion" is done with an loop at the end
1909
1910 // idToken will pick up either a variable or a function name in a function call
1911 HlslToken idToken;
1912
John Kessenich21472ae2016-06-04 11:46:33 -06001913 // Find something before the postfix operations, as they can't operate
1914 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001915 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001916 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001917 if (! acceptExpression(node)) {
1918 expected("expression");
1919 return false;
1920 }
1921 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001922 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001923 return false;
1924 }
John Kessenich34fb0362016-05-03 23:17:20 -06001925 } else if (acceptLiteral(node)) {
1926 // literal (nothing else to do yet), go on to the
1927 } else if (acceptConstructor(node)) {
1928 // constructor (nothing else to do yet)
1929 } else if (acceptIdentifier(idToken)) {
1930 // identifier or function_call name
1931 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001932 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001933 } else if (acceptFunctionCall(idToken, node)) {
1934 // function_call (nothing else to do yet)
1935 } else {
1936 expected("function call arguments");
1937 return false;
1938 }
John Kessenich21472ae2016-06-04 11:46:33 -06001939 } else {
1940 // nothing found, can't post operate
1941 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001942 }
1943
John Kessenich21472ae2016-06-04 11:46:33 -06001944 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001945 do {
1946 TSourceLoc loc = token.loc;
1947 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001948
John Kessenich34fb0362016-05-03 23:17:20 -06001949 // Consume only a valid post-unary operator, otherwise we are done.
1950 switch (postOp) {
1951 case EOpIndexDirectStruct:
1952 case EOpIndexIndirect:
1953 case EOpPostIncrement:
1954 case EOpPostDecrement:
1955 advanceToken();
1956 break;
1957 default:
1958 return true;
1959 }
John Kessenich87142c72016-03-12 20:24:24 -07001960
John Kessenich34fb0362016-05-03 23:17:20 -06001961 // We have a valid post-unary operator, process it.
1962 switch (postOp) {
1963 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001964 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001965 // DOT IDENTIFIER
1966 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001967 HlslToken field;
1968 if (! acceptIdentifier(field)) {
1969 expected("swizzle or member");
1970 return false;
1971 }
LoopDawg4886f692016-06-29 10:58:58 -06001972
1973 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001974 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001975
1976 // In the event of a method node, we look for an open paren and accept the function call.
1977 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1978 if (! acceptFunctionCall(field, node, base)) {
1979 expected("function parameters");
1980 return false;
1981 }
1982 }
1983
John Kessenich34fb0362016-05-03 23:17:20 -06001984 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001985 }
John Kessenich34fb0362016-05-03 23:17:20 -06001986 case EOpIndexIndirect:
1987 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001988 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001989 TIntermTyped* indexNode = nullptr;
1990 if (! acceptExpression(indexNode) ||
1991 ! peekTokenClass(EHTokRightBracket)) {
1992 expected("expression followed by ']'");
1993 return false;
1994 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001995 advanceToken();
1996 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1997 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001998 }
1999 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002000 // INC_OP
2001 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06002002 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06002003 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06002004 node = intermediate.addUnaryMath(postOp, node, loc);
2005 break;
2006 default:
2007 assert(0);
2008 break;
2009 }
2010 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07002011}
2012
John Kessenichd016be12016-03-13 11:24:20 -06002013// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06002014// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06002015//
2016bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2017{
2018 // type
2019 TType type;
2020 if (acceptType(type)) {
2021 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2022 if (constructorFunction == nullptr)
2023 return false;
2024
2025 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002026 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002027 if (! acceptArguments(constructorFunction, arguments)) {
2028 expected("constructor arguments");
2029 return false;
2030 }
2031
2032 // hook it up
2033 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2034
2035 return true;
2036 }
2037
2038 return false;
2039}
2040
John Kessenich34fb0362016-05-03 23:17:20 -06002041// The function_call identifier was already recognized, and passed in as idToken.
2042//
2043// function_call
2044// : [idToken] arguments
2045//
LoopDawg4886f692016-06-29 10:58:58 -06002046bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002047{
John Kessenich4678ca92016-05-13 09:33:42 -06002048 // arguments
2049 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2050 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002051
2052 // methods have an implicit first argument of the calling object.
2053 if (base != nullptr)
2054 parseContext.handleFunctionArgument(function, arguments, base);
2055
John Kessenich4678ca92016-05-13 09:33:42 -06002056 if (! acceptArguments(function, arguments))
2057 return false;
2058
2059 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2060
2061 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002062}
2063
John Kessenich87142c72016-03-12 20:24:24 -07002064// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002065// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002066//
John Kessenichd016be12016-03-13 11:24:20 -06002067// The arguments are pushed onto the 'function' argument list and
2068// onto the 'arguments' aggregate.
2069//
John Kessenich4678ca92016-05-13 09:33:42 -06002070bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002071{
John Kessenich078d7f22016-03-14 10:02:11 -06002072 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002073 if (! acceptTokenClass(EHTokLeftParen))
2074 return false;
2075
2076 do {
John Kessenichd016be12016-03-13 11:24:20 -06002077 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002078 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002079 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002080 break;
John Kessenichd016be12016-03-13 11:24:20 -06002081
2082 // hook it up
2083 parseContext.handleFunctionArgument(function, arguments, arg);
2084
John Kessenich078d7f22016-03-14 10:02:11 -06002085 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002086 if (! acceptTokenClass(EHTokComma))
2087 break;
2088 } while (true);
2089
John Kessenich078d7f22016-03-14 10:02:11 -06002090 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002091 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002092 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002093 return false;
2094 }
2095
2096 return true;
2097}
2098
2099bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2100{
2101 switch (token.tokenClass) {
2102 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002103 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002104 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002105 case EHTokUintConstant:
2106 node = intermediate.addConstantUnion(token.u, token.loc, true);
2107 break;
John Kessenich87142c72016-03-12 20:24:24 -07002108 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002109 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002110 break;
2111 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002112 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002113 break;
2114 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002115 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002116 break;
John Kessenich86f71382016-09-19 20:23:18 -06002117 case EHTokStringConstant:
2118 node = nullptr;
2119 break;
John Kessenich87142c72016-03-12 20:24:24 -07002120
2121 default:
2122 return false;
2123 }
2124
2125 advanceToken();
2126
2127 return true;
2128}
2129
John Kessenich5f934b02016-03-13 17:58:25 -06002130// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002131// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002132//
John Kessenich21472ae2016-06-04 11:46:33 -06002133bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002134{
John Kessenich21472ae2016-06-04 11:46:33 -06002135 TIntermAggregate* compoundStatement = nullptr;
2136
John Kessenich34fb0362016-05-03 23:17:20 -06002137 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002138 if (! acceptTokenClass(EHTokLeftBrace))
2139 return false;
2140
2141 // statement statement ...
2142 TIntermNode* statement = nullptr;
2143 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002144 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2145 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2146 branch->getFlowOp() == EOpDefault)) {
2147 // hook up individual subsequences within a switch statement
2148 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2149 compoundStatement = nullptr;
2150 } else {
2151 // hook it up to the growing compound statement
2152 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2153 }
John Kessenich5f934b02016-03-13 17:58:25 -06002154 }
John Kessenich34fb0362016-05-03 23:17:20 -06002155 if (compoundStatement)
2156 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002157
John Kessenich21472ae2016-06-04 11:46:33 -06002158 retStatement = compoundStatement;
2159
John Kessenich34fb0362016-05-03 23:17:20 -06002160 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002161 return acceptTokenClass(EHTokRightBrace);
2162}
2163
John Kessenich0d2b6de2016-06-05 11:23:11 -06002164bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2165{
2166 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002167 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002168 parseContext.popScope();
2169
2170 return result;
2171}
2172
John Kessenich077e0522016-06-09 02:02:17 -06002173bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002174{
John Kessenich077e0522016-06-09 02:02:17 -06002175 parseContext.pushScope();
2176 bool result = acceptCompoundStatement(statement);
2177 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002178
2179 return result;
2180}
2181
John Kessenich5f934b02016-03-13 17:58:25 -06002182// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002183// : attributes attributed_statement
2184//
2185// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002186// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002187// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002188// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002189// | declaration_statement
2190// | selection_statement
2191// | switch_statement
2192// | case_label
2193// | iteration_statement
2194// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002195//
2196bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2197{
John Kessenich21472ae2016-06-04 11:46:33 -06002198 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002199
John Kessenich21472ae2016-06-04 11:46:33 -06002200 // attributes
2201 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002202
John Kessenich21472ae2016-06-04 11:46:33 -06002203 // attributed_statement
2204 switch (peek()) {
2205 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002206 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002207
John Kessenich21472ae2016-06-04 11:46:33 -06002208 case EHTokIf:
2209 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002210
John Kessenich21472ae2016-06-04 11:46:33 -06002211 case EHTokSwitch:
2212 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002213
John Kessenich21472ae2016-06-04 11:46:33 -06002214 case EHTokFor:
2215 case EHTokDo:
2216 case EHTokWhile:
2217 return acceptIterationStatement(statement);
2218
2219 case EHTokContinue:
2220 case EHTokBreak:
2221 case EHTokDiscard:
2222 case EHTokReturn:
2223 return acceptJumpStatement(statement);
2224
2225 case EHTokCase:
2226 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002227 case EHTokDefault:
2228 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002229
2230 case EHTokSemicolon:
2231 return acceptTokenClass(EHTokSemicolon);
2232
2233 case EHTokRightBrace:
2234 // Performance: not strictly necessary, but stops a bunch of hunting early,
2235 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002236 return false;
2237
John Kessenich21472ae2016-06-04 11:46:33 -06002238 default:
2239 {
2240 // declaration
2241 if (acceptDeclaration(statement))
2242 return true;
2243
2244 // expression
2245 TIntermTyped* node;
2246 if (acceptExpression(node))
2247 statement = node;
2248 else
2249 return false;
2250
2251 // SEMICOLON (following an expression)
2252 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002253 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002254 return false;
2255 }
2256 }
2257 }
2258
John Kessenich5f934b02016-03-13 17:58:25 -06002259 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002260}
2261
John Kessenich21472ae2016-06-04 11:46:33 -06002262// attributes
2263// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2264//
2265// attribute:
2266// : UNROLL
2267// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2268// | FASTOPT
2269// | ALLOW_UAV_CONDITION
2270// | BRANCH
2271// | FLATTEN
2272// | FORCECASE
2273// | CALL
2274//
2275void HlslGrammar::acceptAttributes()
2276{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002277 // For now, accept the [ XXX(X) ] syntax, but drop.
2278 // TODO: subset to correct set? Pass on?
2279 do {
2280 // LEFT_BRACKET?
2281 if (! acceptTokenClass(EHTokLeftBracket))
2282 return;
2283
2284 // attribute
2285 if (peekTokenClass(EHTokIdentifier)) {
2286 // 'token.string' is the attribute
2287 advanceToken();
2288 } else if (! peekTokenClass(EHTokRightBracket)) {
2289 expected("identifier");
2290 advanceToken();
2291 }
2292
2293 // (x)
2294 if (acceptTokenClass(EHTokLeftParen)) {
2295 TIntermTyped* node;
2296 if (! acceptLiteral(node))
2297 expected("literal");
2298 // 'node' has the literal in it
2299 if (! acceptTokenClass(EHTokRightParen))
2300 expected(")");
2301 }
2302
2303 // RIGHT_BRACKET
2304 if (acceptTokenClass(EHTokRightBracket))
2305 continue;
2306
2307 expected("]");
2308 return;
2309
2310 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002311}
2312
John Kessenich0d2b6de2016-06-05 11:23:11 -06002313// selection_statement
2314// : IF LEFT_PAREN expression RIGHT_PAREN statement
2315// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2316//
John Kessenich21472ae2016-06-04 11:46:33 -06002317bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2318{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002319 TSourceLoc loc = token.loc;
2320
2321 // IF
2322 if (! acceptTokenClass(EHTokIf))
2323 return false;
2324
2325 // so that something declared in the condition is scoped to the lifetimes
2326 // of the then-else statements
2327 parseContext.pushScope();
2328
2329 // LEFT_PAREN expression RIGHT_PAREN
2330 TIntermTyped* condition;
2331 if (! acceptParenExpression(condition))
2332 return false;
2333
2334 // create the child statements
2335 TIntermNodePair thenElse = { nullptr, nullptr };
2336
2337 // then statement
2338 if (! acceptScopedStatement(thenElse.node1)) {
2339 expected("then statement");
2340 return false;
2341 }
2342
2343 // ELSE
2344 if (acceptTokenClass(EHTokElse)) {
2345 // else statement
2346 if (! acceptScopedStatement(thenElse.node2)) {
2347 expected("else statement");
2348 return false;
2349 }
2350 }
2351
2352 // Put the pieces together
2353 statement = intermediate.addSelection(condition, thenElse, loc);
2354 parseContext.popScope();
2355
2356 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002357}
2358
John Kessenichd02dc5d2016-07-01 00:04:11 -06002359// switch_statement
2360// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2361//
John Kessenich21472ae2016-06-04 11:46:33 -06002362bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2363{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002364 // SWITCH
2365 TSourceLoc loc = token.loc;
2366 if (! acceptTokenClass(EHTokSwitch))
2367 return false;
2368
2369 // LEFT_PAREN expression RIGHT_PAREN
2370 parseContext.pushScope();
2371 TIntermTyped* switchExpression;
2372 if (! acceptParenExpression(switchExpression)) {
2373 parseContext.popScope();
2374 return false;
2375 }
2376
2377 // compound_statement
2378 parseContext.pushSwitchSequence(new TIntermSequence);
2379 bool statementOkay = acceptCompoundStatement(statement);
2380 if (statementOkay)
2381 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2382
2383 parseContext.popSwitchSequence();
2384 parseContext.popScope();
2385
2386 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002387}
2388
John Kessenich119f8f62016-06-05 15:44:07 -06002389// iteration_statement
2390// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2391// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2392// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2393//
2394// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002395bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2396{
John Kessenich119f8f62016-06-05 15:44:07 -06002397 TSourceLoc loc = token.loc;
2398 TIntermTyped* condition = nullptr;
2399
2400 EHlslTokenClass loop = peek();
2401 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2402
2403 // WHILE or DO or FOR
2404 advanceToken();
2405
2406 switch (loop) {
2407 case EHTokWhile:
2408 // so that something declared in the condition is scoped to the lifetime
2409 // of the while sub-statement
2410 parseContext.pushScope();
2411 parseContext.nestLooping();
2412
2413 // LEFT_PAREN condition RIGHT_PAREN
2414 if (! acceptParenExpression(condition))
2415 return false;
2416
2417 // statement
2418 if (! acceptScopedStatement(statement)) {
2419 expected("while sub-statement");
2420 return false;
2421 }
2422
2423 parseContext.unnestLooping();
2424 parseContext.popScope();
2425
2426 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2427
2428 return true;
2429
2430 case EHTokDo:
2431 parseContext.nestLooping();
2432
2433 if (! acceptTokenClass(EHTokLeftBrace))
2434 expected("{");
2435
2436 // statement
2437 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2438 expected("do sub-statement");
2439 return false;
2440 }
2441
2442 if (! acceptTokenClass(EHTokRightBrace))
2443 expected("}");
2444
2445 // WHILE
2446 if (! acceptTokenClass(EHTokWhile)) {
2447 expected("while");
2448 return false;
2449 }
2450
2451 // LEFT_PAREN condition RIGHT_PAREN
2452 TIntermTyped* condition;
2453 if (! acceptParenExpression(condition))
2454 return false;
2455
2456 if (! acceptTokenClass(EHTokSemicolon))
2457 expected(";");
2458
2459 parseContext.unnestLooping();
2460
2461 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2462
2463 return true;
2464
2465 case EHTokFor:
2466 {
2467 // LEFT_PAREN
2468 if (! acceptTokenClass(EHTokLeftParen))
2469 expected("(");
2470
2471 // so that something declared in the condition is scoped to the lifetime
2472 // of the for sub-statement
2473 parseContext.pushScope();
2474
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002475 // initializer
2476 TIntermNode* initNode = nullptr;
2477 if (! acceptControlDeclaration(initNode)) {
2478 TIntermTyped* initExpr = nullptr;
2479 acceptExpression(initExpr);
2480 initNode = initExpr;
2481 }
2482 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002483 if (! acceptTokenClass(EHTokSemicolon))
2484 expected(";");
2485
2486 parseContext.nestLooping();
2487
2488 // condition SEMI_COLON
2489 acceptExpression(condition);
2490 if (! acceptTokenClass(EHTokSemicolon))
2491 expected(";");
2492
2493 // iterator SEMI_COLON
2494 TIntermTyped* iterator = nullptr;
2495 acceptExpression(iterator);
2496 if (! acceptTokenClass(EHTokRightParen))
2497 expected(")");
2498
2499 // statement
2500 if (! acceptScopedStatement(statement)) {
2501 expected("for sub-statement");
2502 return false;
2503 }
2504
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002505 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002506
2507 parseContext.popScope();
2508 parseContext.unnestLooping();
2509
2510 return true;
2511 }
2512
2513 default:
2514 return false;
2515 }
John Kessenich21472ae2016-06-04 11:46:33 -06002516}
2517
2518// jump_statement
2519// : CONTINUE SEMICOLON
2520// | BREAK SEMICOLON
2521// | DISCARD SEMICOLON
2522// | RETURN SEMICOLON
2523// | RETURN expression SEMICOLON
2524//
2525bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2526{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002527 EHlslTokenClass jump = peek();
2528 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002529 case EHTokContinue:
2530 case EHTokBreak:
2531 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002532 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002533 advanceToken();
2534 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002535 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002536 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002537 return false;
2538 }
John Kessenich21472ae2016-06-04 11:46:33 -06002539
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002540 switch (jump) {
2541 case EHTokContinue:
2542 statement = intermediate.addBranch(EOpContinue, token.loc);
2543 break;
2544 case EHTokBreak:
2545 statement = intermediate.addBranch(EOpBreak, token.loc);
2546 break;
2547 case EHTokDiscard:
2548 statement = intermediate.addBranch(EOpKill, token.loc);
2549 break;
2550
2551 case EHTokReturn:
2552 {
2553 // expression
2554 TIntermTyped* node;
2555 if (acceptExpression(node)) {
2556 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002557 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002558 } else
2559 statement = intermediate.addBranch(EOpReturn, token.loc);
2560 break;
2561 }
2562
2563 default:
2564 assert(0);
2565 return false;
2566 }
2567
2568 // SEMICOLON
2569 if (! acceptTokenClass(EHTokSemicolon))
2570 expected(";");
2571
2572 return true;
2573}
John Kessenich21472ae2016-06-04 11:46:33 -06002574
John Kessenichd02dc5d2016-07-01 00:04:11 -06002575// case_label
2576// : CASE expression COLON
2577//
John Kessenich21472ae2016-06-04 11:46:33 -06002578bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2579{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002580 TSourceLoc loc = token.loc;
2581 if (! acceptTokenClass(EHTokCase))
2582 return false;
2583
2584 TIntermTyped* expression;
2585 if (! acceptExpression(expression)) {
2586 expected("case expression");
2587 return false;
2588 }
2589
2590 if (! acceptTokenClass(EHTokColon)) {
2591 expected(":");
2592 return false;
2593 }
2594
2595 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2596
2597 return true;
2598}
2599
2600// default_label
2601// : DEFAULT COLON
2602//
2603bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2604{
2605 TSourceLoc loc = token.loc;
2606 if (! acceptTokenClass(EHTokDefault))
2607 return false;
2608
2609 if (! acceptTokenClass(EHTokColon)) {
2610 expected(":");
2611 return false;
2612 }
2613
2614 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2615
2616 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002617}
2618
John Kessenich19b92ff2016-06-19 11:50:34 -06002619// array_specifier
2620// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
2621//
2622void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2623{
2624 arraySizes = nullptr;
2625
2626 if (! acceptTokenClass(EHTokLeftBracket))
2627 return;
2628
2629 TSourceLoc loc = token.loc;
2630 TIntermTyped* sizeExpr;
2631 if (! acceptAssignmentExpression(sizeExpr)) {
2632 expected("array-sizing expression");
2633 return;
2634 }
2635
2636 if (! acceptTokenClass(EHTokRightBracket)) {
2637 expected("]");
2638 return;
2639 }
2640
2641 TArraySize arraySize;
2642 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2643 arraySizes = new TArraySizes;
2644 arraySizes->addInnerSize(arraySize);
2645}
2646
John Kessenich630dd7d2016-06-12 23:52:12 -06002647// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002648// : COLON semantic // optional
2649// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2650// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002651// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002652// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002653//
John Kessenich7735b942016-09-05 12:40:06 -06002654void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002655{
John Kessenich630dd7d2016-06-12 23:52:12 -06002656 do {
2657 // COLON
2658 if (acceptTokenClass(EHTokColon)) {
2659 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002660 if (peekTokenClass(EHTokLayout))
2661 acceptLayoutQualifierList(qualifier);
2662 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002663 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002664 if (! acceptTokenClass(EHTokLeftParen)) {
2665 expected("(");
2666 return;
2667 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002668 HlslToken locationToken;
2669 if (! acceptIdentifier(locationToken)) {
2670 expected("c[subcomponent][.component]");
2671 return;
2672 }
2673 HlslToken componentToken;
2674 if (acceptTokenClass(EHTokDot)) {
2675 if (! acceptIdentifier(componentToken)) {
2676 expected("component");
2677 return;
2678 }
2679 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002680 if (! acceptTokenClass(EHTokRightParen)) {
2681 expected(")");
2682 break;
2683 }
John Kessenich7735b942016-09-05 12:40:06 -06002684 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002685 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002686 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002687 return;
2688 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002689 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2690 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002691 if (! acceptTokenClass(EHTokLeftParen)) {
2692 expected("(");
2693 return;
2694 }
John Kessenichb38f0712016-07-30 10:29:54 -06002695 HlslToken registerDesc; // for Type#
2696 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002697 if (! acceptIdentifier(registerDesc)) {
2698 expected("register number description");
2699 return;
2700 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002701 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2702 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002703 // Then we didn't really see the registerDesc yet, it was
2704 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002705 profile = registerDesc;
2706 if (! acceptIdentifier(registerDesc)) {
2707 expected("register number description");
2708 return;
2709 }
2710 }
John Kessenichb38f0712016-07-30 10:29:54 -06002711 int subComponent = 0;
2712 if (acceptTokenClass(EHTokLeftBracket)) {
2713 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2714 if (! peekTokenClass(EHTokIntConstant)) {
2715 expected("literal integer");
2716 return;
2717 }
2718 subComponent = token.i;
2719 advanceToken();
2720 if (! acceptTokenClass(EHTokRightBracket)) {
2721 expected("]");
2722 break;
2723 }
2724 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002725 // (COMMA SPACEN)opt
2726 HlslToken spaceDesc;
2727 if (acceptTokenClass(EHTokComma)) {
2728 if (! acceptIdentifier(spaceDesc)) {
2729 expected ("space identifier");
2730 return;
2731 }
2732 }
2733 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002734 if (! acceptTokenClass(EHTokRightParen)) {
2735 expected(")");
2736 break;
2737 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002738 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002739 } else {
2740 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002741 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002742 }
2743 } else if (acceptTokenClass(EHTokLeftAngle)) {
2744 // TODO: process annotations, just accepting them for now
2745 do {
2746 if (peekTokenClass(EHTokNone))
2747 return;
2748 if (acceptTokenClass(EHTokRightAngle))
2749 break;
2750 advanceToken();
2751 } while (true);
2752 } else
2753 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002754
John Kessenich630dd7d2016-06-12 23:52:12 -06002755 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002756}
2757
John Kesseniche01a9bc2016-03-12 20:11:22 -07002758} // end namespace glslang