blob: 3f0740a02437f8cd2670069ec01fdffc5669e41c [file] [log] [blame]
John Kesseniche01a9bc2016-03-12 20:11:22 -07001//
2//Copyright (C) 2016 Google, Inc.
3//
4//All rights reserved.
5//
6//Redistribution and use in source and binary forms, with or without
7//modification, are permitted provided that the following conditions
8//are met:
9//
10// Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//
13// Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following
15// disclaimer in the documentation and/or other materials provided
16// with the distribution.
17//
18// Neither the name of Google, Inc., nor the names of its
19// contributors may be used to endorse or promote products derived
20// from this software without specific prior written permission.
21//
22//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33//POSSIBILITY OF SUCH DAMAGE.
34//
35
John Kessenichd016be12016-03-13 11:24:20 -060036//
37// This is a set of mutually recursive methods implementing the HLSL grammar.
38// Generally, each returns
39// - through an argument: a type specifically appropriate to which rule it
40// recognized
41// - through the return value: true/false to indicate whether or not it
42// recognized its rule
43//
44// As much as possible, only grammar recognition should happen in this file,
John Kessenich078d7f22016-03-14 10:02:11 -060045// with all other work being farmed out to hlslParseHelper.cpp, which in turn
John Kessenichd016be12016-03-13 11:24:20 -060046// will build the AST.
47//
48// The next token, yet to be "accepted" is always sitting in 'token'.
49// When a method says it accepts a rule, that means all tokens involved
50// in the rule will have been consumed, and none left in 'token'.
51//
52
John Kesseniche01a9bc2016-03-12 20:11:22 -070053#include "hlslTokens.h"
54#include "hlslGrammar.h"
55
56namespace glslang {
57
58// Root entry point to this recursive decent parser.
59// Return true if compilation unit was successfully accepted.
60bool HlslGrammar::parse()
61{
62 advanceToken();
63 return acceptCompilationUnit();
64}
65
66void HlslGrammar::expected(const char* syntax)
67{
68 parseContext.error(token.loc, "Expected", syntax, "");
69}
70
John Kessenichaecd4972016-03-14 10:46:34 -060071// Only process the next token if it is an identifier.
72// Return true if it was an identifier.
73bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
74{
75 if (peekTokenClass(EHTokIdentifier)) {
76 idToken = token;
77 advanceToken();
78 return true;
79 }
80
81 return false;
82}
83
John Kesseniche01a9bc2016-03-12 20:11:22 -070084// compilationUnit
85// : list of externalDeclaration
86//
87bool HlslGrammar::acceptCompilationUnit()
88{
John Kessenichd016be12016-03-13 11:24:20 -060089 TIntermNode* unitNode = nullptr;
90
John Kessenich9c86c6a2016-05-03 22:49:24 -060091 while (! peekTokenClass(EHTokNone)) {
John Kessenichd016be12016-03-13 11:24:20 -060092 // externalDeclaration
93 TIntermNode* declarationNode;
94 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -070095 return false;
John Kessenichd016be12016-03-13 11:24:20 -060096
97 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -060098 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -070099 }
100
John Kessenichd016be12016-03-13 11:24:20 -0600101 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600102 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600103
John Kesseniche01a9bc2016-03-12 20:11:22 -0700104 return true;
105}
106
107// declaration
John Kessenich078d7f22016-03-14 10:02:11 -0600108// : SEMICOLON
109// : fully_specified_type SEMICOLON
John Kessenich630dd7d2016-06-12 23:52:12 -0600110// | fully_specified_type identifier post_decls SEMICOLON
111// | fully_specified_type identifier post_decls = expression SEMICOLON
112// | fully_specified_type identifier function_parameters post_decls SEMICOLON // function prototype
113// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
John Kessenich87142c72016-03-12 20:24:24 -0700114//
John Kessenichd016be12016-03-13 11:24:20 -0600115// 'node' could get created if the declaration creates code, like an initializer
116// or a function body.
117//
118bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700119{
John Kessenichd016be12016-03-13 11:24:20 -0600120 node = nullptr;
121
John Kessenich87142c72016-03-12 20:24:24 -0700122 // fully_specified_type
123 TType type;
124 if (! acceptFullySpecifiedType(type))
125 return false;
126
127 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600128 HlslToken idToken;
129 if (acceptIdentifier(idToken)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600130 acceptPostDecls(type);
John Kessenich87142c72016-03-12 20:24:24 -0700131 // = expression
132 TIntermTyped* expressionNode = nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -0600133 if (acceptTokenClass(EHTokAssign)) {
John Kessenich87142c72016-03-12 20:24:24 -0700134 if (! acceptExpression(expressionNode)) {
135 expected("initializer");
136 return false;
137 }
138 }
139
John Kessenich078d7f22016-03-14 10:02:11 -0600140 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700141 if (acceptTokenClass(EHTokSemicolon)) {
John Kessenichaecd4972016-03-14 10:46:34 -0600142 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
John Kessenich87142c72016-03-12 20:24:24 -0700143 return true;
144 }
John Kessenich5f934b02016-03-13 17:58:25 -0600145
146 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600147 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600148 if (acceptFunctionParameters(*function)) {
John Kessenich630dd7d2016-06-12 23:52:12 -0600149 // post_decls
150 acceptPostDecls(type);
John Kessenich078d7f22016-03-14 10:02:11 -0600151
John Kessenich5f934b02016-03-13 17:58:25 -0600152 // compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600153 if (peekTokenClass(EHTokLeftBrace))
John Kessenich5f934b02016-03-13 17:58:25 -0600154 return acceptFunctionDefinition(*function, node);
155
John Kessenich078d7f22016-03-14 10:02:11 -0600156 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600157 if (acceptTokenClass(EHTokSemicolon))
158 return true;
159
160 return false;
161 }
John Kessenich87142c72016-03-12 20:24:24 -0700162 }
163
John Kessenich078d7f22016-03-14 10:02:11 -0600164 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700165 if (acceptTokenClass(EHTokSemicolon))
166 return true;
167
John Kesseniche01a9bc2016-03-12 20:11:22 -0700168 return true;
169}
170
John Kessenich87142c72016-03-12 20:24:24 -0700171// fully_specified_type
172// : type_specifier
173// | type_qualifier type_specifier
174//
175bool HlslGrammar::acceptFullySpecifiedType(TType& type)
176{
177 // type_qualifier
178 TQualifier qualifier;
179 qualifier.clear();
180 acceptQualifier(qualifier);
181
182 // type_specifier
183 if (! acceptType(type))
184 return false;
185 type.getQualifier() = qualifier;
186
187 return true;
188}
189
John Kessenich630dd7d2016-06-12 23:52:12 -0600190// type_qualifier
191// : qualifier qualifier ...
192//
193// Zero or more of these, so this can't return false.
194//
John Kessenich87142c72016-03-12 20:24:24 -0700195void HlslGrammar::acceptQualifier(TQualifier& qualifier)
196{
John Kessenich630dd7d2016-06-12 23:52:12 -0600197 do {
198 switch (peek()) {
199 case EHTokStatic:
200 // normal glslang default
201 break;
202 case EHTokExtern:
203 // TODO: no meaning in glslang?
204 break;
205 case EHTokShared:
206 // TODO: hint
207 break;
208 case EHTokGroupShared:
209 qualifier.storage = EvqShared;
210 break;
211 case EHTokUniform:
212 qualifier.storage = EvqUniform;
213 break;
214 case EHTokConst:
215 qualifier.storage = EvqConst;
216 break;
217 case EHTokVolatile:
218 qualifier.volatil = true;
219 break;
220 case EHTokLinear:
221 qualifier.storage = EvqVaryingIn;
222 qualifier.smooth = true;
223 break;
224 case EHTokCentroid:
225 qualifier.centroid = true;
226 break;
227 case EHTokNointerpolation:
228 qualifier.flat = true;
229 break;
230 case EHTokNoperspective:
231 qualifier.nopersp = true;
232 break;
233 case EHTokSample:
234 qualifier.sample = true;
235 break;
236 case EHTokRowMajor:
237 qualifier.layoutMatrix = ElmRowMajor;
238 break;
239 case EHTokColumnMajor:
240 qualifier.layoutMatrix = ElmColumnMajor;
241 break;
242 case EHTokPrecise:
243 qualifier.noContraction = true;
244 break;
245 default:
246 return;
247 }
248 advanceToken();
249 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700250}
251
252// If token is for a type, update 'type' with the type information,
253// and return true and advance.
254// Otherwise, return false, and don't advance
255bool HlslGrammar::acceptType(TType& type)
256{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600257 switch (peek()) {
John Kesseniche6e74942016-06-11 16:43:14 -0600258 case EHTokStruct:
259 return acceptStruct(type);
260 break;
261
262 case EHTokIdentifier:
263 // An identifier could be for a user-defined type.
264 // Note we cache the symbol table lookup, to save for a later rule
265 // when this is not a type.
266 token.symbol = parseContext.symbolTable.find(*token.string);
267 if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
268 type.shallowCopy(token.symbol->getType());
269 advanceToken();
270 return true;
271 } else
272 return false;
273
John Kessenich71351de2016-06-08 12:50:56 -0600274 case EHTokVoid:
275 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700276 break;
John Kessenich71351de2016-06-08 12:50:56 -0600277
John Kessenich87142c72016-03-12 20:24:24 -0700278 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600279 new(&type) TType(EbtFloat);
280 break;
John Kessenich87142c72016-03-12 20:24:24 -0700281 case EHTokFloat1:
282 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600283 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700284 break;
John Kessenich87142c72016-03-12 20:24:24 -0700285 case EHTokFloat2:
286 new(&type) TType(EbtFloat, EvqTemporary, 2);
287 break;
288 case EHTokFloat3:
289 new(&type) TType(EbtFloat, EvqTemporary, 3);
290 break;
291 case EHTokFloat4:
292 new(&type) TType(EbtFloat, EvqTemporary, 4);
293 break;
294
John Kessenich71351de2016-06-08 12:50:56 -0600295 case EHTokDouble:
296 new(&type) TType(EbtDouble);
297 break;
298 case EHTokDouble1:
299 new(&type) TType(EbtDouble);
300 type.makeVector();
301 break;
302 case EHTokDouble2:
303 new(&type) TType(EbtDouble, EvqTemporary, 2);
304 break;
305 case EHTokDouble3:
306 new(&type) TType(EbtDouble, EvqTemporary, 3);
307 break;
308 case EHTokDouble4:
309 new(&type) TType(EbtDouble, EvqTemporary, 4);
310 break;
311
312 case EHTokInt:
313 case EHTokDword:
314 new(&type) TType(EbtInt);
315 break;
316 case EHTokInt1:
317 new(&type) TType(EbtInt);
318 type.makeVector();
319 break;
John Kessenich87142c72016-03-12 20:24:24 -0700320 case EHTokInt2:
321 new(&type) TType(EbtInt, EvqTemporary, 2);
322 break;
323 case EHTokInt3:
324 new(&type) TType(EbtInt, EvqTemporary, 3);
325 break;
326 case EHTokInt4:
327 new(&type) TType(EbtInt, EvqTemporary, 4);
328 break;
329
John Kessenich71351de2016-06-08 12:50:56 -0600330 case EHTokUint:
331 new(&type) TType(EbtUint);
332 break;
333 case EHTokUint1:
334 new(&type) TType(EbtUint);
335 type.makeVector();
336 break;
337 case EHTokUint2:
338 new(&type) TType(EbtUint, EvqTemporary, 2);
339 break;
340 case EHTokUint3:
341 new(&type) TType(EbtUint, EvqTemporary, 3);
342 break;
343 case EHTokUint4:
344 new(&type) TType(EbtUint, EvqTemporary, 4);
345 break;
346
347 case EHTokBool:
348 new(&type) TType(EbtBool);
349 break;
350 case EHTokBool1:
351 new(&type) TType(EbtBool);
352 type.makeVector();
353 break;
John Kessenich87142c72016-03-12 20:24:24 -0700354 case EHTokBool2:
355 new(&type) TType(EbtBool, EvqTemporary, 2);
356 break;
357 case EHTokBool3:
358 new(&type) TType(EbtBool, EvqTemporary, 3);
359 break;
360 case EHTokBool4:
361 new(&type) TType(EbtBool, EvqTemporary, 4);
362 break;
363
John Kessenich0133c122016-05-20 12:17:26 -0600364 case EHTokInt1x1:
365 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
366 break;
367 case EHTokInt1x2:
368 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
369 break;
370 case EHTokInt1x3:
371 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
372 break;
373 case EHTokInt1x4:
374 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
375 break;
376 case EHTokInt2x1:
377 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
378 break;
379 case EHTokInt2x2:
380 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
381 break;
382 case EHTokInt2x3:
383 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
384 break;
385 case EHTokInt2x4:
386 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
387 break;
388 case EHTokInt3x1:
389 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
390 break;
391 case EHTokInt3x2:
392 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
393 break;
394 case EHTokInt3x3:
395 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
396 break;
397 case EHTokInt3x4:
398 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
399 break;
400 case EHTokInt4x1:
401 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
402 break;
403 case EHTokInt4x2:
404 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
405 break;
406 case EHTokInt4x3:
407 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
408 break;
409 case EHTokInt4x4:
410 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
411 break;
412
John Kessenich71351de2016-06-08 12:50:56 -0600413 case EHTokUint1x1:
414 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
415 break;
416 case EHTokUint1x2:
417 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
418 break;
419 case EHTokUint1x3:
420 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
421 break;
422 case EHTokUint1x4:
423 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
424 break;
425 case EHTokUint2x1:
426 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
427 break;
428 case EHTokUint2x2:
429 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
430 break;
431 case EHTokUint2x3:
432 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
433 break;
434 case EHTokUint2x4:
435 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
436 break;
437 case EHTokUint3x1:
438 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
439 break;
440 case EHTokUint3x2:
441 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
442 break;
443 case EHTokUint3x3:
444 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
445 break;
446 case EHTokUint3x4:
447 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
448 break;
449 case EHTokUint4x1:
450 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
451 break;
452 case EHTokUint4x2:
453 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
454 break;
455 case EHTokUint4x3:
456 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
457 break;
458 case EHTokUint4x4:
459 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
460 break;
461
462 case EHTokBool1x1:
463 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
464 break;
465 case EHTokBool1x2:
466 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
467 break;
468 case EHTokBool1x3:
469 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
470 break;
471 case EHTokBool1x4:
472 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
473 break;
474 case EHTokBool2x1:
475 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
476 break;
477 case EHTokBool2x2:
478 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
479 break;
480 case EHTokBool2x3:
481 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
482 break;
483 case EHTokBool2x4:
484 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
485 break;
486 case EHTokBool3x1:
487 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
488 break;
489 case EHTokBool3x2:
490 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
491 break;
492 case EHTokBool3x3:
493 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
494 break;
495 case EHTokBool3x4:
496 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
497 break;
498 case EHTokBool4x1:
499 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
500 break;
501 case EHTokBool4x2:
502 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
503 break;
504 case EHTokBool4x3:
505 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
506 break;
507 case EHTokBool4x4:
508 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
509 break;
510
John Kessenich0133c122016-05-20 12:17:26 -0600511 case EHTokFloat1x1:
512 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
513 break;
514 case EHTokFloat1x2:
515 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
516 break;
517 case EHTokFloat1x3:
518 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
519 break;
520 case EHTokFloat1x4:
521 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
522 break;
523 case EHTokFloat2x1:
524 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
525 break;
John Kessenich87142c72016-03-12 20:24:24 -0700526 case EHTokFloat2x2:
527 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
528 break;
529 case EHTokFloat2x3:
530 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
531 break;
532 case EHTokFloat2x4:
533 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
534 break;
John Kessenich0133c122016-05-20 12:17:26 -0600535 case EHTokFloat3x1:
536 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
537 break;
John Kessenich87142c72016-03-12 20:24:24 -0700538 case EHTokFloat3x2:
539 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
540 break;
541 case EHTokFloat3x3:
542 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
543 break;
544 case EHTokFloat3x4:
545 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
546 break;
John Kessenich0133c122016-05-20 12:17:26 -0600547 case EHTokFloat4x1:
548 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
549 break;
John Kessenich87142c72016-03-12 20:24:24 -0700550 case EHTokFloat4x2:
551 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
552 break;
553 case EHTokFloat4x3:
554 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
555 break;
556 case EHTokFloat4x4:
557 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
558 break;
559
John Kessenich0133c122016-05-20 12:17:26 -0600560 case EHTokDouble1x1:
561 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
562 break;
563 case EHTokDouble1x2:
564 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
565 break;
566 case EHTokDouble1x3:
567 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
568 break;
569 case EHTokDouble1x4:
570 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
571 break;
572 case EHTokDouble2x1:
573 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
574 break;
575 case EHTokDouble2x2:
576 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
577 break;
578 case EHTokDouble2x3:
579 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
580 break;
581 case EHTokDouble2x4:
582 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
583 break;
584 case EHTokDouble3x1:
585 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
586 break;
587 case EHTokDouble3x2:
588 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
589 break;
590 case EHTokDouble3x3:
591 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
592 break;
593 case EHTokDouble3x4:
594 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
595 break;
596 case EHTokDouble4x1:
597 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
598 break;
599 case EHTokDouble4x2:
600 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
601 break;
602 case EHTokDouble4x3:
603 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
604 break;
605 case EHTokDouble4x4:
606 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
607 break;
608
John Kessenich87142c72016-03-12 20:24:24 -0700609 default:
610 return false;
611 }
612
613 advanceToken();
614
615 return true;
616}
617
John Kesseniche6e74942016-06-11 16:43:14 -0600618// struct
619// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE
620// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE
621//
622bool HlslGrammar::acceptStruct(TType& type)
623{
624 // STRUCT
625 if (! acceptTokenClass(EHTokStruct))
626 return false;
627
628 // IDENTIFIER
629 TString structName = "";
630 if (peekTokenClass(EHTokIdentifier)) {
631 structName = *token.string;
632 advanceToken();
633 }
634
635 // LEFT_BRACE
636 if (! acceptTokenClass(EHTokLeftBrace)) {
637 expected("{");
638 return false;
639 }
640
641 // struct_declaration_list
642 TTypeList* typeList;
643 if (! acceptStructDeclarationList(typeList)) {
644 expected("struct member declarations");
645 return false;
646 }
647
648 // RIGHT_BRACE
649 if (! acceptTokenClass(EHTokRightBrace)) {
650 expected("}");
651 return false;
652 }
653
654 // create the user-defined type
655 new(&type) TType(typeList, structName);
656
657 // If it was named, which means it can be reused later, add
658 // it to the symbol table.
659 if (structName.size() > 0) {
660 TVariable* userTypeDef = new TVariable(&structName, type, true);
661 if (! parseContext.symbolTable.insert(*userTypeDef))
662 parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
663 }
664
665 return true;
666}
667
668// struct_declaration_list
669// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
670//
671// struct_declaration
672// : fully_specified_type struct_declarator COMMA struct_declarator ...
673//
674// struct_declarator
John Kessenich630dd7d2016-06-12 23:52:12 -0600675// : IDENTIFIER post_decls
676// | IDENTIFIER array_specifier post_decls
John Kesseniche6e74942016-06-11 16:43:14 -0600677//
678bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList)
679{
680 typeList = new TTypeList();
681
682 do {
683 // success on seeing the RIGHT_BRACE coming up
684 if (peekTokenClass(EHTokRightBrace))
685 return true;
686
687 // struct_declaration
688
689 // fully_specified_type
690 TType memberType;
691 if (! acceptFullySpecifiedType(memberType)) {
692 expected("member type");
693 return false;
694 }
695
696 // struct_declarator COMMA struct_declarator ...
697 do {
698 // peek IDENTIFIER
699 if (! peekTokenClass(EHTokIdentifier)) {
700 expected("member name");
701 return false;
702 }
703
704 // add it to the list of members
705 TTypeLoc member = { new TType(EbtVoid), token.loc };
706 member.type->shallowCopy(memberType);
707 member.type->setFieldName(*token.string);
708 typeList->push_back(member);
709
710 // accept IDENTIFIER
711 advanceToken();
712
713 // array_specifier
714 // TODO
715
John Kessenich630dd7d2016-06-12 23:52:12 -0600716 acceptPostDecls(*member.type);
717
John Kesseniche6e74942016-06-11 16:43:14 -0600718 // success on seeing the SEMICOLON coming up
719 if (peekTokenClass(EHTokSemicolon))
720 break;
721
722 // COMMA
723 if (! acceptTokenClass(EHTokComma)) {
724 expected(",");
725 return false;
726 }
727
728 } while (true);
729
730 // SEMI_COLON
731 if (! acceptTokenClass(EHTokSemicolon)) {
732 expected(";");
733 return false;
734 }
735
736 } while (true);
737}
738
John Kessenich5f934b02016-03-13 17:58:25 -0600739// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600740// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -0600741// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600742//
743bool HlslGrammar::acceptFunctionParameters(TFunction& function)
744{
John Kessenich078d7f22016-03-14 10:02:11 -0600745 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600746 if (! acceptTokenClass(EHTokLeftParen))
747 return false;
748
John Kessenich71351de2016-06-08 12:50:56 -0600749 // VOID RIGHT_PAREN
750 if (! acceptTokenClass(EHTokVoid)) {
751 do {
752 // parameter_declaration
753 if (! acceptParameterDeclaration(function))
754 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600755
John Kessenich71351de2016-06-08 12:50:56 -0600756 // COMMA
757 if (! acceptTokenClass(EHTokComma))
758 break;
759 } while (true);
760 }
John Kessenich5f934b02016-03-13 17:58:25 -0600761
John Kessenich078d7f22016-03-14 10:02:11 -0600762 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600763 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600764 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -0600765 return false;
766 }
767
768 return true;
769}
770
771// parameter_declaration
John Kessenichc3387d32016-06-17 14:21:02 -0600772// : fully_specified_type post_decls
773// | fully_specified_type identifier post_decls
John Kessenich5f934b02016-03-13 17:58:25 -0600774//
775bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
776{
777 // fully_specified_type
778 TType* type = new TType;
779 if (! acceptFullySpecifiedType(*type))
780 return false;
781
782 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600783 HlslToken idToken;
784 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600785
John Kessenichc3387d32016-06-17 14:21:02 -0600786 acceptPostDecls(*type);
787
John Kessenichaecd4972016-03-14 10:46:34 -0600788 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600789 function.addParameter(param);
790
791 return true;
792}
793
794// Do the work to create the function definition in addition to
795// parsing the body (compound_statement).
796bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
797{
798 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
799
John Kessenich077e0522016-06-09 02:02:17 -0600800 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600801 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
802
803 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600804 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600805 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600806 node = intermediate.growAggregate(node, functionBody);
807 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600808 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600809 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600810
811 return true;
812 }
813
814 return false;
815}
816
John Kessenich0d2b6de2016-06-05 11:23:11 -0600817// Accept an expression with parenthesis around it, where
818// the parenthesis ARE NOT expression parenthesis, but the
819// syntactically required ones like in "if ( expression )"
820//
821// Note this one is not set up to be speculative; as it gives
822// errors if not found.
823//
824bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
825{
826 // LEFT_PAREN
827 if (! acceptTokenClass(EHTokLeftParen))
828 expected("(");
829
830 if (! acceptExpression(expression)) {
831 expected("expression");
832 return false;
833 }
834
835 // RIGHT_PAREN
836 if (! acceptTokenClass(EHTokRightParen))
837 expected(")");
838
839 return true;
840}
841
John Kessenich34fb0362016-05-03 23:17:20 -0600842// The top-level full expression recognizer.
843//
John Kessenich87142c72016-03-12 20:24:24 -0700844// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600845// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700846//
847bool HlslGrammar::acceptExpression(TIntermTyped*& node)
848{
LoopDawgef764a22016-06-03 09:17:51 -0600849 node = nullptr;
850
John Kessenich34fb0362016-05-03 23:17:20 -0600851 // assignment_expression
852 if (! acceptAssignmentExpression(node))
853 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600854
John Kessenich34fb0362016-05-03 23:17:20 -0600855 if (! peekTokenClass(EHTokComma))
856 return true;
857
858 do {
859 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600860 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600861 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600862
John Kessenich34fb0362016-05-03 23:17:20 -0600863 // ... assignment_expression
864 TIntermTyped* rightNode = nullptr;
865 if (! acceptAssignmentExpression(rightNode)) {
866 expected("assignment expression");
867 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600868 }
869
John Kessenich34fb0362016-05-03 23:17:20 -0600870 node = intermediate.addComma(node, rightNode, loc);
871
872 if (! peekTokenClass(EHTokComma))
873 return true;
874 } while (true);
875}
876
877// Accept an assignment expression, where assignment operations
878// associate right-to-left. This is, it is implicit, for example
879//
880// a op (b op (c op d))
881//
882// assigment_expression
883// : binary_expression op binary_expression op binary_expression ...
884//
885bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
886{
887 if (! acceptBinaryExpression(node, PlLogicalOr))
888 return false;
889
890 TOperator assignOp = HlslOpMap::assignment(peek());
891 if (assignOp == EOpNull)
892 return true;
893
894 // ... op
895 TSourceLoc loc = token.loc;
896 advanceToken();
897
898 // ... binary_expression
899 // But, done by recursing this function, which automatically
900 // gets the right-to-left associativity.
901 TIntermTyped* rightNode = nullptr;
902 if (! acceptAssignmentExpression(rightNode)) {
903 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600904 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700905 }
906
John Kessenich34fb0362016-05-03 23:17:20 -0600907 node = intermediate.addAssign(assignOp, node, rightNode, loc);
908
909 if (! peekTokenClass(EHTokComma))
910 return true;
911
912 return true;
913}
914
915// Accept a binary expression, for binary operations that
916// associate left-to-right. This is, it is implicit, for example
917//
918// ((a op b) op c) op d
919//
920// binary_expression
921// : expression op expression op expression ...
922//
923// where 'expression' is the next higher level in precedence.
924//
925bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
926{
927 if (precedenceLevel > PlMul)
928 return acceptUnaryExpression(node);
929
930 // assignment_expression
931 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
932 return false;
933
934 TOperator op = HlslOpMap::binary(peek());
935 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
936 if (tokenLevel < precedenceLevel)
937 return true;
938
939 do {
940 // ... op
941 TSourceLoc loc = token.loc;
942 advanceToken();
943
944 // ... expression
945 TIntermTyped* rightNode = nullptr;
946 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
947 expected("expression");
948 return false;
949 }
950
951 node = intermediate.addBinaryMath(op, node, rightNode, loc);
952
953 if (! peekTokenClass(EHTokComma))
954 return true;
955 } while (true);
956}
957
958// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -0600959// : (type) unary_expression
960// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -0600961// | - unary_expression
962// | ! unary_expression
963// | ~ unary_expression
964// | ++ unary_expression
965// | -- unary_expression
966// | postfix_expression
967//
968bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
969{
John Kessenich1cc1a282016-06-03 16:55:49 -0600970 // (type) unary_expression
971 // Have to look two steps ahead, because this could be, e.g., a
972 // postfix_expression instead, since that also starts with at "(".
973 if (acceptTokenClass(EHTokLeftParen)) {
974 TType castType;
975 if (acceptType(castType)) {
976 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600977 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -0600978 return false;
979 }
980
981 // We've matched "(type)" now, get the expression to cast
982 TSourceLoc loc = token.loc;
983 if (! acceptUnaryExpression(node))
984 return false;
985
986 // Hook it up like a constructor
987 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
988 if (constructorFunction == nullptr) {
989 expected("type that can be constructed");
990 return false;
991 }
992 TIntermTyped* arguments = nullptr;
993 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
994 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
995
996 return true;
997 } else {
998 // This isn't a type cast, but it still started "(", so if it is a
999 // unary expression, it can only be a postfix_expression, so try that.
1000 // Back it up first.
1001 recedeToken();
1002 return acceptPostfixExpression(node);
1003 }
1004 }
1005
1006 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001007 TOperator unaryOp = HlslOpMap::preUnary(peek());
1008
John Kessenich1cc1a282016-06-03 16:55:49 -06001009 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001010 if (unaryOp == EOpNull)
1011 return acceptPostfixExpression(node);
1012
1013 // op unary_expression
1014 TSourceLoc loc = token.loc;
1015 advanceToken();
1016 if (! acceptUnaryExpression(node))
1017 return false;
1018
1019 // + is a no-op
1020 if (unaryOp == EOpAdd)
1021 return true;
1022
1023 node = intermediate.addUnaryMath(unaryOp, node, loc);
1024
1025 return node != nullptr;
1026}
1027
1028// postfix_expression
1029// : LEFT_PAREN expression RIGHT_PAREN
1030// | literal
1031// | constructor
1032// | identifier
1033// | function_call
1034// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1035// | postfix_expression DOT IDENTIFIER
1036// | postfix_expression INC_OP
1037// | postfix_expression DEC_OP
1038//
1039bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1040{
1041 // Not implemented as self-recursive:
1042 // The logical "right recursion" is done with an loop at the end
1043
1044 // idToken will pick up either a variable or a function name in a function call
1045 HlslToken idToken;
1046
John Kessenich21472ae2016-06-04 11:46:33 -06001047 // Find something before the postfix operations, as they can't operate
1048 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001049 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001050 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001051 if (! acceptExpression(node)) {
1052 expected("expression");
1053 return false;
1054 }
1055 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001056 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001057 return false;
1058 }
John Kessenich34fb0362016-05-03 23:17:20 -06001059 } else if (acceptLiteral(node)) {
1060 // literal (nothing else to do yet), go on to the
1061 } else if (acceptConstructor(node)) {
1062 // constructor (nothing else to do yet)
1063 } else if (acceptIdentifier(idToken)) {
1064 // identifier or function_call name
1065 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001066 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001067 } else if (acceptFunctionCall(idToken, node)) {
1068 // function_call (nothing else to do yet)
1069 } else {
1070 expected("function call arguments");
1071 return false;
1072 }
John Kessenich21472ae2016-06-04 11:46:33 -06001073 } else {
1074 // nothing found, can't post operate
1075 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001076 }
1077
John Kessenich21472ae2016-06-04 11:46:33 -06001078 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001079 do {
1080 TSourceLoc loc = token.loc;
1081 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001082
John Kessenich34fb0362016-05-03 23:17:20 -06001083 // Consume only a valid post-unary operator, otherwise we are done.
1084 switch (postOp) {
1085 case EOpIndexDirectStruct:
1086 case EOpIndexIndirect:
1087 case EOpPostIncrement:
1088 case EOpPostDecrement:
1089 advanceToken();
1090 break;
1091 default:
1092 return true;
1093 }
John Kessenich87142c72016-03-12 20:24:24 -07001094
John Kessenich34fb0362016-05-03 23:17:20 -06001095 // We have a valid post-unary operator, process it.
1096 switch (postOp) {
1097 case EOpIndexDirectStruct:
1098 // todo
1099 break;
1100 case EOpIndexIndirect:
1101 {
1102 TIntermTyped* indexNode = nullptr;
1103 if (! acceptExpression(indexNode) ||
1104 ! peekTokenClass(EHTokRightBracket)) {
1105 expected("expression followed by ']'");
1106 return false;
1107 }
1108 // todo: node = intermediate.addBinaryMath(
1109 }
1110 case EOpPostIncrement:
1111 case EOpPostDecrement:
1112 node = intermediate.addUnaryMath(postOp, node, loc);
1113 break;
1114 default:
1115 assert(0);
1116 break;
1117 }
1118 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001119}
1120
John Kessenichd016be12016-03-13 11:24:20 -06001121// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001122// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001123//
1124bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1125{
1126 // type
1127 TType type;
1128 if (acceptType(type)) {
1129 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1130 if (constructorFunction == nullptr)
1131 return false;
1132
1133 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001134 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001135 if (! acceptArguments(constructorFunction, arguments)) {
1136 expected("constructor arguments");
1137 return false;
1138 }
1139
1140 // hook it up
1141 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1142
1143 return true;
1144 }
1145
1146 return false;
1147}
1148
John Kessenich34fb0362016-05-03 23:17:20 -06001149// The function_call identifier was already recognized, and passed in as idToken.
1150//
1151// function_call
1152// : [idToken] arguments
1153//
John Kessenich4678ca92016-05-13 09:33:42 -06001154bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001155{
John Kessenich4678ca92016-05-13 09:33:42 -06001156 // arguments
1157 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1158 TIntermTyped* arguments = nullptr;
1159 if (! acceptArguments(function, arguments))
1160 return false;
1161
1162 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1163
1164 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001165}
1166
John Kessenich87142c72016-03-12 20:24:24 -07001167// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001168// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001169//
John Kessenichd016be12016-03-13 11:24:20 -06001170// The arguments are pushed onto the 'function' argument list and
1171// onto the 'arguments' aggregate.
1172//
John Kessenich4678ca92016-05-13 09:33:42 -06001173bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001174{
John Kessenich078d7f22016-03-14 10:02:11 -06001175 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001176 if (! acceptTokenClass(EHTokLeftParen))
1177 return false;
1178
1179 do {
John Kessenichd016be12016-03-13 11:24:20 -06001180 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001181 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001182 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001183 break;
John Kessenichd016be12016-03-13 11:24:20 -06001184
1185 // hook it up
1186 parseContext.handleFunctionArgument(function, arguments, arg);
1187
John Kessenich078d7f22016-03-14 10:02:11 -06001188 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001189 if (! acceptTokenClass(EHTokComma))
1190 break;
1191 } while (true);
1192
John Kessenich078d7f22016-03-14 10:02:11 -06001193 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001194 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001195 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001196 return false;
1197 }
1198
1199 return true;
1200}
1201
1202bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1203{
1204 switch (token.tokenClass) {
1205 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001206 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001207 break;
1208 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001209 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001210 break;
1211 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001212 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001213 break;
1214 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001215 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001216 break;
1217
1218 default:
1219 return false;
1220 }
1221
1222 advanceToken();
1223
1224 return true;
1225}
1226
John Kessenich5f934b02016-03-13 17:58:25 -06001227// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001228// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001229//
John Kessenich21472ae2016-06-04 11:46:33 -06001230bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001231{
John Kessenich21472ae2016-06-04 11:46:33 -06001232 TIntermAggregate* compoundStatement = nullptr;
1233
John Kessenich34fb0362016-05-03 23:17:20 -06001234 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001235 if (! acceptTokenClass(EHTokLeftBrace))
1236 return false;
1237
1238 // statement statement ...
1239 TIntermNode* statement = nullptr;
1240 while (acceptStatement(statement)) {
1241 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001242 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001243 }
John Kessenich34fb0362016-05-03 23:17:20 -06001244 if (compoundStatement)
1245 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001246
John Kessenich21472ae2016-06-04 11:46:33 -06001247 retStatement = compoundStatement;
1248
John Kessenich34fb0362016-05-03 23:17:20 -06001249 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001250 return acceptTokenClass(EHTokRightBrace);
1251}
1252
John Kessenich0d2b6de2016-06-05 11:23:11 -06001253bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1254{
1255 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001256 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001257 parseContext.popScope();
1258
1259 return result;
1260}
1261
John Kessenich077e0522016-06-09 02:02:17 -06001262bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001263{
John Kessenich077e0522016-06-09 02:02:17 -06001264 parseContext.pushScope();
1265 bool result = acceptCompoundStatement(statement);
1266 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001267
1268 return result;
1269}
1270
John Kessenich5f934b02016-03-13 17:58:25 -06001271// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001272// : attributes attributed_statement
1273//
1274// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001275// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001276// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001277// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001278// | declaration_statement
1279// | selection_statement
1280// | switch_statement
1281// | case_label
1282// | iteration_statement
1283// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001284//
1285bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1286{
John Kessenich21472ae2016-06-04 11:46:33 -06001287 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001288
John Kessenich21472ae2016-06-04 11:46:33 -06001289 // attributes
1290 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001291
John Kessenich21472ae2016-06-04 11:46:33 -06001292 // attributed_statement
1293 switch (peek()) {
1294 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001295 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001296
John Kessenich21472ae2016-06-04 11:46:33 -06001297 case EHTokIf:
1298 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001299
John Kessenich21472ae2016-06-04 11:46:33 -06001300 case EHTokSwitch:
1301 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001302
John Kessenich21472ae2016-06-04 11:46:33 -06001303 case EHTokFor:
1304 case EHTokDo:
1305 case EHTokWhile:
1306 return acceptIterationStatement(statement);
1307
1308 case EHTokContinue:
1309 case EHTokBreak:
1310 case EHTokDiscard:
1311 case EHTokReturn:
1312 return acceptJumpStatement(statement);
1313
1314 case EHTokCase:
1315 return acceptCaseLabel(statement);
1316
1317 case EHTokSemicolon:
1318 return acceptTokenClass(EHTokSemicolon);
1319
1320 case EHTokRightBrace:
1321 // Performance: not strictly necessary, but stops a bunch of hunting early,
1322 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001323 return false;
1324
John Kessenich21472ae2016-06-04 11:46:33 -06001325 default:
1326 {
1327 // declaration
1328 if (acceptDeclaration(statement))
1329 return true;
1330
1331 // expression
1332 TIntermTyped* node;
1333 if (acceptExpression(node))
1334 statement = node;
1335 else
1336 return false;
1337
1338 // SEMICOLON (following an expression)
1339 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001340 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001341 return false;
1342 }
1343 }
1344 }
1345
John Kessenich5f934b02016-03-13 17:58:25 -06001346 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001347}
1348
John Kessenich21472ae2016-06-04 11:46:33 -06001349// attributes
1350// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1351//
1352// attribute:
1353// : UNROLL
1354// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1355// | FASTOPT
1356// | ALLOW_UAV_CONDITION
1357// | BRANCH
1358// | FLATTEN
1359// | FORCECASE
1360// | CALL
1361//
1362void HlslGrammar::acceptAttributes()
1363{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001364 // For now, accept the [ XXX(X) ] syntax, but drop.
1365 // TODO: subset to correct set? Pass on?
1366 do {
1367 // LEFT_BRACKET?
1368 if (! acceptTokenClass(EHTokLeftBracket))
1369 return;
1370
1371 // attribute
1372 if (peekTokenClass(EHTokIdentifier)) {
1373 // 'token.string' is the attribute
1374 advanceToken();
1375 } else if (! peekTokenClass(EHTokRightBracket)) {
1376 expected("identifier");
1377 advanceToken();
1378 }
1379
1380 // (x)
1381 if (acceptTokenClass(EHTokLeftParen)) {
1382 TIntermTyped* node;
1383 if (! acceptLiteral(node))
1384 expected("literal");
1385 // 'node' has the literal in it
1386 if (! acceptTokenClass(EHTokRightParen))
1387 expected(")");
1388 }
1389
1390 // RIGHT_BRACKET
1391 if (acceptTokenClass(EHTokRightBracket))
1392 continue;
1393
1394 expected("]");
1395 return;
1396
1397 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001398}
1399
John Kessenich0d2b6de2016-06-05 11:23:11 -06001400// selection_statement
1401// : IF LEFT_PAREN expression RIGHT_PAREN statement
1402// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1403//
John Kessenich21472ae2016-06-04 11:46:33 -06001404bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1405{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001406 TSourceLoc loc = token.loc;
1407
1408 // IF
1409 if (! acceptTokenClass(EHTokIf))
1410 return false;
1411
1412 // so that something declared in the condition is scoped to the lifetimes
1413 // of the then-else statements
1414 parseContext.pushScope();
1415
1416 // LEFT_PAREN expression RIGHT_PAREN
1417 TIntermTyped* condition;
1418 if (! acceptParenExpression(condition))
1419 return false;
1420
1421 // create the child statements
1422 TIntermNodePair thenElse = { nullptr, nullptr };
1423
1424 // then statement
1425 if (! acceptScopedStatement(thenElse.node1)) {
1426 expected("then statement");
1427 return false;
1428 }
1429
1430 // ELSE
1431 if (acceptTokenClass(EHTokElse)) {
1432 // else statement
1433 if (! acceptScopedStatement(thenElse.node2)) {
1434 expected("else statement");
1435 return false;
1436 }
1437 }
1438
1439 // Put the pieces together
1440 statement = intermediate.addSelection(condition, thenElse, loc);
1441 parseContext.popScope();
1442
1443 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001444}
1445
1446bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1447{
1448 return false;
1449}
1450
John Kessenich119f8f62016-06-05 15:44:07 -06001451// iteration_statement
1452// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1453// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1454// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1455//
1456// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001457bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1458{
John Kessenich119f8f62016-06-05 15:44:07 -06001459 TSourceLoc loc = token.loc;
1460 TIntermTyped* condition = nullptr;
1461
1462 EHlslTokenClass loop = peek();
1463 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1464
1465 // WHILE or DO or FOR
1466 advanceToken();
1467
1468 switch (loop) {
1469 case EHTokWhile:
1470 // so that something declared in the condition is scoped to the lifetime
1471 // of the while sub-statement
1472 parseContext.pushScope();
1473 parseContext.nestLooping();
1474
1475 // LEFT_PAREN condition RIGHT_PAREN
1476 if (! acceptParenExpression(condition))
1477 return false;
1478
1479 // statement
1480 if (! acceptScopedStatement(statement)) {
1481 expected("while sub-statement");
1482 return false;
1483 }
1484
1485 parseContext.unnestLooping();
1486 parseContext.popScope();
1487
1488 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1489
1490 return true;
1491
1492 case EHTokDo:
1493 parseContext.nestLooping();
1494
1495 if (! acceptTokenClass(EHTokLeftBrace))
1496 expected("{");
1497
1498 // statement
1499 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1500 expected("do sub-statement");
1501 return false;
1502 }
1503
1504 if (! acceptTokenClass(EHTokRightBrace))
1505 expected("}");
1506
1507 // WHILE
1508 if (! acceptTokenClass(EHTokWhile)) {
1509 expected("while");
1510 return false;
1511 }
1512
1513 // LEFT_PAREN condition RIGHT_PAREN
1514 TIntermTyped* condition;
1515 if (! acceptParenExpression(condition))
1516 return false;
1517
1518 if (! acceptTokenClass(EHTokSemicolon))
1519 expected(";");
1520
1521 parseContext.unnestLooping();
1522
1523 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1524
1525 return true;
1526
1527 case EHTokFor:
1528 {
1529 // LEFT_PAREN
1530 if (! acceptTokenClass(EHTokLeftParen))
1531 expected("(");
1532
1533 // so that something declared in the condition is scoped to the lifetime
1534 // of the for sub-statement
1535 parseContext.pushScope();
1536
1537 // initializer SEMI_COLON
1538 TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
1539 acceptExpression(initializer);
1540 if (! acceptTokenClass(EHTokSemicolon))
1541 expected(";");
1542
1543 parseContext.nestLooping();
1544
1545 // condition SEMI_COLON
1546 acceptExpression(condition);
1547 if (! acceptTokenClass(EHTokSemicolon))
1548 expected(";");
1549
1550 // iterator SEMI_COLON
1551 TIntermTyped* iterator = nullptr;
1552 acceptExpression(iterator);
1553 if (! acceptTokenClass(EHTokRightParen))
1554 expected(")");
1555
1556 // statement
1557 if (! acceptScopedStatement(statement)) {
1558 expected("for sub-statement");
1559 return false;
1560 }
1561
1562 statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
1563
1564 parseContext.popScope();
1565 parseContext.unnestLooping();
1566
1567 return true;
1568 }
1569
1570 default:
1571 return false;
1572 }
John Kessenich21472ae2016-06-04 11:46:33 -06001573}
1574
1575// jump_statement
1576// : CONTINUE SEMICOLON
1577// | BREAK SEMICOLON
1578// | DISCARD SEMICOLON
1579// | RETURN SEMICOLON
1580// | RETURN expression SEMICOLON
1581//
1582bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1583{
1584 switch (peek()) {
1585 case EHTokContinue:
1586 case EHTokBreak:
1587 case EHTokDiscard:
1588 // TODO
1589 return false;
1590
1591 case EHTokReturn:
1592 // return
1593 if (acceptTokenClass(EHTokReturn)) {
1594 // expression
1595 TIntermTyped* node;
1596 if (acceptExpression(node)) {
1597 // hook it up
1598 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1599 } else
1600 statement = intermediate.addBranch(EOpReturn, token.loc);
1601
1602 // SEMICOLON
1603 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001604 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001605 return false;
1606 }
1607
1608 return true;
1609 }
1610
1611 default:
1612 return false;
1613 }
1614}
1615
1616
1617bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1618{
1619 return false;
1620}
1621
John Kessenich630dd7d2016-06-12 23:52:12 -06001622// post_decls
1623// : COLON semantic // optional
1624// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1625// COLON REGISTER // optional
1626// annotations // optional
1627//
1628void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06001629{
John Kessenich630dd7d2016-06-12 23:52:12 -06001630 do {
1631 // COLON
1632 if (acceptTokenClass(EHTokColon)) {
1633 HlslToken idToken;
1634 if (acceptTokenClass(EHTokPackOffset)) {
1635 if (! acceptTokenClass(EHTokLeftParen)) {
1636 expected("(");
1637 return;
1638 }
1639 acceptTokenClass(EHTokIdentifier);
1640 acceptTokenClass(EHTokDot);
1641 acceptTokenClass(EHTokIdentifier);
1642 if (! acceptTokenClass(EHTokRightParen)) {
1643 expected(")");
1644 break;
1645 }
1646 // TODO: process the packoffset information
1647 } else if (! acceptIdentifier(idToken)) {
1648 expected("semantic or packoffset or register");
1649 return;
1650 } else if (*idToken.string == "register") {
1651 if (! acceptTokenClass(EHTokLeftParen)) {
1652 expected("(");
1653 return;
1654 }
1655 acceptTokenClass(EHTokIdentifier);
1656 acceptTokenClass(EHTokComma);
1657 acceptTokenClass(EHTokIdentifier);
1658 acceptTokenClass(EHTokLeftBracket);
1659 if (peekTokenClass(EHTokIntConstant))
1660 advanceToken();
1661 acceptTokenClass(EHTokRightBracket);
1662 if (! acceptTokenClass(EHTokRightParen)) {
1663 expected(")");
1664 break;
1665 }
1666 // TODO: process the register information
1667 } else {
1668 // semantic, in idToken.string
1669 parseContext.handleSemantic(type, *idToken.string);
1670 }
1671 } else if (acceptTokenClass(EHTokLeftAngle)) {
1672 // TODO: process annotations, just accepting them for now
1673 do {
1674 if (peekTokenClass(EHTokNone))
1675 return;
1676 if (acceptTokenClass(EHTokRightAngle))
1677 break;
1678 advanceToken();
1679 } while (true);
1680 } else
1681 break;
John Kessenich078d7f22016-03-14 10:02:11 -06001682
John Kessenich630dd7d2016-06-12 23:52:12 -06001683 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06001684}
1685
John Kesseniche01a9bc2016-03-12 20:11:22 -07001686} // end namespace glslang