blob: 30d42f108921126a7a078eeeeb38cf165da45f62 [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:
John Kessenich10f7fc72016-09-25 20:25:06 -0600494 qualifier.layoutMatrix = ElmColumnMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600495 break;
496 case EHTokColumnMajor:
John Kessenich10f7fc72016-09-25 20:25:06 -0600497 qualifier.layoutMatrix = ElmRowMajor;
John Kessenich630dd7d2016-06-12 23:52:12 -0600498 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 Kessenicha1e2d492016-09-20 13:22:58 -0600724// annotations
725// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
John Kessenich86f71382016-09-19 20:23:18 -0600726//
John Kessenicha1e2d492016-09-20 13:22:58 -0600727bool HlslGrammar::acceptAnnotations(TQualifier&)
John Kessenich86f71382016-09-19 20:23:18 -0600728{
John Kessenicha1e2d492016-09-20 13:22:58 -0600729 if (! acceptTokenClass(EHTokLeftAngle))
John Kessenich86f71382016-09-19 20:23:18 -0600730 return false;
731
John Kessenicha1e2d492016-09-20 13:22:58 -0600732 // note that we are nesting a name space
733 parseContext.nestAnnotations();
John Kessenich86f71382016-09-19 20:23:18 -0600734
735 // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
736 do {
737 // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
738 while (acceptTokenClass(EHTokSemicolon))
739 ;
740
741 if (acceptTokenClass(EHTokRightAngle))
John Kessenicha1e2d492016-09-20 13:22:58 -0600742 break;
John Kessenich86f71382016-09-19 20:23:18 -0600743
744 // declaration
745 TIntermNode* node;
746 if (! acceptDeclaration(node)) {
John Kessenicha1e2d492016-09-20 13:22:58 -0600747 expected("declaration in annotation");
John Kessenich86f71382016-09-19 20:23:18 -0600748 return false;
749 }
750 } while (true);
John Kessenicha1e2d492016-09-20 13:22:58 -0600751
752 parseContext.unnestAnnotations();
753 return true;
John Kessenich86f71382016-09-19 20:23:18 -0600754}
LoopDawg6daaa4f2016-06-23 19:13:48 -0600755
LoopDawg4886f692016-06-29 10:58:58 -0600756// sampler_type
757// : SAMPLER
758// | SAMPLER1D
759// | SAMPLER2D
760// | SAMPLER3D
761// | SAMPLERCUBE
762// | SAMPLERSTATE
763// | SAMPLERCOMPARISONSTATE
764bool HlslGrammar::acceptSamplerType(TType& type)
765{
766 // read sampler type
767 const EHlslTokenClass samplerType = peek();
768
LoopDawga78b0292016-07-19 14:28:05 -0600769 // TODO: for DX9
LoopDawg5d58fae2016-07-15 11:22:24 -0600770 // TSamplerDim dim = EsdNone;
LoopDawg4886f692016-06-29 10:58:58 -0600771
LoopDawga78b0292016-07-19 14:28:05 -0600772 bool isShadow = false;
773
LoopDawg4886f692016-06-29 10:58:58 -0600774 switch (samplerType) {
775 case EHTokSampler: break;
LoopDawg5d58fae2016-07-15 11:22:24 -0600776 case EHTokSampler1d: /*dim = Esd1D*/; break;
777 case EHTokSampler2d: /*dim = Esd2D*/; break;
778 case EHTokSampler3d: /*dim = Esd3D*/; break;
779 case EHTokSamplerCube: /*dim = EsdCube*/; break;
LoopDawg4886f692016-06-29 10:58:58 -0600780 case EHTokSamplerState: break;
LoopDawga78b0292016-07-19 14:28:05 -0600781 case EHTokSamplerComparisonState: isShadow = true; break;
LoopDawg4886f692016-06-29 10:58:58 -0600782 default:
783 return false; // not a sampler declaration
784 }
785
786 advanceToken(); // consume the sampler type keyword
787
788 TArraySizes* arraySizes = nullptr; // TODO: array
LoopDawg4886f692016-06-29 10:58:58 -0600789
790 TSampler sampler;
LoopDawga78b0292016-07-19 14:28:05 -0600791 sampler.setPureSampler(isShadow);
LoopDawg4886f692016-06-29 10:58:58 -0600792
793 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
794
795 return true;
796}
797
798// texture_type
799// | BUFFER
800// | TEXTURE1D
801// | TEXTURE1DARRAY
802// | TEXTURE2D
803// | TEXTURE2DARRAY
804// | TEXTURE3D
805// | TEXTURECUBE
806// | TEXTURECUBEARRAY
807// | TEXTURE2DMS
808// | TEXTURE2DMSARRAY
809bool HlslGrammar::acceptTextureType(TType& type)
810{
811 const EHlslTokenClass textureType = peek();
812
813 TSamplerDim dim = EsdNone;
814 bool array = false;
815 bool ms = false;
816
817 switch (textureType) {
818 case EHTokBuffer: dim = EsdBuffer; break;
819 case EHTokTexture1d: dim = Esd1D; break;
820 case EHTokTexture1darray: dim = Esd1D; array = true; break;
821 case EHTokTexture2d: dim = Esd2D; break;
822 case EHTokTexture2darray: dim = Esd2D; array = true; break;
823 case EHTokTexture3d: dim = Esd3D; break;
824 case EHTokTextureCube: dim = EsdCube; break;
825 case EHTokTextureCubearray: dim = EsdCube; array = true; break;
826 case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
827 case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
828 default:
829 return false; // not a texture declaration
830 }
831
832 advanceToken(); // consume the texture object keyword
833
834 TType txType(EbtFloat, EvqUniform, 4); // default type is float4
835
836 TIntermTyped* msCount = nullptr;
837
838 // texture type: required for multisample types!
839 if (acceptTokenClass(EHTokLeftAngle)) {
840 if (! acceptType(txType)) {
841 expected("scalar or vector type");
842 return false;
843 }
844
845 const TBasicType basicRetType = txType.getBasicType() ;
846
847 if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) {
848 unimplemented("basic type in texture");
849 return false;
850 }
851
steve-lunargd53f7172016-07-27 15:46:48 -0600852 // Buffers can handle small mats if they fit in 4 components
853 if (dim == EsdBuffer && txType.isMatrix()) {
854 if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
855 expected("components < 4 in matrix buffer type");
856 return false;
857 }
858
859 // TODO: except we don't handle it yet...
860 unimplemented("matrix type in buffer");
861 return false;
862 }
863
LoopDawg4886f692016-06-29 10:58:58 -0600864 if (!txType.isScalar() && !txType.isVector()) {
865 expected("scalar or vector type");
866 return false;
867 }
868
869 if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
870 // TODO: handle vec2/3 types
871 expected("vector size not yet supported in texture type");
872 return false;
873 }
874
875 if (ms && acceptTokenClass(EHTokComma)) {
876 // read sample count for multisample types, if given
877 if (! peekTokenClass(EHTokIntConstant)) {
878 expected("multisample count");
879 return false;
880 }
881
882 if (! acceptLiteral(msCount)) // should never fail, since we just found an integer
883 return false;
884 }
885
886 if (! acceptTokenClass(EHTokRightAngle)) {
887 expected("right angle bracket");
888 return false;
889 }
890 } else if (ms) {
891 expected("texture type for multisample");
892 return false;
893 }
894
895 TArraySizes* arraySizes = nullptr;
896 const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
897
898 TSampler sampler;
steve-lunargd53f7172016-07-27 15:46:48 -0600899
900 // Buffers are combined.
901 if (dim == EsdBuffer) {
902 sampler.set(txType.getBasicType(), dim, array);
903 } else {
904 // DX10 textures are separated. TODO: DX9.
905 sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
906 }
LoopDawg4886f692016-06-29 10:58:58 -0600907
908 type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
909
910 return true;
911}
912
913
John Kessenich87142c72016-03-12 20:24:24 -0700914// If token is for a type, update 'type' with the type information,
915// and return true and advance.
916// Otherwise, return false, and don't advance
917bool HlslGrammar::acceptType(TType& type)
918{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600919 switch (peek()) {
LoopDawg6daaa4f2016-06-23 19:13:48 -0600920 case EHTokVector:
921 return acceptVectorTemplateType(type);
922 break;
923
924 case EHTokMatrix:
925 return acceptMatrixTemplateType(type);
926 break;
927
LoopDawg4886f692016-06-29 10:58:58 -0600928 case EHTokSampler: // fall through
929 case EHTokSampler1d: // ...
930 case EHTokSampler2d: // ...
931 case EHTokSampler3d: // ...
932 case EHTokSamplerCube: // ...
933 case EHTokSamplerState: // ...
934 case EHTokSamplerComparisonState: // ...
935 return acceptSamplerType(type);
936 break;
937
938 case EHTokBuffer: // fall through
939 case EHTokTexture1d: // ...
940 case EHTokTexture1darray: // ...
941 case EHTokTexture2d: // ...
942 case EHTokTexture2darray: // ...
943 case EHTokTexture3d: // ...
944 case EHTokTextureCube: // ...
945 case EHTokTextureCubearray: // ...
946 case EHTokTexture2DMS: // ...
947 case EHTokTexture2DMSarray: // ...
948 return acceptTextureType(type);
949 break;
950
John Kesseniche6e74942016-06-11 16:43:14 -0600951 case EHTokStruct:
John Kessenich3d157c52016-07-25 16:05:33 -0600952 case EHTokCBuffer:
953 case EHTokTBuffer:
John Kesseniche6e74942016-06-11 16:43:14 -0600954 return acceptStruct(type);
955 break;
956
957 case EHTokIdentifier:
958 // An identifier could be for a user-defined type.
959 // Note we cache the symbol table lookup, to save for a later rule
960 // when this is not a type.
961 token.symbol = parseContext.symbolTable.find(*token.string);
962 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
963 type.shallowCopy(token.symbol->getType());
964 advanceToken();
965 return true;
966 } else
967 return false;
968
John Kessenich71351de2016-06-08 12:50:56 -0600969 case EHTokVoid:
970 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700971 break;
John Kessenich71351de2016-06-08 12:50:56 -0600972
John Kessenicha1e2d492016-09-20 13:22:58 -0600973 case EHTokString:
974 new(&type) TType(EbtString);
975 break;
976
John Kessenich87142c72016-03-12 20:24:24 -0700977 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600978 new(&type) TType(EbtFloat);
979 break;
John Kessenich87142c72016-03-12 20:24:24 -0700980 case EHTokFloat1:
981 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600982 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700983 break;
John Kessenich87142c72016-03-12 20:24:24 -0700984 case EHTokFloat2:
985 new(&type) TType(EbtFloat, EvqTemporary, 2);
986 break;
987 case EHTokFloat3:
988 new(&type) TType(EbtFloat, EvqTemporary, 3);
989 break;
990 case EHTokFloat4:
991 new(&type) TType(EbtFloat, EvqTemporary, 4);
992 break;
993
John Kessenich71351de2016-06-08 12:50:56 -0600994 case EHTokDouble:
995 new(&type) TType(EbtDouble);
996 break;
997 case EHTokDouble1:
998 new(&type) TType(EbtDouble);
999 type.makeVector();
1000 break;
1001 case EHTokDouble2:
1002 new(&type) TType(EbtDouble, EvqTemporary, 2);
1003 break;
1004 case EHTokDouble3:
1005 new(&type) TType(EbtDouble, EvqTemporary, 3);
1006 break;
1007 case EHTokDouble4:
1008 new(&type) TType(EbtDouble, EvqTemporary, 4);
1009 break;
1010
1011 case EHTokInt:
1012 case EHTokDword:
1013 new(&type) TType(EbtInt);
1014 break;
1015 case EHTokInt1:
1016 new(&type) TType(EbtInt);
1017 type.makeVector();
1018 break;
John Kessenich87142c72016-03-12 20:24:24 -07001019 case EHTokInt2:
1020 new(&type) TType(EbtInt, EvqTemporary, 2);
1021 break;
1022 case EHTokInt3:
1023 new(&type) TType(EbtInt, EvqTemporary, 3);
1024 break;
1025 case EHTokInt4:
1026 new(&type) TType(EbtInt, EvqTemporary, 4);
1027 break;
1028
John Kessenich71351de2016-06-08 12:50:56 -06001029 case EHTokUint:
1030 new(&type) TType(EbtUint);
1031 break;
1032 case EHTokUint1:
1033 new(&type) TType(EbtUint);
1034 type.makeVector();
1035 break;
1036 case EHTokUint2:
1037 new(&type) TType(EbtUint, EvqTemporary, 2);
1038 break;
1039 case EHTokUint3:
1040 new(&type) TType(EbtUint, EvqTemporary, 3);
1041 break;
1042 case EHTokUint4:
1043 new(&type) TType(EbtUint, EvqTemporary, 4);
1044 break;
1045
LoopDawg6daaa4f2016-06-23 19:13:48 -06001046
John Kessenich71351de2016-06-08 12:50:56 -06001047 case EHTokBool:
1048 new(&type) TType(EbtBool);
1049 break;
1050 case EHTokBool1:
1051 new(&type) TType(EbtBool);
1052 type.makeVector();
1053 break;
John Kessenich87142c72016-03-12 20:24:24 -07001054 case EHTokBool2:
1055 new(&type) TType(EbtBool, EvqTemporary, 2);
1056 break;
1057 case EHTokBool3:
1058 new(&type) TType(EbtBool, EvqTemporary, 3);
1059 break;
1060 case EHTokBool4:
1061 new(&type) TType(EbtBool, EvqTemporary, 4);
1062 break;
1063
John Kessenich0133c122016-05-20 12:17:26 -06001064 case EHTokInt1x1:
1065 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1066 break;
1067 case EHTokInt1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001068 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001069 break;
1070 case EHTokInt1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001071 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001072 break;
1073 case EHTokInt1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001074 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001075 break;
1076 case EHTokInt2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001077 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001078 break;
1079 case EHTokInt2x2:
1080 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1081 break;
1082 case EHTokInt2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001083 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001084 break;
1085 case EHTokInt2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001086 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001087 break;
1088 case EHTokInt3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001089 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001090 break;
1091 case EHTokInt3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001092 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001093 break;
1094 case EHTokInt3x3:
1095 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1096 break;
1097 case EHTokInt3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001098 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001099 break;
1100 case EHTokInt4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001101 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001102 break;
1103 case EHTokInt4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001104 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001105 break;
1106 case EHTokInt4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001107 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001108 break;
1109 case EHTokInt4x4:
1110 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1111 break;
1112
John Kessenich71351de2016-06-08 12:50:56 -06001113 case EHTokUint1x1:
1114 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1115 break;
1116 case EHTokUint1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001117 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001118 break;
1119 case EHTokUint1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001120 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001121 break;
1122 case EHTokUint1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001123 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001124 break;
1125 case EHTokUint2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001126 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001127 break;
1128 case EHTokUint2x2:
1129 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1130 break;
1131 case EHTokUint2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001132 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001133 break;
1134 case EHTokUint2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001135 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001136 break;
1137 case EHTokUint3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001138 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001139 break;
1140 case EHTokUint3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001141 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001142 break;
1143 case EHTokUint3x3:
1144 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1145 break;
1146 case EHTokUint3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001147 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001148 break;
1149 case EHTokUint4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001150 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001151 break;
1152 case EHTokUint4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001153 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001154 break;
1155 case EHTokUint4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001156 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001157 break;
1158 case EHTokUint4x4:
1159 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1160 break;
1161
1162 case EHTokBool1x1:
1163 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1164 break;
1165 case EHTokBool1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001166 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001167 break;
1168 case EHTokBool1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001169 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001170 break;
1171 case EHTokBool1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001172 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001173 break;
1174 case EHTokBool2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001175 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001176 break;
1177 case EHTokBool2x2:
1178 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1179 break;
1180 case EHTokBool2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001181 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001182 break;
1183 case EHTokBool2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001184 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001185 break;
1186 case EHTokBool3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001187 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001188 break;
1189 case EHTokBool3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001190 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001191 break;
1192 case EHTokBool3x3:
1193 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1194 break;
1195 case EHTokBool3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001196 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
John Kessenich71351de2016-06-08 12:50:56 -06001197 break;
1198 case EHTokBool4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001199 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
John Kessenich71351de2016-06-08 12:50:56 -06001200 break;
1201 case EHTokBool4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001202 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
John Kessenich71351de2016-06-08 12:50:56 -06001203 break;
1204 case EHTokBool4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001205 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
John Kessenich71351de2016-06-08 12:50:56 -06001206 break;
1207 case EHTokBool4x4:
1208 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1209 break;
1210
John Kessenich0133c122016-05-20 12:17:26 -06001211 case EHTokFloat1x1:
1212 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1213 break;
1214 case EHTokFloat1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001215 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001216 break;
1217 case EHTokFloat1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001218 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001219 break;
1220 case EHTokFloat1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001221 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001222 break;
1223 case EHTokFloat2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001224 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001225 break;
John Kessenich87142c72016-03-12 20:24:24 -07001226 case EHTokFloat2x2:
1227 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1228 break;
1229 case EHTokFloat2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001230 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001231 break;
1232 case EHTokFloat2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001233 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001234 break;
John Kessenich0133c122016-05-20 12:17:26 -06001235 case EHTokFloat3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001236 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001237 break;
John Kessenich87142c72016-03-12 20:24:24 -07001238 case EHTokFloat3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001239 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001240 break;
1241 case EHTokFloat3x3:
1242 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1243 break;
1244 case EHTokFloat3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001245 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
John Kessenich87142c72016-03-12 20:24:24 -07001246 break;
John Kessenich0133c122016-05-20 12:17:26 -06001247 case EHTokFloat4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001248 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001249 break;
John Kessenich87142c72016-03-12 20:24:24 -07001250 case EHTokFloat4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001251 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
John Kessenich87142c72016-03-12 20:24:24 -07001252 break;
1253 case EHTokFloat4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001254 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
John Kessenich87142c72016-03-12 20:24:24 -07001255 break;
1256 case EHTokFloat4x4:
1257 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1258 break;
1259
John Kessenich0133c122016-05-20 12:17:26 -06001260 case EHTokDouble1x1:
1261 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
1262 break;
1263 case EHTokDouble1x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001264 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001265 break;
1266 case EHTokDouble1x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001267 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001268 break;
1269 case EHTokDouble1x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001270 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001271 break;
1272 case EHTokDouble2x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001273 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001274 break;
1275 case EHTokDouble2x2:
1276 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
1277 break;
1278 case EHTokDouble2x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001279 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001280 break;
1281 case EHTokDouble2x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001282 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001283 break;
1284 case EHTokDouble3x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001285 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001286 break;
1287 case EHTokDouble3x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001288 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001289 break;
1290 case EHTokDouble3x3:
1291 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
1292 break;
1293 case EHTokDouble3x4:
steve-lunarg297ae212016-08-24 14:36:13 -06001294 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
John Kessenich0133c122016-05-20 12:17:26 -06001295 break;
1296 case EHTokDouble4x1:
steve-lunarg297ae212016-08-24 14:36:13 -06001297 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
John Kessenich0133c122016-05-20 12:17:26 -06001298 break;
1299 case EHTokDouble4x2:
steve-lunarg297ae212016-08-24 14:36:13 -06001300 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
John Kessenich0133c122016-05-20 12:17:26 -06001301 break;
1302 case EHTokDouble4x3:
steve-lunarg297ae212016-08-24 14:36:13 -06001303 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
John Kessenich0133c122016-05-20 12:17:26 -06001304 break;
1305 case EHTokDouble4x4:
1306 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
1307 break;
1308
John Kessenich87142c72016-03-12 20:24:24 -07001309 default:
1310 return false;
1311 }
1312
1313 advanceToken();
1314
1315 return true;
1316}
1317
John Kesseniche6e74942016-06-11 16:43:14 -06001318// struct
John Kessenich3d157c52016-07-25 16:05:33 -06001319// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1320// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
1321//
1322// struct_type
1323// : STRUCT
1324// | CBUFFER
1325// | TBUFFER
John Kesseniche6e74942016-06-11 16:43:14 -06001326//
1327bool HlslGrammar::acceptStruct(TType& type)
1328{
John Kessenichb804de62016-09-05 12:19:18 -06001329 // This storage qualifier will tell us whether it's an AST
1330 // block type or just a generic structure type.
1331 TStorageQualifier storageQualifier = EvqTemporary;
John Kessenich3d157c52016-07-25 16:05:33 -06001332
1333 // CBUFFER
1334 if (acceptTokenClass(EHTokCBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001335 storageQualifier = EvqUniform;
John Kessenich3d157c52016-07-25 16:05:33 -06001336 // TBUFFER
1337 else if (acceptTokenClass(EHTokTBuffer))
John Kessenichb804de62016-09-05 12:19:18 -06001338 storageQualifier = EvqBuffer;
John Kesseniche6e74942016-06-11 16:43:14 -06001339 // STRUCT
John Kessenich3d157c52016-07-25 16:05:33 -06001340 else if (! acceptTokenClass(EHTokStruct))
John Kesseniche6e74942016-06-11 16:43:14 -06001341 return false;
1342
1343 // IDENTIFIER
1344 TString structName = "";
1345 if (peekTokenClass(EHTokIdentifier)) {
1346 structName = *token.string;
1347 advanceToken();
1348 }
1349
John Kessenich3d157c52016-07-25 16:05:33 -06001350 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001351 TQualifier postDeclQualifier;
1352 postDeclQualifier.clear();
1353 acceptPostDecls(postDeclQualifier);
John Kessenich3d157c52016-07-25 16:05:33 -06001354
John Kesseniche6e74942016-06-11 16:43:14 -06001355 // LEFT_BRACE
1356 if (! acceptTokenClass(EHTokLeftBrace)) {
1357 expected("{");
1358 return false;
1359 }
1360
1361 // struct_declaration_list
1362 TTypeList* typeList;
1363 if (! acceptStructDeclarationList(typeList)) {
1364 expected("struct member declarations");
1365 return false;
1366 }
1367
1368 // RIGHT_BRACE
1369 if (! acceptTokenClass(EHTokRightBrace)) {
1370 expected("}");
1371 return false;
1372 }
1373
1374 // create the user-defined type
John Kessenichb804de62016-09-05 12:19:18 -06001375 if (storageQualifier == EvqTemporary)
John Kessenich3d157c52016-07-25 16:05:33 -06001376 new(&type) TType(typeList, structName);
John Kessenichb804de62016-09-05 12:19:18 -06001377 else {
John Kessenich7735b942016-09-05 12:40:06 -06001378 postDeclQualifier.storage = storageQualifier;
1379 new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
John Kessenichb804de62016-09-05 12:19:18 -06001380 }
John Kesseniche6e74942016-06-11 16:43:14 -06001381
John Kessenich3d157c52016-07-25 16:05:33 -06001382 // If it was named, which means the type can be reused later, add
1383 // it to the symbol table. (Unless it's a block, in which
1384 // case the name is not a type.)
1385 if (type.getBasicType() != EbtBlock && structName.size() > 0) {
John Kesseniche6e74942016-06-11 16:43:14 -06001386 TVariable* userTypeDef = new TVariable(&structName, type, true);
1387 if (! parseContext.symbolTable.insert(*userTypeDef))
1388 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
1389 }
1390
1391 return true;
1392}
1393
1394// struct_declaration_list
1395// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
1396//
1397// struct_declaration
1398// : fully_specified_type struct_declarator COMMA struct_declarator ...
1399//
1400// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -06001401// : IDENTIFIER post_decls
1402// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -06001403//
1404bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
1405{
1406 typeList = new TTypeList();
1407
1408 do {
1409 // success on seeing the RIGHT_BRACE coming up
1410 if (peekTokenClass(EHTokRightBrace))
1411 return true;
1412
1413 // struct_declaration
1414
1415 // fully_specified_type
1416 TType memberType;
1417 if (! acceptFullySpecifiedType(memberType)) {
1418 expected("member type");
1419 return false;
1420 }
1421
1422 // struct_declarator COMMA struct_declarator ...
1423 do {
1424 // peek IDENTIFIER
1425 if (! peekTokenClass(EHTokIdentifier)) {
1426 expected("member name");
1427 return false;
1428 }
1429
1430 // add it to the list of members
1431 TTypeLoc member = { new TType(EbtVoid), token.loc };
1432 member.type->shallowCopy(memberType);
1433 member.type->setFieldName(*token.string);
1434 typeList->push_back(member);
1435
1436 // accept IDENTIFIER
1437 advanceToken();
1438
1439 // array_specifier
John Kessenich19b92ff2016-06-19 11:50:34 -06001440 TArraySizes* arraySizes = nullptr;
1441 acceptArraySpecifier(arraySizes);
1442 if (arraySizes)
1443 typeList->back().type->newArraySizes(*arraySizes);
John Kesseniche6e74942016-06-11 16:43:14 -06001444
John Kessenich7735b942016-09-05 12:40:06 -06001445 acceptPostDecls(member.type->getQualifier());
John Kessenich630dd7d2016-06-12 23:52:12 -06001446
John Kesseniche6e74942016-06-11 16:43:14 -06001447 // success on seeing the SEMICOLON coming up
1448 if (peekTokenClass(EHTokSemicolon))
1449 break;
1450
1451 // COMMA
1452 if (! acceptTokenClass(EHTokComma)) {
1453 expected(",");
1454 return false;
1455 }
1456
1457 } while (true);
1458
1459 // SEMI_COLON
1460 if (! acceptTokenClass(EHTokSemicolon)) {
1461 expected(";");
1462 return false;
1463 }
1464
1465 } while (true);
1466}
1467
John Kessenich5f934b02016-03-13 17:58:25 -06001468// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -06001469// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -06001470// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001471//
1472bool HlslGrammar::acceptFunctionParameters(TFunction& function)
1473{
John Kessenich078d7f22016-03-14 10:02:11 -06001474 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001475 if (! acceptTokenClass(EHTokLeftParen))
1476 return false;
1477
John Kessenich71351de2016-06-08 12:50:56 -06001478 // VOID RIGHT_PAREN
1479 if (! acceptTokenClass(EHTokVoid)) {
1480 do {
1481 // parameter_declaration
1482 if (! acceptParameterDeclaration(function))
1483 break;
John Kessenich5f934b02016-03-13 17:58:25 -06001484
John Kessenich71351de2016-06-08 12:50:56 -06001485 // COMMA
1486 if (! acceptTokenClass(EHTokComma))
1487 break;
1488 } while (true);
1489 }
John Kessenich5f934b02016-03-13 17:58:25 -06001490
John Kessenich078d7f22016-03-14 10:02:11 -06001491 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -06001492 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001493 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -06001494 return false;
1495 }
1496
1497 return true;
1498}
1499
1500// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -06001501// : fully_specified_type post_decls
John Kessenich19b92ff2016-06-19 11:50:34 -06001502// | fully_specified_type identifier array_specifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -06001503//
1504bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
1505{
1506 // fully_specified_type
1507 TType* type = new TType;
1508 if (! acceptFullySpecifiedType(*type))
1509 return false;
1510
1511 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -06001512 HlslToken idToken;
1513 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -06001514
John Kessenich19b92ff2016-06-19 11:50:34 -06001515 // array_specifier
1516 TArraySizes* arraySizes = nullptr;
1517 acceptArraySpecifier(arraySizes);
1518 if (arraySizes)
1519 type->newArraySizes(*arraySizes);
1520
1521 // post_decls
John Kessenich7735b942016-09-05 12:40:06 -06001522 acceptPostDecls(type->getQualifier());
John Kessenichc3387d32016-06-17 14:21:02 -06001523
John Kessenich5aa59e22016-06-17 15:50:47 -06001524 parseContext.paramFix(*type);
1525
John Kessenichaecd4972016-03-14 10:46:34 -06001526 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -06001527 function.addParameter(param);
1528
1529 return true;
1530}
1531
1532// Do the work to create the function definition in addition to
1533// parsing the body (compound_statement).
1534bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
1535{
John Kessenicha3051662016-09-02 19:13:36 -06001536 TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
John Kessenich1a4b7752016-09-02 19:05:24 -06001537 TSourceLoc loc = token.loc;
John Kessenich5f934b02016-03-13 17:58:25 -06001538
John Kessenich077e0522016-06-09 02:02:17 -06001539 // This does a pushScope()
John Kessenicha3051662016-09-02 19:13:36 -06001540 node = parseContext.handleFunctionDefinition(loc, functionDeclarator);
John Kessenich5f934b02016-03-13 17:58:25 -06001541
1542 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001543 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001544 if (acceptCompoundStatement(functionBody)) {
John Kessenicha3051662016-09-02 19:13:36 -06001545 parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
John Kessenich5f934b02016-03-13 17:58:25 -06001546 return true;
1547 }
1548
1549 return false;
1550}
1551
John Kessenich0d2b6de2016-06-05 11:23:11 -06001552// Accept an expression with parenthesis around it, where
1553// the parenthesis ARE NOT expression parenthesis, but the
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001554// syntactically required ones like in "if ( expression )".
1555//
1556// Also accepts a declaration expression; "if (int a = expression)".
John Kessenich0d2b6de2016-06-05 11:23:11 -06001557//
1558// Note this one is not set up to be speculative; as it gives
1559// errors if not found.
1560//
1561bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
1562{
1563 // LEFT_PAREN
1564 if (! acceptTokenClass(EHTokLeftParen))
1565 expected("(");
1566
John Kessenich5bc4d9a2016-06-20 01:22:38 -06001567 bool decl = false;
1568 TIntermNode* declNode = nullptr;
1569 decl = acceptControlDeclaration(declNode);
1570 if (decl) {
1571 if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
1572 expected("initialized declaration");
1573 return false;
1574 } else
1575 expression = declNode->getAsTyped();
1576 } else {
1577 // no declaration
1578 if (! acceptExpression(expression)) {
1579 expected("expression");
1580 return false;
1581 }
John Kessenich0d2b6de2016-06-05 11:23:11 -06001582 }
1583
1584 // RIGHT_PAREN
1585 if (! acceptTokenClass(EHTokRightParen))
1586 expected(")");
1587
1588 return true;
1589}
1590
John Kessenich34fb0362016-05-03 23:17:20 -06001591// The top-level full expression recognizer.
1592//
John Kessenich87142c72016-03-12 20:24:24 -07001593// expression
John Kessenich34fb0362016-05-03 23:17:20 -06001594// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -07001595//
1596bool HlslGrammar::acceptExpression(TIntermTyped*& node)
1597{
LoopDawgef764a22016-06-03 09:17:51 -06001598 node = nullptr;
1599
John Kessenich34fb0362016-05-03 23:17:20 -06001600 // assignment_expression
1601 if (! acceptAssignmentExpression(node))
1602 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001603
John Kessenich34fb0362016-05-03 23:17:20 -06001604 if (! peekTokenClass(EHTokComma))
1605 return true;
1606
1607 do {
1608 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -06001609 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -06001610 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -06001611
John Kessenich34fb0362016-05-03 23:17:20 -06001612 // ... assignment_expression
1613 TIntermTyped* rightNode = nullptr;
1614 if (! acceptAssignmentExpression(rightNode)) {
1615 expected("assignment expression");
1616 return false;
John Kessenich5f934b02016-03-13 17:58:25 -06001617 }
1618
John Kessenich34fb0362016-05-03 23:17:20 -06001619 node = intermediate.addComma(node, rightNode, loc);
1620
1621 if (! peekTokenClass(EHTokComma))
1622 return true;
1623 } while (true);
1624}
1625
John Kessenich07354242016-07-01 19:58:06 -06001626// initializer
1627// : LEFT_BRACE initializer_list RIGHT_BRACE
1628//
1629// initializer_list
1630// : assignment_expression COMMA assignment_expression COMMA ...
1631//
1632bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
1633{
1634 // LEFT_BRACE
1635 if (! acceptTokenClass(EHTokLeftBrace))
1636 return false;
1637
1638 // initializer_list
1639 TSourceLoc loc = token.loc;
1640 node = nullptr;
1641 do {
1642 // assignment_expression
1643 TIntermTyped* expr;
1644 if (! acceptAssignmentExpression(expr)) {
1645 expected("assignment expression in initializer list");
1646 return false;
1647 }
1648 node = intermediate.growAggregate(node, expr, loc);
1649
1650 // COMMA
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001651 if (acceptTokenClass(EHTokComma)) {
1652 if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma
1653 return true;
John Kessenich07354242016-07-01 19:58:06 -06001654 continue;
steve-lunargfe5a3ff2016-07-30 10:36:09 -06001655 }
John Kessenich07354242016-07-01 19:58:06 -06001656
1657 // RIGHT_BRACE
1658 if (acceptTokenClass(EHTokRightBrace))
1659 return true;
1660
1661 expected(", or }");
1662 return false;
1663 } while (true);
1664}
1665
John Kessenich34fb0362016-05-03 23:17:20 -06001666// Accept an assignment expression, where assignment operations
John Kessenich07354242016-07-01 19:58:06 -06001667// associate right-to-left. That is, it is implicit, for example
John Kessenich34fb0362016-05-03 23:17:20 -06001668//
1669// a op (b op (c op d))
1670//
1671// assigment_expression
John Kessenich00957f82016-07-27 10:39:57 -06001672// : initializer
1673// | conditional_expression
1674// | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
John Kessenich34fb0362016-05-03 23:17:20 -06001675//
1676bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
1677{
John Kessenich07354242016-07-01 19:58:06 -06001678 // initializer
1679 if (peekTokenClass(EHTokLeftBrace)) {
1680 if (acceptInitializer(node))
1681 return true;
1682
1683 expected("initializer");
1684 return false;
1685 }
1686
John Kessenich00957f82016-07-27 10:39:57 -06001687 // conditional_expression
1688 if (! acceptConditionalExpression(node))
John Kessenich34fb0362016-05-03 23:17:20 -06001689 return false;
1690
John Kessenich07354242016-07-01 19:58:06 -06001691 // assignment operation?
John Kessenich34fb0362016-05-03 23:17:20 -06001692 TOperator assignOp = HlslOpMap::assignment(peek());
1693 if (assignOp == EOpNull)
1694 return true;
1695
John Kessenich00957f82016-07-27 10:39:57 -06001696 // assign_op
John Kessenich34fb0362016-05-03 23:17:20 -06001697 TSourceLoc loc = token.loc;
1698 advanceToken();
1699
John Kessenich00957f82016-07-27 10:39:57 -06001700 // conditional_expression assign_op conditional_expression ...
1701 // Done by recursing this function, which automatically
John Kessenich34fb0362016-05-03 23:17:20 -06001702 // gets the right-to-left associativity.
1703 TIntermTyped* rightNode = nullptr;
1704 if (! acceptAssignmentExpression(rightNode)) {
1705 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -06001706 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001707 }
1708
John Kessenichd21baed2016-09-16 03:05:12 -06001709 node = parseContext.handleAssign(loc, assignOp, node, rightNode);
John Kessenichfea226b2016-07-28 17:53:56 -06001710 if (node == nullptr) {
1711 parseContext.error(loc, "could not create assignment", "", "");
1712 return false;
1713 }
John Kessenich34fb0362016-05-03 23:17:20 -06001714
1715 if (! peekTokenClass(EHTokComma))
1716 return true;
1717
1718 return true;
1719}
1720
John Kessenich00957f82016-07-27 10:39:57 -06001721// Accept a conditional expression, which associates right-to-left,
1722// accomplished by the "true" expression calling down to lower
1723// precedence levels than this level.
1724//
1725// conditional_expression
1726// : binary_expression
1727// | binary_expression QUESTION expression COLON assignment_expression
1728//
1729bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
1730{
1731 // binary_expression
1732 if (! acceptBinaryExpression(node, PlLogicalOr))
1733 return false;
1734
1735 if (! acceptTokenClass(EHTokQuestion))
1736 return true;
1737
1738 TIntermTyped* trueNode = nullptr;
1739 if (! acceptExpression(trueNode)) {
1740 expected("expression after ?");
1741 return false;
1742 }
1743 TSourceLoc loc = token.loc;
1744
1745 if (! acceptTokenClass(EHTokColon)) {
1746 expected(":");
1747 return false;
1748 }
1749
1750 TIntermTyped* falseNode = nullptr;
1751 if (! acceptAssignmentExpression(falseNode)) {
1752 expected("expression after :");
1753 return false;
1754 }
1755
1756 node = intermediate.addSelection(node, trueNode, falseNode, loc);
1757
1758 return true;
1759}
1760
John Kessenich34fb0362016-05-03 23:17:20 -06001761// Accept a binary expression, for binary operations that
1762// associate left-to-right. This is, it is implicit, for example
1763//
1764// ((a op b) op c) op d
1765//
1766// binary_expression
1767// : expression op expression op expression ...
1768//
1769// where 'expression' is the next higher level in precedence.
1770//
1771bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
1772{
1773 if (precedenceLevel > PlMul)
1774 return acceptUnaryExpression(node);
1775
1776 // assignment_expression
1777 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
1778 return false;
1779
John Kessenich34fb0362016-05-03 23:17:20 -06001780 do {
John Kessenich64076ed2016-07-28 21:43:17 -06001781 TOperator op = HlslOpMap::binary(peek());
1782 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
1783 if (tokenLevel < precedenceLevel)
1784 return true;
1785
John Kessenich34fb0362016-05-03 23:17:20 -06001786 // ... op
1787 TSourceLoc loc = token.loc;
1788 advanceToken();
1789
1790 // ... expression
1791 TIntermTyped* rightNode = nullptr;
1792 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
1793 expected("expression");
1794 return false;
1795 }
1796
1797 node = intermediate.addBinaryMath(op, node, rightNode, loc);
John Kessenichfea226b2016-07-28 17:53:56 -06001798 if (node == nullptr) {
1799 parseContext.error(loc, "Could not perform requested binary operation", "", "");
1800 return false;
1801 }
John Kessenich34fb0362016-05-03 23:17:20 -06001802 } while (true);
1803}
1804
1805// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -06001806// : (type) unary_expression
1807// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -06001808// | - unary_expression
1809// | ! unary_expression
1810// | ~ unary_expression
1811// | ++ unary_expression
1812// | -- unary_expression
1813// | postfix_expression
1814//
1815bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
1816{
John Kessenich1cc1a282016-06-03 16:55:49 -06001817 // (type) unary_expression
1818 // Have to look two steps ahead, because this could be, e.g., a
1819 // postfix_expression instead, since that also starts with at "(".
1820 if (acceptTokenClass(EHTokLeftParen)) {
1821 TType castType;
1822 if (acceptType(castType)) {
steve-lunarg5964c642016-07-30 07:38:55 -06001823 if (acceptTokenClass(EHTokRightParen)) {
1824 // We've matched "(type)" now, get the expression to cast
1825 TSourceLoc loc = token.loc;
1826 if (! acceptUnaryExpression(node))
1827 return false;
1828
1829 // Hook it up like a constructor
1830 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
1831 if (constructorFunction == nullptr) {
1832 expected("type that can be constructed");
1833 return false;
1834 }
1835 TIntermTyped* arguments = nullptr;
1836 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
1837 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
1838
1839 return true;
1840 } else {
1841 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
1842 // the '(int' part. We must back up twice.
1843 recedeToken();
1844 recedeToken();
John Kessenich1cc1a282016-06-03 16:55:49 -06001845 }
John Kessenich1cc1a282016-06-03 16:55:49 -06001846 } else {
1847 // This isn't a type cast, but it still started "(", so if it is a
1848 // unary expression, it can only be a postfix_expression, so try that.
1849 // Back it up first.
1850 recedeToken();
1851 return acceptPostfixExpression(node);
1852 }
1853 }
1854
1855 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001856 TOperator unaryOp = HlslOpMap::preUnary(peek());
1857
John Kessenich1cc1a282016-06-03 16:55:49 -06001858 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001859 if (unaryOp == EOpNull)
1860 return acceptPostfixExpression(node);
1861
1862 // op unary_expression
1863 TSourceLoc loc = token.loc;
1864 advanceToken();
1865 if (! acceptUnaryExpression(node))
1866 return false;
1867
1868 // + is a no-op
1869 if (unaryOp == EOpAdd)
1870 return true;
1871
1872 node = intermediate.addUnaryMath(unaryOp, node, loc);
1873
1874 return node != nullptr;
1875}
1876
1877// postfix_expression
1878// : LEFT_PAREN expression RIGHT_PAREN
1879// | literal
1880// | constructor
1881// | identifier
1882// | function_call
1883// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1884// | postfix_expression DOT IDENTIFIER
1885// | postfix_expression INC_OP
1886// | postfix_expression DEC_OP
1887//
1888bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1889{
1890 // Not implemented as self-recursive:
1891 // The logical "right recursion" is done with an loop at the end
1892
1893 // idToken will pick up either a variable or a function name in a function call
1894 HlslToken idToken;
1895
John Kessenich21472ae2016-06-04 11:46:33 -06001896 // Find something before the postfix operations, as they can't operate
1897 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001898 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001899 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001900 if (! acceptExpression(node)) {
1901 expected("expression");
1902 return false;
1903 }
1904 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001905 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001906 return false;
1907 }
John Kessenich34fb0362016-05-03 23:17:20 -06001908 } else if (acceptLiteral(node)) {
1909 // literal (nothing else to do yet), go on to the
1910 } else if (acceptConstructor(node)) {
1911 // constructor (nothing else to do yet)
1912 } else if (acceptIdentifier(idToken)) {
1913 // identifier or function_call name
1914 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001915 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001916 } else if (acceptFunctionCall(idToken, node)) {
1917 // function_call (nothing else to do yet)
1918 } else {
1919 expected("function call arguments");
1920 return false;
1921 }
John Kessenich21472ae2016-06-04 11:46:33 -06001922 } else {
1923 // nothing found, can't post operate
1924 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001925 }
1926
John Kessenich21472ae2016-06-04 11:46:33 -06001927 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001928 do {
1929 TSourceLoc loc = token.loc;
1930 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001931
John Kessenich34fb0362016-05-03 23:17:20 -06001932 // Consume only a valid post-unary operator, otherwise we are done.
1933 switch (postOp) {
1934 case EOpIndexDirectStruct:
1935 case EOpIndexIndirect:
1936 case EOpPostIncrement:
1937 case EOpPostDecrement:
1938 advanceToken();
1939 break;
1940 default:
1941 return true;
1942 }
John Kessenich87142c72016-03-12 20:24:24 -07001943
John Kessenich34fb0362016-05-03 23:17:20 -06001944 // We have a valid post-unary operator, process it.
1945 switch (postOp) {
1946 case EOpIndexDirectStruct:
John Kessenich93a162a2016-06-17 17:16:27 -06001947 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001948 // DOT IDENTIFIER
1949 // includes swizzles and struct members
John Kessenich93a162a2016-06-17 17:16:27 -06001950 HlslToken field;
1951 if (! acceptIdentifier(field)) {
1952 expected("swizzle or member");
1953 return false;
1954 }
LoopDawg4886f692016-06-29 10:58:58 -06001955
1956 TIntermTyped* base = node; // preserve for method function calls
John Kessenich93a162a2016-06-17 17:16:27 -06001957 node = parseContext.handleDotDereference(field.loc, node, *field.string);
LoopDawg4886f692016-06-29 10:58:58 -06001958
1959 // In the event of a method node, we look for an open paren and accept the function call.
1960 if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
1961 if (! acceptFunctionCall(field, node, base)) {
1962 expected("function parameters");
1963 return false;
1964 }
1965 }
1966
John Kessenich34fb0362016-05-03 23:17:20 -06001967 break;
John Kessenich93a162a2016-06-17 17:16:27 -06001968 }
John Kessenich34fb0362016-05-03 23:17:20 -06001969 case EOpIndexIndirect:
1970 {
John Kessenich19b92ff2016-06-19 11:50:34 -06001971 // LEFT_BRACKET integer_expression RIGHT_BRACKET
John Kessenich34fb0362016-05-03 23:17:20 -06001972 TIntermTyped* indexNode = nullptr;
1973 if (! acceptExpression(indexNode) ||
1974 ! peekTokenClass(EHTokRightBracket)) {
1975 expected("expression followed by ']'");
1976 return false;
1977 }
John Kessenich19b92ff2016-06-19 11:50:34 -06001978 advanceToken();
1979 node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
1980 break;
John Kessenich34fb0362016-05-03 23:17:20 -06001981 }
1982 case EOpPostIncrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001983 // INC_OP
1984 // fall through
John Kessenich34fb0362016-05-03 23:17:20 -06001985 case EOpPostDecrement:
John Kessenich19b92ff2016-06-19 11:50:34 -06001986 // DEC_OP
John Kessenich34fb0362016-05-03 23:17:20 -06001987 node = intermediate.addUnaryMath(postOp, node, loc);
1988 break;
1989 default:
1990 assert(0);
1991 break;
1992 }
1993 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001994}
1995
John Kessenichd016be12016-03-13 11:24:20 -06001996// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001997// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001998//
1999bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
2000{
2001 // type
2002 TType type;
2003 if (acceptType(type)) {
2004 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
2005 if (constructorFunction == nullptr)
2006 return false;
2007
2008 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06002009 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06002010 if (! acceptArguments(constructorFunction, arguments)) {
2011 expected("constructor arguments");
2012 return false;
2013 }
2014
2015 // hook it up
2016 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
2017
2018 return true;
2019 }
2020
2021 return false;
2022}
2023
John Kessenich34fb0362016-05-03 23:17:20 -06002024// The function_call identifier was already recognized, and passed in as idToken.
2025//
2026// function_call
2027// : [idToken] arguments
2028//
LoopDawg4886f692016-06-29 10:58:58 -06002029bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node, TIntermTyped* base)
John Kessenich34fb0362016-05-03 23:17:20 -06002030{
John Kessenich4678ca92016-05-13 09:33:42 -06002031 // arguments
2032 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
2033 TIntermTyped* arguments = nullptr;
LoopDawg4886f692016-06-29 10:58:58 -06002034
2035 // methods have an implicit first argument of the calling object.
2036 if (base != nullptr)
2037 parseContext.handleFunctionArgument(function, arguments, base);
2038
John Kessenich4678ca92016-05-13 09:33:42 -06002039 if (! acceptArguments(function, arguments))
2040 return false;
2041
2042 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
2043
2044 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06002045}
2046
John Kessenich87142c72016-03-12 20:24:24 -07002047// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06002048// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002049//
John Kessenichd016be12016-03-13 11:24:20 -06002050// The arguments are pushed onto the 'function' argument list and
2051// onto the 'arguments' aggregate.
2052//
John Kessenich4678ca92016-05-13 09:33:42 -06002053bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07002054{
John Kessenich078d7f22016-03-14 10:02:11 -06002055 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002056 if (! acceptTokenClass(EHTokLeftParen))
2057 return false;
2058
2059 do {
John Kessenichd016be12016-03-13 11:24:20 -06002060 // expression
John Kessenich87142c72016-03-12 20:24:24 -07002061 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06002062 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07002063 break;
John Kessenichd016be12016-03-13 11:24:20 -06002064
2065 // hook it up
2066 parseContext.handleFunctionArgument(function, arguments, arg);
2067
John Kessenich078d7f22016-03-14 10:02:11 -06002068 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07002069 if (! acceptTokenClass(EHTokComma))
2070 break;
2071 } while (true);
2072
John Kessenich078d7f22016-03-14 10:02:11 -06002073 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07002074 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002075 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07002076 return false;
2077 }
2078
2079 return true;
2080}
2081
2082bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
2083{
2084 switch (token.tokenClass) {
2085 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002086 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002087 break;
steve-lunarg2de32912016-07-28 14:49:48 -06002088 case EHTokUintConstant:
2089 node = intermediate.addConstantUnion(token.u, token.loc, true);
2090 break;
John Kessenich87142c72016-03-12 20:24:24 -07002091 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002092 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002093 break;
2094 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002095 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002096 break;
2097 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06002098 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07002099 break;
John Kessenich86f71382016-09-19 20:23:18 -06002100 case EHTokStringConstant:
2101 node = nullptr;
2102 break;
John Kessenich87142c72016-03-12 20:24:24 -07002103
2104 default:
2105 return false;
2106 }
2107
2108 advanceToken();
2109
2110 return true;
2111}
2112
John Kessenich5f934b02016-03-13 17:58:25 -06002113// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06002114// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002115//
John Kessenich21472ae2016-06-04 11:46:33 -06002116bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07002117{
John Kessenich21472ae2016-06-04 11:46:33 -06002118 TIntermAggregate* compoundStatement = nullptr;
2119
John Kessenich34fb0362016-05-03 23:17:20 -06002120 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002121 if (! acceptTokenClass(EHTokLeftBrace))
2122 return false;
2123
2124 // statement statement ...
2125 TIntermNode* statement = nullptr;
2126 while (acceptStatement(statement)) {
John Kessenichd02dc5d2016-07-01 00:04:11 -06002127 TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
2128 if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
2129 branch->getFlowOp() == EOpDefault)) {
2130 // hook up individual subsequences within a switch statement
2131 parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
2132 compoundStatement = nullptr;
2133 } else {
2134 // hook it up to the growing compound statement
2135 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
2136 }
John Kessenich5f934b02016-03-13 17:58:25 -06002137 }
John Kessenich34fb0362016-05-03 23:17:20 -06002138 if (compoundStatement)
2139 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06002140
John Kessenich21472ae2016-06-04 11:46:33 -06002141 retStatement = compoundStatement;
2142
John Kessenich34fb0362016-05-03 23:17:20 -06002143 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06002144 return acceptTokenClass(EHTokRightBrace);
2145}
2146
John Kessenich0d2b6de2016-06-05 11:23:11 -06002147bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
2148{
2149 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06002150 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06002151 parseContext.popScope();
2152
2153 return result;
2154}
2155
John Kessenich077e0522016-06-09 02:02:17 -06002156bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06002157{
John Kessenich077e0522016-06-09 02:02:17 -06002158 parseContext.pushScope();
2159 bool result = acceptCompoundStatement(statement);
2160 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06002161
2162 return result;
2163}
2164
John Kessenich5f934b02016-03-13 17:58:25 -06002165// statement
John Kessenich21472ae2016-06-04 11:46:33 -06002166// : attributes attributed_statement
2167//
2168// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002169// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06002170// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06002171// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06002172// | declaration_statement
2173// | selection_statement
2174// | switch_statement
2175// | case_label
2176// | iteration_statement
2177// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06002178//
2179bool HlslGrammar::acceptStatement(TIntermNode*& statement)
2180{
John Kessenich21472ae2016-06-04 11:46:33 -06002181 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06002182
John Kessenich21472ae2016-06-04 11:46:33 -06002183 // attributes
2184 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06002185
John Kessenich21472ae2016-06-04 11:46:33 -06002186 // attributed_statement
2187 switch (peek()) {
2188 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06002189 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002190
John Kessenich21472ae2016-06-04 11:46:33 -06002191 case EHTokIf:
2192 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002193
John Kessenich21472ae2016-06-04 11:46:33 -06002194 case EHTokSwitch:
2195 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06002196
John Kessenich21472ae2016-06-04 11:46:33 -06002197 case EHTokFor:
2198 case EHTokDo:
2199 case EHTokWhile:
2200 return acceptIterationStatement(statement);
2201
2202 case EHTokContinue:
2203 case EHTokBreak:
2204 case EHTokDiscard:
2205 case EHTokReturn:
2206 return acceptJumpStatement(statement);
2207
2208 case EHTokCase:
2209 return acceptCaseLabel(statement);
John Kessenichd02dc5d2016-07-01 00:04:11 -06002210 case EHTokDefault:
2211 return acceptDefaultLabel(statement);
John Kessenich21472ae2016-06-04 11:46:33 -06002212
2213 case EHTokSemicolon:
2214 return acceptTokenClass(EHTokSemicolon);
2215
2216 case EHTokRightBrace:
2217 // Performance: not strictly necessary, but stops a bunch of hunting early,
2218 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06002219 return false;
2220
John Kessenich21472ae2016-06-04 11:46:33 -06002221 default:
2222 {
2223 // declaration
2224 if (acceptDeclaration(statement))
2225 return true;
2226
2227 // expression
2228 TIntermTyped* node;
2229 if (acceptExpression(node))
2230 statement = node;
2231 else
2232 return false;
2233
2234 // SEMICOLON (following an expression)
2235 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06002236 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06002237 return false;
2238 }
2239 }
2240 }
2241
John Kessenich5f934b02016-03-13 17:58:25 -06002242 return true;
John Kessenich87142c72016-03-12 20:24:24 -07002243}
2244
John Kessenich21472ae2016-06-04 11:46:33 -06002245// attributes
2246// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
2247//
2248// attribute:
2249// : UNROLL
2250// | UNROLL LEFT_PAREN literal RIGHT_PAREN
2251// | FASTOPT
2252// | ALLOW_UAV_CONDITION
2253// | BRANCH
2254// | FLATTEN
2255// | FORCECASE
2256// | CALL
2257//
2258void HlslGrammar::acceptAttributes()
2259{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002260 // For now, accept the [ XXX(X) ] syntax, but drop.
2261 // TODO: subset to correct set? Pass on?
2262 do {
2263 // LEFT_BRACKET?
2264 if (! acceptTokenClass(EHTokLeftBracket))
2265 return;
2266
2267 // attribute
2268 if (peekTokenClass(EHTokIdentifier)) {
2269 // 'token.string' is the attribute
2270 advanceToken();
2271 } else if (! peekTokenClass(EHTokRightBracket)) {
2272 expected("identifier");
2273 advanceToken();
2274 }
2275
2276 // (x)
2277 if (acceptTokenClass(EHTokLeftParen)) {
2278 TIntermTyped* node;
2279 if (! acceptLiteral(node))
2280 expected("literal");
2281 // 'node' has the literal in it
2282 if (! acceptTokenClass(EHTokRightParen))
2283 expected(")");
2284 }
2285
2286 // RIGHT_BRACKET
2287 if (acceptTokenClass(EHTokRightBracket))
2288 continue;
2289
2290 expected("]");
2291 return;
2292
2293 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06002294}
2295
John Kessenich0d2b6de2016-06-05 11:23:11 -06002296// selection_statement
2297// : IF LEFT_PAREN expression RIGHT_PAREN statement
2298// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
2299//
John Kessenich21472ae2016-06-04 11:46:33 -06002300bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
2301{
John Kessenich0d2b6de2016-06-05 11:23:11 -06002302 TSourceLoc loc = token.loc;
2303
2304 // IF
2305 if (! acceptTokenClass(EHTokIf))
2306 return false;
2307
2308 // so that something declared in the condition is scoped to the lifetimes
2309 // of the then-else statements
2310 parseContext.pushScope();
2311
2312 // LEFT_PAREN expression RIGHT_PAREN
2313 TIntermTyped* condition;
2314 if (! acceptParenExpression(condition))
2315 return false;
2316
2317 // create the child statements
2318 TIntermNodePair thenElse = { nullptr, nullptr };
2319
2320 // then statement
2321 if (! acceptScopedStatement(thenElse.node1)) {
2322 expected("then statement");
2323 return false;
2324 }
2325
2326 // ELSE
2327 if (acceptTokenClass(EHTokElse)) {
2328 // else statement
2329 if (! acceptScopedStatement(thenElse.node2)) {
2330 expected("else statement");
2331 return false;
2332 }
2333 }
2334
2335 // Put the pieces together
2336 statement = intermediate.addSelection(condition, thenElse, loc);
2337 parseContext.popScope();
2338
2339 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002340}
2341
John Kessenichd02dc5d2016-07-01 00:04:11 -06002342// switch_statement
2343// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
2344//
John Kessenich21472ae2016-06-04 11:46:33 -06002345bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
2346{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002347 // SWITCH
2348 TSourceLoc loc = token.loc;
2349 if (! acceptTokenClass(EHTokSwitch))
2350 return false;
2351
2352 // LEFT_PAREN expression RIGHT_PAREN
2353 parseContext.pushScope();
2354 TIntermTyped* switchExpression;
2355 if (! acceptParenExpression(switchExpression)) {
2356 parseContext.popScope();
2357 return false;
2358 }
2359
2360 // compound_statement
2361 parseContext.pushSwitchSequence(new TIntermSequence);
2362 bool statementOkay = acceptCompoundStatement(statement);
2363 if (statementOkay)
2364 statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr);
2365
2366 parseContext.popSwitchSequence();
2367 parseContext.popScope();
2368
2369 return statementOkay;
John Kessenich21472ae2016-06-04 11:46:33 -06002370}
2371
John Kessenich119f8f62016-06-05 15:44:07 -06002372// iteration_statement
2373// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
2374// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
2375// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
2376//
2377// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06002378bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
2379{
John Kessenich119f8f62016-06-05 15:44:07 -06002380 TSourceLoc loc = token.loc;
2381 TIntermTyped* condition = nullptr;
2382
2383 EHlslTokenClass loop = peek();
2384 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
2385
2386 // WHILE or DO or FOR
2387 advanceToken();
2388
2389 switch (loop) {
2390 case EHTokWhile:
2391 // so that something declared in the condition is scoped to the lifetime
2392 // of the while sub-statement
2393 parseContext.pushScope();
2394 parseContext.nestLooping();
2395
2396 // LEFT_PAREN condition RIGHT_PAREN
2397 if (! acceptParenExpression(condition))
2398 return false;
2399
2400 // statement
2401 if (! acceptScopedStatement(statement)) {
2402 expected("while sub-statement");
2403 return false;
2404 }
2405
2406 parseContext.unnestLooping();
2407 parseContext.popScope();
2408
2409 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
2410
2411 return true;
2412
2413 case EHTokDo:
2414 parseContext.nestLooping();
2415
2416 if (! acceptTokenClass(EHTokLeftBrace))
2417 expected("{");
2418
2419 // statement
2420 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
2421 expected("do sub-statement");
2422 return false;
2423 }
2424
2425 if (! acceptTokenClass(EHTokRightBrace))
2426 expected("}");
2427
2428 // WHILE
2429 if (! acceptTokenClass(EHTokWhile)) {
2430 expected("while");
2431 return false;
2432 }
2433
2434 // LEFT_PAREN condition RIGHT_PAREN
2435 TIntermTyped* condition;
2436 if (! acceptParenExpression(condition))
2437 return false;
2438
2439 if (! acceptTokenClass(EHTokSemicolon))
2440 expected(";");
2441
2442 parseContext.unnestLooping();
2443
2444 statement = intermediate.addLoop(statement, condition, 0, false, loc);
2445
2446 return true;
2447
2448 case EHTokFor:
2449 {
2450 // LEFT_PAREN
2451 if (! acceptTokenClass(EHTokLeftParen))
2452 expected("(");
2453
2454 // so that something declared in the condition is scoped to the lifetime
2455 // of the for sub-statement
2456 parseContext.pushScope();
2457
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002458 // initializer
2459 TIntermNode* initNode = nullptr;
2460 if (! acceptControlDeclaration(initNode)) {
2461 TIntermTyped* initExpr = nullptr;
2462 acceptExpression(initExpr);
2463 initNode = initExpr;
2464 }
2465 // SEMI_COLON
John Kessenich119f8f62016-06-05 15:44:07 -06002466 if (! acceptTokenClass(EHTokSemicolon))
2467 expected(";");
2468
2469 parseContext.nestLooping();
2470
2471 // condition SEMI_COLON
2472 acceptExpression(condition);
2473 if (! acceptTokenClass(EHTokSemicolon))
2474 expected(";");
2475
2476 // iterator SEMI_COLON
2477 TIntermTyped* iterator = nullptr;
2478 acceptExpression(iterator);
2479 if (! acceptTokenClass(EHTokRightParen))
2480 expected(")");
2481
2482 // statement
2483 if (! acceptScopedStatement(statement)) {
2484 expected("for sub-statement");
2485 return false;
2486 }
2487
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002488 statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
John Kessenich119f8f62016-06-05 15:44:07 -06002489
2490 parseContext.popScope();
2491 parseContext.unnestLooping();
2492
2493 return true;
2494 }
2495
2496 default:
2497 return false;
2498 }
John Kessenich21472ae2016-06-04 11:46:33 -06002499}
2500
2501// jump_statement
2502// : CONTINUE SEMICOLON
2503// | BREAK SEMICOLON
2504// | DISCARD SEMICOLON
2505// | RETURN SEMICOLON
2506// | RETURN expression SEMICOLON
2507//
2508bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
2509{
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002510 EHlslTokenClass jump = peek();
2511 switch (jump) {
John Kessenich21472ae2016-06-04 11:46:33 -06002512 case EHTokContinue:
2513 case EHTokBreak:
2514 case EHTokDiscard:
John Kessenich21472ae2016-06-04 11:46:33 -06002515 case EHTokReturn:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002516 advanceToken();
2517 break;
John Kessenich21472ae2016-06-04 11:46:33 -06002518 default:
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002519 // not something we handle in this function
John Kessenich21472ae2016-06-04 11:46:33 -06002520 return false;
2521 }
John Kessenich21472ae2016-06-04 11:46:33 -06002522
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002523 switch (jump) {
2524 case EHTokContinue:
2525 statement = intermediate.addBranch(EOpContinue, token.loc);
2526 break;
2527 case EHTokBreak:
2528 statement = intermediate.addBranch(EOpBreak, token.loc);
2529 break;
2530 case EHTokDiscard:
2531 statement = intermediate.addBranch(EOpKill, token.loc);
2532 break;
2533
2534 case EHTokReturn:
2535 {
2536 // expression
2537 TIntermTyped* node;
2538 if (acceptExpression(node)) {
2539 // hook it up
steve-lunargc4a13072016-08-09 11:28:03 -06002540 statement = parseContext.handleReturnValue(token.loc, node);
John Kessenich5bc4d9a2016-06-20 01:22:38 -06002541 } else
2542 statement = intermediate.addBranch(EOpReturn, token.loc);
2543 break;
2544 }
2545
2546 default:
2547 assert(0);
2548 return false;
2549 }
2550
2551 // SEMICOLON
2552 if (! acceptTokenClass(EHTokSemicolon))
2553 expected(";");
2554
2555 return true;
2556}
John Kessenich21472ae2016-06-04 11:46:33 -06002557
John Kessenichd02dc5d2016-07-01 00:04:11 -06002558// case_label
2559// : CASE expression COLON
2560//
John Kessenich21472ae2016-06-04 11:46:33 -06002561bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
2562{
John Kessenichd02dc5d2016-07-01 00:04:11 -06002563 TSourceLoc loc = token.loc;
2564 if (! acceptTokenClass(EHTokCase))
2565 return false;
2566
2567 TIntermTyped* expression;
2568 if (! acceptExpression(expression)) {
2569 expected("case expression");
2570 return false;
2571 }
2572
2573 if (! acceptTokenClass(EHTokColon)) {
2574 expected(":");
2575 return false;
2576 }
2577
2578 statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
2579
2580 return true;
2581}
2582
2583// default_label
2584// : DEFAULT COLON
2585//
2586bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
2587{
2588 TSourceLoc loc = token.loc;
2589 if (! acceptTokenClass(EHTokDefault))
2590 return false;
2591
2592 if (! acceptTokenClass(EHTokColon)) {
2593 expected(":");
2594 return false;
2595 }
2596
2597 statement = parseContext.intermediate.addBranch(EOpDefault, loc);
2598
2599 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06002600}
2601
John Kessenich19b92ff2016-06-19 11:50:34 -06002602// array_specifier
2603// : LEFT_BRACKET integer_expression RGHT_BRACKET post_decls // optional
2604//
2605void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
2606{
2607 arraySizes = nullptr;
2608
2609 if (! acceptTokenClass(EHTokLeftBracket))
2610 return;
2611
2612 TSourceLoc loc = token.loc;
2613 TIntermTyped* sizeExpr;
2614 if (! acceptAssignmentExpression(sizeExpr)) {
2615 expected("array-sizing expression");
2616 return;
2617 }
2618
2619 if (! acceptTokenClass(EHTokRightBracket)) {
2620 expected("]");
2621 return;
2622 }
2623
2624 TArraySize arraySize;
2625 parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
2626 arraySizes = new TArraySizes;
2627 arraySizes->addInnerSize(arraySize);
2628}
2629
John Kessenich630dd7d2016-06-12 23:52:12 -06002630// post_decls
John Kessenichcfd7ce82016-09-05 16:03:12 -06002631// : COLON semantic // optional
2632// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
2633// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
John Kesseniche3218e22016-09-05 14:37:03 -06002634// COLON LAYOUT layout_qualifier_list
John Kessenichcfd7ce82016-09-05 16:03:12 -06002635// annotations // optional
John Kessenich630dd7d2016-06-12 23:52:12 -06002636//
John Kessenich7735b942016-09-05 12:40:06 -06002637void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
John Kessenich078d7f22016-03-14 10:02:11 -06002638{
John Kessenich630dd7d2016-06-12 23:52:12 -06002639 do {
2640 // COLON
2641 if (acceptTokenClass(EHTokColon)) {
2642 HlslToken idToken;
John Kesseniche3218e22016-09-05 14:37:03 -06002643 if (peekTokenClass(EHTokLayout))
2644 acceptLayoutQualifierList(qualifier);
2645 else if (acceptTokenClass(EHTokPackOffset)) {
John Kessenich96e9f472016-07-29 14:28:39 -06002646 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002647 if (! acceptTokenClass(EHTokLeftParen)) {
2648 expected("(");
2649 return;
2650 }
John Kessenich82d6baf2016-07-29 13:03:05 -06002651 HlslToken locationToken;
2652 if (! acceptIdentifier(locationToken)) {
2653 expected("c[subcomponent][.component]");
2654 return;
2655 }
2656 HlslToken componentToken;
2657 if (acceptTokenClass(EHTokDot)) {
2658 if (! acceptIdentifier(componentToken)) {
2659 expected("component");
2660 return;
2661 }
2662 }
John Kessenich630dd7d2016-06-12 23:52:12 -06002663 if (! acceptTokenClass(EHTokRightParen)) {
2664 expected(")");
2665 break;
2666 }
John Kessenich7735b942016-09-05 12:40:06 -06002667 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002668 } else if (! acceptIdentifier(idToken)) {
John Kesseniche3218e22016-09-05 14:37:03 -06002669 expected("layout, semantic, packoffset, or register");
John Kessenich630dd7d2016-06-12 23:52:12 -06002670 return;
2671 } else if (*idToken.string == "register") {
John Kessenichcfd7ce82016-09-05 16:03:12 -06002672 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
2673 // LEFT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002674 if (! acceptTokenClass(EHTokLeftParen)) {
2675 expected("(");
2676 return;
2677 }
John Kessenichb38f0712016-07-30 10:29:54 -06002678 HlslToken registerDesc; // for Type#
2679 HlslToken profile;
John Kessenich96e9f472016-07-29 14:28:39 -06002680 if (! acceptIdentifier(registerDesc)) {
2681 expected("register number description");
2682 return;
2683 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002684 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
2685 acceptTokenClass(EHTokComma)) {
John Kessenichb38f0712016-07-30 10:29:54 -06002686 // Then we didn't really see the registerDesc yet, it was
2687 // actually the profile. Adjust...
John Kessenich96e9f472016-07-29 14:28:39 -06002688 profile = registerDesc;
2689 if (! acceptIdentifier(registerDesc)) {
2690 expected("register number description");
2691 return;
2692 }
2693 }
John Kessenichb38f0712016-07-30 10:29:54 -06002694 int subComponent = 0;
2695 if (acceptTokenClass(EHTokLeftBracket)) {
2696 // LEFT_BRACKET subcomponent RIGHT_BRACKET
2697 if (! peekTokenClass(EHTokIntConstant)) {
2698 expected("literal integer");
2699 return;
2700 }
2701 subComponent = token.i;
2702 advanceToken();
2703 if (! acceptTokenClass(EHTokRightBracket)) {
2704 expected("]");
2705 break;
2706 }
2707 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002708 // (COMMA SPACEN)opt
2709 HlslToken spaceDesc;
2710 if (acceptTokenClass(EHTokComma)) {
2711 if (! acceptIdentifier(spaceDesc)) {
2712 expected ("space identifier");
2713 return;
2714 }
2715 }
2716 // RIGHT_PAREN
John Kessenich630dd7d2016-06-12 23:52:12 -06002717 if (! acceptTokenClass(EHTokRightParen)) {
2718 expected(")");
2719 break;
2720 }
John Kessenichcfd7ce82016-09-05 16:03:12 -06002721 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002722 } else {
2723 // semantic, in idToken.string
John Kessenich7735b942016-09-05 12:40:06 -06002724 parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
John Kessenich630dd7d2016-06-12 23:52:12 -06002725 }
John Kessenicha1e2d492016-09-20 13:22:58 -06002726 } else if (peekTokenClass(EHTokLeftAngle))
2727 acceptAnnotations(qualifier);
2728 else
John Kessenich630dd7d2016-06-12 23:52:12 -06002729 break;
John Kessenich078d7f22016-03-14 10:02:11 -06002730
John Kessenich630dd7d2016-06-12 23:52:12 -06002731 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06002732}
2733
John Kesseniche01a9bc2016-03-12 20:11:22 -07002734} // end namespace glslang