blob: 15ff2beec5cd1fc6b6350188db8c2ebfe2f62ed1 [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 Kessenich5aa59e22016-06-17 15:50:47 -0600788 parseContext.paramFix(*type);
789
John Kessenichaecd4972016-03-14 10:46:34 -0600790 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600791 function.addParameter(param);
792
793 return true;
794}
795
796// Do the work to create the function definition in addition to
797// parsing the body (compound_statement).
798bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
799{
800 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
801
John Kessenich077e0522016-06-09 02:02:17 -0600802 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600803 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
804
805 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600806 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600807 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600808 node = intermediate.growAggregate(node, functionBody);
809 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600810 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600811 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600812
813 return true;
814 }
815
816 return false;
817}
818
John Kessenich0d2b6de2016-06-05 11:23:11 -0600819// Accept an expression with parenthesis around it, where
820// the parenthesis ARE NOT expression parenthesis, but the
821// syntactically required ones like in "if ( expression )"
822//
823// Note this one is not set up to be speculative; as it gives
824// errors if not found.
825//
826bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
827{
828 // LEFT_PAREN
829 if (! acceptTokenClass(EHTokLeftParen))
830 expected("(");
831
832 if (! acceptExpression(expression)) {
833 expected("expression");
834 return false;
835 }
836
837 // RIGHT_PAREN
838 if (! acceptTokenClass(EHTokRightParen))
839 expected(")");
840
841 return true;
842}
843
John Kessenich34fb0362016-05-03 23:17:20 -0600844// The top-level full expression recognizer.
845//
John Kessenich87142c72016-03-12 20:24:24 -0700846// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600847// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700848//
849bool HlslGrammar::acceptExpression(TIntermTyped*& node)
850{
LoopDawgef764a22016-06-03 09:17:51 -0600851 node = nullptr;
852
John Kessenich34fb0362016-05-03 23:17:20 -0600853 // assignment_expression
854 if (! acceptAssignmentExpression(node))
855 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600856
John Kessenich34fb0362016-05-03 23:17:20 -0600857 if (! peekTokenClass(EHTokComma))
858 return true;
859
860 do {
861 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600862 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600863 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600864
John Kessenich34fb0362016-05-03 23:17:20 -0600865 // ... assignment_expression
866 TIntermTyped* rightNode = nullptr;
867 if (! acceptAssignmentExpression(rightNode)) {
868 expected("assignment expression");
869 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600870 }
871
John Kessenich34fb0362016-05-03 23:17:20 -0600872 node = intermediate.addComma(node, rightNode, loc);
873
874 if (! peekTokenClass(EHTokComma))
875 return true;
876 } while (true);
877}
878
879// Accept an assignment expression, where assignment operations
880// associate right-to-left. This is, it is implicit, for example
881//
882// a op (b op (c op d))
883//
884// assigment_expression
885// : binary_expression op binary_expression op binary_expression ...
886//
887bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
888{
889 if (! acceptBinaryExpression(node, PlLogicalOr))
890 return false;
891
892 TOperator assignOp = HlslOpMap::assignment(peek());
893 if (assignOp == EOpNull)
894 return true;
895
896 // ... op
897 TSourceLoc loc = token.loc;
898 advanceToken();
899
900 // ... binary_expression
901 // But, done by recursing this function, which automatically
902 // gets the right-to-left associativity.
903 TIntermTyped* rightNode = nullptr;
904 if (! acceptAssignmentExpression(rightNode)) {
905 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600906 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700907 }
908
John Kessenich34fb0362016-05-03 23:17:20 -0600909 node = intermediate.addAssign(assignOp, node, rightNode, loc);
910
911 if (! peekTokenClass(EHTokComma))
912 return true;
913
914 return true;
915}
916
917// Accept a binary expression, for binary operations that
918// associate left-to-right. This is, it is implicit, for example
919//
920// ((a op b) op c) op d
921//
922// binary_expression
923// : expression op expression op expression ...
924//
925// where 'expression' is the next higher level in precedence.
926//
927bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
928{
929 if (precedenceLevel > PlMul)
930 return acceptUnaryExpression(node);
931
932 // assignment_expression
933 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
934 return false;
935
936 TOperator op = HlslOpMap::binary(peek());
937 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
938 if (tokenLevel < precedenceLevel)
939 return true;
940
941 do {
942 // ... op
943 TSourceLoc loc = token.loc;
944 advanceToken();
945
946 // ... expression
947 TIntermTyped* rightNode = nullptr;
948 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
949 expected("expression");
950 return false;
951 }
952
953 node = intermediate.addBinaryMath(op, node, rightNode, loc);
954
955 if (! peekTokenClass(EHTokComma))
956 return true;
957 } while (true);
958}
959
960// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -0600961// : (type) unary_expression
962// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -0600963// | - unary_expression
964// | ! unary_expression
965// | ~ unary_expression
966// | ++ unary_expression
967// | -- unary_expression
968// | postfix_expression
969//
970bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
971{
John Kessenich1cc1a282016-06-03 16:55:49 -0600972 // (type) unary_expression
973 // Have to look two steps ahead, because this could be, e.g., a
974 // postfix_expression instead, since that also starts with at "(".
975 if (acceptTokenClass(EHTokLeftParen)) {
976 TType castType;
977 if (acceptType(castType)) {
978 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600979 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -0600980 return false;
981 }
982
983 // We've matched "(type)" now, get the expression to cast
984 TSourceLoc loc = token.loc;
985 if (! acceptUnaryExpression(node))
986 return false;
987
988 // Hook it up like a constructor
989 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
990 if (constructorFunction == nullptr) {
991 expected("type that can be constructed");
992 return false;
993 }
994 TIntermTyped* arguments = nullptr;
995 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
996 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
997
998 return true;
999 } else {
1000 // This isn't a type cast, but it still started "(", so if it is a
1001 // unary expression, it can only be a postfix_expression, so try that.
1002 // Back it up first.
1003 recedeToken();
1004 return acceptPostfixExpression(node);
1005 }
1006 }
1007
1008 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001009 TOperator unaryOp = HlslOpMap::preUnary(peek());
1010
John Kessenich1cc1a282016-06-03 16:55:49 -06001011 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001012 if (unaryOp == EOpNull)
1013 return acceptPostfixExpression(node);
1014
1015 // op unary_expression
1016 TSourceLoc loc = token.loc;
1017 advanceToken();
1018 if (! acceptUnaryExpression(node))
1019 return false;
1020
1021 // + is a no-op
1022 if (unaryOp == EOpAdd)
1023 return true;
1024
1025 node = intermediate.addUnaryMath(unaryOp, node, loc);
1026
1027 return node != nullptr;
1028}
1029
1030// postfix_expression
1031// : LEFT_PAREN expression RIGHT_PAREN
1032// | literal
1033// | constructor
1034// | identifier
1035// | function_call
1036// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1037// | postfix_expression DOT IDENTIFIER
1038// | postfix_expression INC_OP
1039// | postfix_expression DEC_OP
1040//
1041bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1042{
1043 // Not implemented as self-recursive:
1044 // The logical "right recursion" is done with an loop at the end
1045
1046 // idToken will pick up either a variable or a function name in a function call
1047 HlslToken idToken;
1048
John Kessenich21472ae2016-06-04 11:46:33 -06001049 // Find something before the postfix operations, as they can't operate
1050 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001051 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001052 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001053 if (! acceptExpression(node)) {
1054 expected("expression");
1055 return false;
1056 }
1057 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001058 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001059 return false;
1060 }
John Kessenich34fb0362016-05-03 23:17:20 -06001061 } else if (acceptLiteral(node)) {
1062 // literal (nothing else to do yet), go on to the
1063 } else if (acceptConstructor(node)) {
1064 // constructor (nothing else to do yet)
1065 } else if (acceptIdentifier(idToken)) {
1066 // identifier or function_call name
1067 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001068 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001069 } else if (acceptFunctionCall(idToken, node)) {
1070 // function_call (nothing else to do yet)
1071 } else {
1072 expected("function call arguments");
1073 return false;
1074 }
John Kessenich21472ae2016-06-04 11:46:33 -06001075 } else {
1076 // nothing found, can't post operate
1077 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001078 }
1079
John Kessenich21472ae2016-06-04 11:46:33 -06001080 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001081 do {
1082 TSourceLoc loc = token.loc;
1083 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001084
John Kessenich34fb0362016-05-03 23:17:20 -06001085 // Consume only a valid post-unary operator, otherwise we are done.
1086 switch (postOp) {
1087 case EOpIndexDirectStruct:
1088 case EOpIndexIndirect:
1089 case EOpPostIncrement:
1090 case EOpPostDecrement:
1091 advanceToken();
1092 break;
1093 default:
1094 return true;
1095 }
John Kessenich87142c72016-03-12 20:24:24 -07001096
John Kessenich34fb0362016-05-03 23:17:20 -06001097 // We have a valid post-unary operator, process it.
1098 switch (postOp) {
1099 case EOpIndexDirectStruct:
1100 // todo
1101 break;
1102 case EOpIndexIndirect:
1103 {
1104 TIntermTyped* indexNode = nullptr;
1105 if (! acceptExpression(indexNode) ||
1106 ! peekTokenClass(EHTokRightBracket)) {
1107 expected("expression followed by ']'");
1108 return false;
1109 }
1110 // todo: node = intermediate.addBinaryMath(
1111 }
1112 case EOpPostIncrement:
1113 case EOpPostDecrement:
1114 node = intermediate.addUnaryMath(postOp, node, loc);
1115 break;
1116 default:
1117 assert(0);
1118 break;
1119 }
1120 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001121}
1122
John Kessenichd016be12016-03-13 11:24:20 -06001123// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001124// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001125//
1126bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1127{
1128 // type
1129 TType type;
1130 if (acceptType(type)) {
1131 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1132 if (constructorFunction == nullptr)
1133 return false;
1134
1135 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001136 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001137 if (! acceptArguments(constructorFunction, arguments)) {
1138 expected("constructor arguments");
1139 return false;
1140 }
1141
1142 // hook it up
1143 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1144
1145 return true;
1146 }
1147
1148 return false;
1149}
1150
John Kessenich34fb0362016-05-03 23:17:20 -06001151// The function_call identifier was already recognized, and passed in as idToken.
1152//
1153// function_call
1154// : [idToken] arguments
1155//
John Kessenich4678ca92016-05-13 09:33:42 -06001156bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001157{
John Kessenich4678ca92016-05-13 09:33:42 -06001158 // arguments
1159 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1160 TIntermTyped* arguments = nullptr;
1161 if (! acceptArguments(function, arguments))
1162 return false;
1163
1164 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1165
1166 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001167}
1168
John Kessenich87142c72016-03-12 20:24:24 -07001169// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001170// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001171//
John Kessenichd016be12016-03-13 11:24:20 -06001172// The arguments are pushed onto the 'function' argument list and
1173// onto the 'arguments' aggregate.
1174//
John Kessenich4678ca92016-05-13 09:33:42 -06001175bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001176{
John Kessenich078d7f22016-03-14 10:02:11 -06001177 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001178 if (! acceptTokenClass(EHTokLeftParen))
1179 return false;
1180
1181 do {
John Kessenichd016be12016-03-13 11:24:20 -06001182 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001183 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001184 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001185 break;
John Kessenichd016be12016-03-13 11:24:20 -06001186
1187 // hook it up
1188 parseContext.handleFunctionArgument(function, arguments, arg);
1189
John Kessenich078d7f22016-03-14 10:02:11 -06001190 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001191 if (! acceptTokenClass(EHTokComma))
1192 break;
1193 } while (true);
1194
John Kessenich078d7f22016-03-14 10:02:11 -06001195 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001196 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001197 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001198 return false;
1199 }
1200
1201 return true;
1202}
1203
1204bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1205{
1206 switch (token.tokenClass) {
1207 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001208 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001209 break;
1210 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001211 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001212 break;
1213 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001214 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001215 break;
1216 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001217 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001218 break;
1219
1220 default:
1221 return false;
1222 }
1223
1224 advanceToken();
1225
1226 return true;
1227}
1228
John Kessenich5f934b02016-03-13 17:58:25 -06001229// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001230// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001231//
John Kessenich21472ae2016-06-04 11:46:33 -06001232bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001233{
John Kessenich21472ae2016-06-04 11:46:33 -06001234 TIntermAggregate* compoundStatement = nullptr;
1235
John Kessenich34fb0362016-05-03 23:17:20 -06001236 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001237 if (! acceptTokenClass(EHTokLeftBrace))
1238 return false;
1239
1240 // statement statement ...
1241 TIntermNode* statement = nullptr;
1242 while (acceptStatement(statement)) {
1243 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001244 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001245 }
John Kessenich34fb0362016-05-03 23:17:20 -06001246 if (compoundStatement)
1247 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001248
John Kessenich21472ae2016-06-04 11:46:33 -06001249 retStatement = compoundStatement;
1250
John Kessenich34fb0362016-05-03 23:17:20 -06001251 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001252 return acceptTokenClass(EHTokRightBrace);
1253}
1254
John Kessenich0d2b6de2016-06-05 11:23:11 -06001255bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1256{
1257 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001258 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001259 parseContext.popScope();
1260
1261 return result;
1262}
1263
John Kessenich077e0522016-06-09 02:02:17 -06001264bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001265{
John Kessenich077e0522016-06-09 02:02:17 -06001266 parseContext.pushScope();
1267 bool result = acceptCompoundStatement(statement);
1268 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001269
1270 return result;
1271}
1272
John Kessenich5f934b02016-03-13 17:58:25 -06001273// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001274// : attributes attributed_statement
1275//
1276// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001277// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001278// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001279// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001280// | declaration_statement
1281// | selection_statement
1282// | switch_statement
1283// | case_label
1284// | iteration_statement
1285// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001286//
1287bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1288{
John Kessenich21472ae2016-06-04 11:46:33 -06001289 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001290
John Kessenich21472ae2016-06-04 11:46:33 -06001291 // attributes
1292 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001293
John Kessenich21472ae2016-06-04 11:46:33 -06001294 // attributed_statement
1295 switch (peek()) {
1296 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001297 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001298
John Kessenich21472ae2016-06-04 11:46:33 -06001299 case EHTokIf:
1300 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001301
John Kessenich21472ae2016-06-04 11:46:33 -06001302 case EHTokSwitch:
1303 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001304
John Kessenich21472ae2016-06-04 11:46:33 -06001305 case EHTokFor:
1306 case EHTokDo:
1307 case EHTokWhile:
1308 return acceptIterationStatement(statement);
1309
1310 case EHTokContinue:
1311 case EHTokBreak:
1312 case EHTokDiscard:
1313 case EHTokReturn:
1314 return acceptJumpStatement(statement);
1315
1316 case EHTokCase:
1317 return acceptCaseLabel(statement);
1318
1319 case EHTokSemicolon:
1320 return acceptTokenClass(EHTokSemicolon);
1321
1322 case EHTokRightBrace:
1323 // Performance: not strictly necessary, but stops a bunch of hunting early,
1324 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001325 return false;
1326
John Kessenich21472ae2016-06-04 11:46:33 -06001327 default:
1328 {
1329 // declaration
1330 if (acceptDeclaration(statement))
1331 return true;
1332
1333 // expression
1334 TIntermTyped* node;
1335 if (acceptExpression(node))
1336 statement = node;
1337 else
1338 return false;
1339
1340 // SEMICOLON (following an expression)
1341 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001342 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001343 return false;
1344 }
1345 }
1346 }
1347
John Kessenich5f934b02016-03-13 17:58:25 -06001348 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001349}
1350
John Kessenich21472ae2016-06-04 11:46:33 -06001351// attributes
1352// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1353//
1354// attribute:
1355// : UNROLL
1356// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1357// | FASTOPT
1358// | ALLOW_UAV_CONDITION
1359// | BRANCH
1360// | FLATTEN
1361// | FORCECASE
1362// | CALL
1363//
1364void HlslGrammar::acceptAttributes()
1365{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001366 // For now, accept the [ XXX(X) ] syntax, but drop.
1367 // TODO: subset to correct set? Pass on?
1368 do {
1369 // LEFT_BRACKET?
1370 if (! acceptTokenClass(EHTokLeftBracket))
1371 return;
1372
1373 // attribute
1374 if (peekTokenClass(EHTokIdentifier)) {
1375 // 'token.string' is the attribute
1376 advanceToken();
1377 } else if (! peekTokenClass(EHTokRightBracket)) {
1378 expected("identifier");
1379 advanceToken();
1380 }
1381
1382 // (x)
1383 if (acceptTokenClass(EHTokLeftParen)) {
1384 TIntermTyped* node;
1385 if (! acceptLiteral(node))
1386 expected("literal");
1387 // 'node' has the literal in it
1388 if (! acceptTokenClass(EHTokRightParen))
1389 expected(")");
1390 }
1391
1392 // RIGHT_BRACKET
1393 if (acceptTokenClass(EHTokRightBracket))
1394 continue;
1395
1396 expected("]");
1397 return;
1398
1399 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001400}
1401
John Kessenich0d2b6de2016-06-05 11:23:11 -06001402// selection_statement
1403// : IF LEFT_PAREN expression RIGHT_PAREN statement
1404// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1405//
John Kessenich21472ae2016-06-04 11:46:33 -06001406bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1407{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001408 TSourceLoc loc = token.loc;
1409
1410 // IF
1411 if (! acceptTokenClass(EHTokIf))
1412 return false;
1413
1414 // so that something declared in the condition is scoped to the lifetimes
1415 // of the then-else statements
1416 parseContext.pushScope();
1417
1418 // LEFT_PAREN expression RIGHT_PAREN
1419 TIntermTyped* condition;
1420 if (! acceptParenExpression(condition))
1421 return false;
1422
1423 // create the child statements
1424 TIntermNodePair thenElse = { nullptr, nullptr };
1425
1426 // then statement
1427 if (! acceptScopedStatement(thenElse.node1)) {
1428 expected("then statement");
1429 return false;
1430 }
1431
1432 // ELSE
1433 if (acceptTokenClass(EHTokElse)) {
1434 // else statement
1435 if (! acceptScopedStatement(thenElse.node2)) {
1436 expected("else statement");
1437 return false;
1438 }
1439 }
1440
1441 // Put the pieces together
1442 statement = intermediate.addSelection(condition, thenElse, loc);
1443 parseContext.popScope();
1444
1445 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001446}
1447
1448bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1449{
1450 return false;
1451}
1452
John Kessenich119f8f62016-06-05 15:44:07 -06001453// iteration_statement
1454// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1455// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1456// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1457//
1458// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001459bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1460{
John Kessenich119f8f62016-06-05 15:44:07 -06001461 TSourceLoc loc = token.loc;
1462 TIntermTyped* condition = nullptr;
1463
1464 EHlslTokenClass loop = peek();
1465 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1466
1467 // WHILE or DO or FOR
1468 advanceToken();
1469
1470 switch (loop) {
1471 case EHTokWhile:
1472 // so that something declared in the condition is scoped to the lifetime
1473 // of the while sub-statement
1474 parseContext.pushScope();
1475 parseContext.nestLooping();
1476
1477 // LEFT_PAREN condition RIGHT_PAREN
1478 if (! acceptParenExpression(condition))
1479 return false;
1480
1481 // statement
1482 if (! acceptScopedStatement(statement)) {
1483 expected("while sub-statement");
1484 return false;
1485 }
1486
1487 parseContext.unnestLooping();
1488 parseContext.popScope();
1489
1490 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1491
1492 return true;
1493
1494 case EHTokDo:
1495 parseContext.nestLooping();
1496
1497 if (! acceptTokenClass(EHTokLeftBrace))
1498 expected("{");
1499
1500 // statement
1501 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1502 expected("do sub-statement");
1503 return false;
1504 }
1505
1506 if (! acceptTokenClass(EHTokRightBrace))
1507 expected("}");
1508
1509 // WHILE
1510 if (! acceptTokenClass(EHTokWhile)) {
1511 expected("while");
1512 return false;
1513 }
1514
1515 // LEFT_PAREN condition RIGHT_PAREN
1516 TIntermTyped* condition;
1517 if (! acceptParenExpression(condition))
1518 return false;
1519
1520 if (! acceptTokenClass(EHTokSemicolon))
1521 expected(";");
1522
1523 parseContext.unnestLooping();
1524
1525 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1526
1527 return true;
1528
1529 case EHTokFor:
1530 {
1531 // LEFT_PAREN
1532 if (! acceptTokenClass(EHTokLeftParen))
1533 expected("(");
1534
1535 // so that something declared in the condition is scoped to the lifetime
1536 // of the for sub-statement
1537 parseContext.pushScope();
1538
1539 // initializer SEMI_COLON
1540 TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
1541 acceptExpression(initializer);
1542 if (! acceptTokenClass(EHTokSemicolon))
1543 expected(";");
1544
1545 parseContext.nestLooping();
1546
1547 // condition SEMI_COLON
1548 acceptExpression(condition);
1549 if (! acceptTokenClass(EHTokSemicolon))
1550 expected(";");
1551
1552 // iterator SEMI_COLON
1553 TIntermTyped* iterator = nullptr;
1554 acceptExpression(iterator);
1555 if (! acceptTokenClass(EHTokRightParen))
1556 expected(")");
1557
1558 // statement
1559 if (! acceptScopedStatement(statement)) {
1560 expected("for sub-statement");
1561 return false;
1562 }
1563
1564 statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
1565
1566 parseContext.popScope();
1567 parseContext.unnestLooping();
1568
1569 return true;
1570 }
1571
1572 default:
1573 return false;
1574 }
John Kessenich21472ae2016-06-04 11:46:33 -06001575}
1576
1577// jump_statement
1578// : CONTINUE SEMICOLON
1579// | BREAK SEMICOLON
1580// | DISCARD SEMICOLON
1581// | RETURN SEMICOLON
1582// | RETURN expression SEMICOLON
1583//
1584bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1585{
1586 switch (peek()) {
1587 case EHTokContinue:
1588 case EHTokBreak:
1589 case EHTokDiscard:
1590 // TODO
1591 return false;
1592
1593 case EHTokReturn:
1594 // return
1595 if (acceptTokenClass(EHTokReturn)) {
1596 // expression
1597 TIntermTyped* node;
1598 if (acceptExpression(node)) {
1599 // hook it up
1600 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1601 } else
1602 statement = intermediate.addBranch(EOpReturn, token.loc);
1603
1604 // SEMICOLON
1605 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001606 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001607 return false;
1608 }
1609
1610 return true;
1611 }
1612
1613 default:
1614 return false;
1615 }
1616}
1617
1618
1619bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1620{
1621 return false;
1622}
1623
John Kessenich630dd7d2016-06-12 23:52:12 -06001624// post_decls
1625// : COLON semantic // optional
1626// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1627// COLON REGISTER // optional
1628// annotations // optional
1629//
1630void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06001631{
John Kessenich630dd7d2016-06-12 23:52:12 -06001632 do {
1633 // COLON
1634 if (acceptTokenClass(EHTokColon)) {
1635 HlslToken idToken;
1636 if (acceptTokenClass(EHTokPackOffset)) {
1637 if (! acceptTokenClass(EHTokLeftParen)) {
1638 expected("(");
1639 return;
1640 }
1641 acceptTokenClass(EHTokIdentifier);
1642 acceptTokenClass(EHTokDot);
1643 acceptTokenClass(EHTokIdentifier);
1644 if (! acceptTokenClass(EHTokRightParen)) {
1645 expected(")");
1646 break;
1647 }
1648 // TODO: process the packoffset information
1649 } else if (! acceptIdentifier(idToken)) {
1650 expected("semantic or packoffset or register");
1651 return;
1652 } else if (*idToken.string == "register") {
1653 if (! acceptTokenClass(EHTokLeftParen)) {
1654 expected("(");
1655 return;
1656 }
1657 acceptTokenClass(EHTokIdentifier);
1658 acceptTokenClass(EHTokComma);
1659 acceptTokenClass(EHTokIdentifier);
1660 acceptTokenClass(EHTokLeftBracket);
1661 if (peekTokenClass(EHTokIntConstant))
1662 advanceToken();
1663 acceptTokenClass(EHTokRightBracket);
1664 if (! acceptTokenClass(EHTokRightParen)) {
1665 expected(")");
1666 break;
1667 }
1668 // TODO: process the register information
1669 } else {
1670 // semantic, in idToken.string
1671 parseContext.handleSemantic(type, *idToken.string);
1672 }
1673 } else if (acceptTokenClass(EHTokLeftAngle)) {
1674 // TODO: process annotations, just accepting them for now
1675 do {
1676 if (peekTokenClass(EHTokNone))
1677 return;
1678 if (acceptTokenClass(EHTokRightAngle))
1679 break;
1680 advanceToken();
1681 } while (true);
1682 } else
1683 break;
John Kessenich078d7f22016-03-14 10:02:11 -06001684
John Kessenich630dd7d2016-06-12 23:52:12 -06001685 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06001686}
1687
John Kesseniche01a9bc2016-03-12 20:11:22 -07001688} // end namespace glslang