blob: c0d4f285734ed23f7c736b54bab95941cd4a90a6 [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
772// : fully_specified_type
773// | fully_specified_type identifier
774//
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 Kessenichaecd4972016-03-14 10:46:34 -0600786 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600787 function.addParameter(param);
788
789 return true;
790}
791
792// Do the work to create the function definition in addition to
793// parsing the body (compound_statement).
794bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
795{
796 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
797
John Kessenich077e0522016-06-09 02:02:17 -0600798 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600799 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
800
801 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600802 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600803 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600804 node = intermediate.growAggregate(node, functionBody);
805 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600806 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600807 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600808
809 return true;
810 }
811
812 return false;
813}
814
John Kessenich0d2b6de2016-06-05 11:23:11 -0600815// Accept an expression with parenthesis around it, where
816// the parenthesis ARE NOT expression parenthesis, but the
817// syntactically required ones like in "if ( expression )"
818//
819// Note this one is not set up to be speculative; as it gives
820// errors if not found.
821//
822bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
823{
824 // LEFT_PAREN
825 if (! acceptTokenClass(EHTokLeftParen))
826 expected("(");
827
828 if (! acceptExpression(expression)) {
829 expected("expression");
830 return false;
831 }
832
833 // RIGHT_PAREN
834 if (! acceptTokenClass(EHTokRightParen))
835 expected(")");
836
837 return true;
838}
839
John Kessenich34fb0362016-05-03 23:17:20 -0600840// The top-level full expression recognizer.
841//
John Kessenich87142c72016-03-12 20:24:24 -0700842// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600843// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700844//
845bool HlslGrammar::acceptExpression(TIntermTyped*& node)
846{
LoopDawgef764a22016-06-03 09:17:51 -0600847 node = nullptr;
848
John Kessenich34fb0362016-05-03 23:17:20 -0600849 // assignment_expression
850 if (! acceptAssignmentExpression(node))
851 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600852
John Kessenich34fb0362016-05-03 23:17:20 -0600853 if (! peekTokenClass(EHTokComma))
854 return true;
855
856 do {
857 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600858 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600859 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600860
John Kessenich34fb0362016-05-03 23:17:20 -0600861 // ... assignment_expression
862 TIntermTyped* rightNode = nullptr;
863 if (! acceptAssignmentExpression(rightNode)) {
864 expected("assignment expression");
865 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600866 }
867
John Kessenich34fb0362016-05-03 23:17:20 -0600868 node = intermediate.addComma(node, rightNode, loc);
869
870 if (! peekTokenClass(EHTokComma))
871 return true;
872 } while (true);
873}
874
875// Accept an assignment expression, where assignment operations
876// associate right-to-left. This is, it is implicit, for example
877//
878// a op (b op (c op d))
879//
880// assigment_expression
881// : binary_expression op binary_expression op binary_expression ...
882//
883bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
884{
885 if (! acceptBinaryExpression(node, PlLogicalOr))
886 return false;
887
888 TOperator assignOp = HlslOpMap::assignment(peek());
889 if (assignOp == EOpNull)
890 return true;
891
892 // ... op
893 TSourceLoc loc = token.loc;
894 advanceToken();
895
896 // ... binary_expression
897 // But, done by recursing this function, which automatically
898 // gets the right-to-left associativity.
899 TIntermTyped* rightNode = nullptr;
900 if (! acceptAssignmentExpression(rightNode)) {
901 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600902 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700903 }
904
John Kessenich34fb0362016-05-03 23:17:20 -0600905 node = intermediate.addAssign(assignOp, node, rightNode, loc);
906
907 if (! peekTokenClass(EHTokComma))
908 return true;
909
910 return true;
911}
912
913// Accept a binary expression, for binary operations that
914// associate left-to-right. This is, it is implicit, for example
915//
916// ((a op b) op c) op d
917//
918// binary_expression
919// : expression op expression op expression ...
920//
921// where 'expression' is the next higher level in precedence.
922//
923bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
924{
925 if (precedenceLevel > PlMul)
926 return acceptUnaryExpression(node);
927
928 // assignment_expression
929 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
930 return false;
931
932 TOperator op = HlslOpMap::binary(peek());
933 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
934 if (tokenLevel < precedenceLevel)
935 return true;
936
937 do {
938 // ... op
939 TSourceLoc loc = token.loc;
940 advanceToken();
941
942 // ... expression
943 TIntermTyped* rightNode = nullptr;
944 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
945 expected("expression");
946 return false;
947 }
948
949 node = intermediate.addBinaryMath(op, node, rightNode, loc);
950
951 if (! peekTokenClass(EHTokComma))
952 return true;
953 } while (true);
954}
955
956// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -0600957// : (type) unary_expression
958// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -0600959// | - unary_expression
960// | ! unary_expression
961// | ~ unary_expression
962// | ++ unary_expression
963// | -- unary_expression
964// | postfix_expression
965//
966bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
967{
John Kessenich1cc1a282016-06-03 16:55:49 -0600968 // (type) unary_expression
969 // Have to look two steps ahead, because this could be, e.g., a
970 // postfix_expression instead, since that also starts with at "(".
971 if (acceptTokenClass(EHTokLeftParen)) {
972 TType castType;
973 if (acceptType(castType)) {
974 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600975 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -0600976 return false;
977 }
978
979 // We've matched "(type)" now, get the expression to cast
980 TSourceLoc loc = token.loc;
981 if (! acceptUnaryExpression(node))
982 return false;
983
984 // Hook it up like a constructor
985 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
986 if (constructorFunction == nullptr) {
987 expected("type that can be constructed");
988 return false;
989 }
990 TIntermTyped* arguments = nullptr;
991 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
992 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
993
994 return true;
995 } else {
996 // This isn't a type cast, but it still started "(", so if it is a
997 // unary expression, it can only be a postfix_expression, so try that.
998 // Back it up first.
999 recedeToken();
1000 return acceptPostfixExpression(node);
1001 }
1002 }
1003
1004 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -06001005 TOperator unaryOp = HlslOpMap::preUnary(peek());
1006
John Kessenich1cc1a282016-06-03 16:55:49 -06001007 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -06001008 if (unaryOp == EOpNull)
1009 return acceptPostfixExpression(node);
1010
1011 // op unary_expression
1012 TSourceLoc loc = token.loc;
1013 advanceToken();
1014 if (! acceptUnaryExpression(node))
1015 return false;
1016
1017 // + is a no-op
1018 if (unaryOp == EOpAdd)
1019 return true;
1020
1021 node = intermediate.addUnaryMath(unaryOp, node, loc);
1022
1023 return node != nullptr;
1024}
1025
1026// postfix_expression
1027// : LEFT_PAREN expression RIGHT_PAREN
1028// | literal
1029// | constructor
1030// | identifier
1031// | function_call
1032// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
1033// | postfix_expression DOT IDENTIFIER
1034// | postfix_expression INC_OP
1035// | postfix_expression DEC_OP
1036//
1037bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
1038{
1039 // Not implemented as self-recursive:
1040 // The logical "right recursion" is done with an loop at the end
1041
1042 // idToken will pick up either a variable or a function name in a function call
1043 HlslToken idToken;
1044
John Kessenich21472ae2016-06-04 11:46:33 -06001045 // Find something before the postfix operations, as they can't operate
1046 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -07001047 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -06001048 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001049 if (! acceptExpression(node)) {
1050 expected("expression");
1051 return false;
1052 }
1053 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001054 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001055 return false;
1056 }
John Kessenich34fb0362016-05-03 23:17:20 -06001057 } else if (acceptLiteral(node)) {
1058 // literal (nothing else to do yet), go on to the
1059 } else if (acceptConstructor(node)) {
1060 // constructor (nothing else to do yet)
1061 } else if (acceptIdentifier(idToken)) {
1062 // identifier or function_call name
1063 if (! peekTokenClass(EHTokLeftParen)) {
John Kesseniche6e74942016-06-11 16:43:14 -06001064 node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -06001065 } else if (acceptFunctionCall(idToken, node)) {
1066 // function_call (nothing else to do yet)
1067 } else {
1068 expected("function call arguments");
1069 return false;
1070 }
John Kessenich21472ae2016-06-04 11:46:33 -06001071 } else {
1072 // nothing found, can't post operate
1073 return false;
John Kessenich87142c72016-03-12 20:24:24 -07001074 }
1075
John Kessenich21472ae2016-06-04 11:46:33 -06001076 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -06001077 do {
1078 TSourceLoc loc = token.loc;
1079 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -07001080
John Kessenich34fb0362016-05-03 23:17:20 -06001081 // Consume only a valid post-unary operator, otherwise we are done.
1082 switch (postOp) {
1083 case EOpIndexDirectStruct:
1084 case EOpIndexIndirect:
1085 case EOpPostIncrement:
1086 case EOpPostDecrement:
1087 advanceToken();
1088 break;
1089 default:
1090 return true;
1091 }
John Kessenich87142c72016-03-12 20:24:24 -07001092
John Kessenich34fb0362016-05-03 23:17:20 -06001093 // We have a valid post-unary operator, process it.
1094 switch (postOp) {
1095 case EOpIndexDirectStruct:
1096 // todo
1097 break;
1098 case EOpIndexIndirect:
1099 {
1100 TIntermTyped* indexNode = nullptr;
1101 if (! acceptExpression(indexNode) ||
1102 ! peekTokenClass(EHTokRightBracket)) {
1103 expected("expression followed by ']'");
1104 return false;
1105 }
1106 // todo: node = intermediate.addBinaryMath(
1107 }
1108 case EOpPostIncrement:
1109 case EOpPostDecrement:
1110 node = intermediate.addUnaryMath(postOp, node, loc);
1111 break;
1112 default:
1113 assert(0);
1114 break;
1115 }
1116 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -07001117}
1118
John Kessenichd016be12016-03-13 11:24:20 -06001119// constructor
John Kessenich078d7f22016-03-14 10:02:11 -06001120// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -06001121//
1122bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
1123{
1124 // type
1125 TType type;
1126 if (acceptType(type)) {
1127 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
1128 if (constructorFunction == nullptr)
1129 return false;
1130
1131 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -06001132 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -06001133 if (! acceptArguments(constructorFunction, arguments)) {
1134 expected("constructor arguments");
1135 return false;
1136 }
1137
1138 // hook it up
1139 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
1140
1141 return true;
1142 }
1143
1144 return false;
1145}
1146
John Kessenich34fb0362016-05-03 23:17:20 -06001147// The function_call identifier was already recognized, and passed in as idToken.
1148//
1149// function_call
1150// : [idToken] arguments
1151//
John Kessenich4678ca92016-05-13 09:33:42 -06001152bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -06001153{
John Kessenich4678ca92016-05-13 09:33:42 -06001154 // arguments
1155 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
1156 TIntermTyped* arguments = nullptr;
1157 if (! acceptArguments(function, arguments))
1158 return false;
1159
1160 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
1161
1162 return true;
John Kessenich34fb0362016-05-03 23:17:20 -06001163}
1164
John Kessenich87142c72016-03-12 20:24:24 -07001165// arguments
John Kessenich078d7f22016-03-14 10:02:11 -06001166// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001167//
John Kessenichd016be12016-03-13 11:24:20 -06001168// The arguments are pushed onto the 'function' argument list and
1169// onto the 'arguments' aggregate.
1170//
John Kessenich4678ca92016-05-13 09:33:42 -06001171bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -07001172{
John Kessenich078d7f22016-03-14 10:02:11 -06001173 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001174 if (! acceptTokenClass(EHTokLeftParen))
1175 return false;
1176
1177 do {
John Kessenichd016be12016-03-13 11:24:20 -06001178 // expression
John Kessenich87142c72016-03-12 20:24:24 -07001179 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -06001180 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -07001181 break;
John Kessenichd016be12016-03-13 11:24:20 -06001182
1183 // hook it up
1184 parseContext.handleFunctionArgument(function, arguments, arg);
1185
John Kessenich078d7f22016-03-14 10:02:11 -06001186 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001187 if (! acceptTokenClass(EHTokComma))
1188 break;
1189 } while (true);
1190
John Kessenich078d7f22016-03-14 10:02:11 -06001191 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001192 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001193 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001194 return false;
1195 }
1196
1197 return true;
1198}
1199
1200bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1201{
1202 switch (token.tokenClass) {
1203 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001204 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001205 break;
1206 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001207 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001208 break;
1209 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001210 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001211 break;
1212 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001213 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001214 break;
1215
1216 default:
1217 return false;
1218 }
1219
1220 advanceToken();
1221
1222 return true;
1223}
1224
John Kessenich5f934b02016-03-13 17:58:25 -06001225// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001226// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001227//
John Kessenich21472ae2016-06-04 11:46:33 -06001228bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001229{
John Kessenich21472ae2016-06-04 11:46:33 -06001230 TIntermAggregate* compoundStatement = nullptr;
1231
John Kessenich34fb0362016-05-03 23:17:20 -06001232 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001233 if (! acceptTokenClass(EHTokLeftBrace))
1234 return false;
1235
1236 // statement statement ...
1237 TIntermNode* statement = nullptr;
1238 while (acceptStatement(statement)) {
1239 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001240 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001241 }
John Kessenich34fb0362016-05-03 23:17:20 -06001242 if (compoundStatement)
1243 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001244
John Kessenich21472ae2016-06-04 11:46:33 -06001245 retStatement = compoundStatement;
1246
John Kessenich34fb0362016-05-03 23:17:20 -06001247 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001248 return acceptTokenClass(EHTokRightBrace);
1249}
1250
John Kessenich0d2b6de2016-06-05 11:23:11 -06001251bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1252{
1253 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001254 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001255 parseContext.popScope();
1256
1257 return result;
1258}
1259
John Kessenich077e0522016-06-09 02:02:17 -06001260bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001261{
John Kessenich077e0522016-06-09 02:02:17 -06001262 parseContext.pushScope();
1263 bool result = acceptCompoundStatement(statement);
1264 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001265
1266 return result;
1267}
1268
John Kessenich5f934b02016-03-13 17:58:25 -06001269// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001270// : attributes attributed_statement
1271//
1272// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001273// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001274// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001275// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001276// | declaration_statement
1277// | selection_statement
1278// | switch_statement
1279// | case_label
1280// | iteration_statement
1281// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001282//
1283bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1284{
John Kessenich21472ae2016-06-04 11:46:33 -06001285 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001286
John Kessenich21472ae2016-06-04 11:46:33 -06001287 // attributes
1288 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001289
John Kessenich21472ae2016-06-04 11:46:33 -06001290 // attributed_statement
1291 switch (peek()) {
1292 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001293 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001294
John Kessenich21472ae2016-06-04 11:46:33 -06001295 case EHTokIf:
1296 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001297
John Kessenich21472ae2016-06-04 11:46:33 -06001298 case EHTokSwitch:
1299 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001300
John Kessenich21472ae2016-06-04 11:46:33 -06001301 case EHTokFor:
1302 case EHTokDo:
1303 case EHTokWhile:
1304 return acceptIterationStatement(statement);
1305
1306 case EHTokContinue:
1307 case EHTokBreak:
1308 case EHTokDiscard:
1309 case EHTokReturn:
1310 return acceptJumpStatement(statement);
1311
1312 case EHTokCase:
1313 return acceptCaseLabel(statement);
1314
1315 case EHTokSemicolon:
1316 return acceptTokenClass(EHTokSemicolon);
1317
1318 case EHTokRightBrace:
1319 // Performance: not strictly necessary, but stops a bunch of hunting early,
1320 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001321 return false;
1322
John Kessenich21472ae2016-06-04 11:46:33 -06001323 default:
1324 {
1325 // declaration
1326 if (acceptDeclaration(statement))
1327 return true;
1328
1329 // expression
1330 TIntermTyped* node;
1331 if (acceptExpression(node))
1332 statement = node;
1333 else
1334 return false;
1335
1336 // SEMICOLON (following an expression)
1337 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001338 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001339 return false;
1340 }
1341 }
1342 }
1343
John Kessenich5f934b02016-03-13 17:58:25 -06001344 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001345}
1346
John Kessenich21472ae2016-06-04 11:46:33 -06001347// attributes
1348// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1349//
1350// attribute:
1351// : UNROLL
1352// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1353// | FASTOPT
1354// | ALLOW_UAV_CONDITION
1355// | BRANCH
1356// | FLATTEN
1357// | FORCECASE
1358// | CALL
1359//
1360void HlslGrammar::acceptAttributes()
1361{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001362 // For now, accept the [ XXX(X) ] syntax, but drop.
1363 // TODO: subset to correct set? Pass on?
1364 do {
1365 // LEFT_BRACKET?
1366 if (! acceptTokenClass(EHTokLeftBracket))
1367 return;
1368
1369 // attribute
1370 if (peekTokenClass(EHTokIdentifier)) {
1371 // 'token.string' is the attribute
1372 advanceToken();
1373 } else if (! peekTokenClass(EHTokRightBracket)) {
1374 expected("identifier");
1375 advanceToken();
1376 }
1377
1378 // (x)
1379 if (acceptTokenClass(EHTokLeftParen)) {
1380 TIntermTyped* node;
1381 if (! acceptLiteral(node))
1382 expected("literal");
1383 // 'node' has the literal in it
1384 if (! acceptTokenClass(EHTokRightParen))
1385 expected(")");
1386 }
1387
1388 // RIGHT_BRACKET
1389 if (acceptTokenClass(EHTokRightBracket))
1390 continue;
1391
1392 expected("]");
1393 return;
1394
1395 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001396}
1397
John Kessenich0d2b6de2016-06-05 11:23:11 -06001398// selection_statement
1399// : IF LEFT_PAREN expression RIGHT_PAREN statement
1400// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1401//
John Kessenich21472ae2016-06-04 11:46:33 -06001402bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1403{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001404 TSourceLoc loc = token.loc;
1405
1406 // IF
1407 if (! acceptTokenClass(EHTokIf))
1408 return false;
1409
1410 // so that something declared in the condition is scoped to the lifetimes
1411 // of the then-else statements
1412 parseContext.pushScope();
1413
1414 // LEFT_PAREN expression RIGHT_PAREN
1415 TIntermTyped* condition;
1416 if (! acceptParenExpression(condition))
1417 return false;
1418
1419 // create the child statements
1420 TIntermNodePair thenElse = { nullptr, nullptr };
1421
1422 // then statement
1423 if (! acceptScopedStatement(thenElse.node1)) {
1424 expected("then statement");
1425 return false;
1426 }
1427
1428 // ELSE
1429 if (acceptTokenClass(EHTokElse)) {
1430 // else statement
1431 if (! acceptScopedStatement(thenElse.node2)) {
1432 expected("else statement");
1433 return false;
1434 }
1435 }
1436
1437 // Put the pieces together
1438 statement = intermediate.addSelection(condition, thenElse, loc);
1439 parseContext.popScope();
1440
1441 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001442}
1443
1444bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1445{
1446 return false;
1447}
1448
John Kessenich119f8f62016-06-05 15:44:07 -06001449// iteration_statement
1450// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1451// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1452// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1453//
1454// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001455bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1456{
John Kessenich119f8f62016-06-05 15:44:07 -06001457 TSourceLoc loc = token.loc;
1458 TIntermTyped* condition = nullptr;
1459
1460 EHlslTokenClass loop = peek();
1461 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1462
1463 // WHILE or DO or FOR
1464 advanceToken();
1465
1466 switch (loop) {
1467 case EHTokWhile:
1468 // so that something declared in the condition is scoped to the lifetime
1469 // of the while sub-statement
1470 parseContext.pushScope();
1471 parseContext.nestLooping();
1472
1473 // LEFT_PAREN condition RIGHT_PAREN
1474 if (! acceptParenExpression(condition))
1475 return false;
1476
1477 // statement
1478 if (! acceptScopedStatement(statement)) {
1479 expected("while sub-statement");
1480 return false;
1481 }
1482
1483 parseContext.unnestLooping();
1484 parseContext.popScope();
1485
1486 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1487
1488 return true;
1489
1490 case EHTokDo:
1491 parseContext.nestLooping();
1492
1493 if (! acceptTokenClass(EHTokLeftBrace))
1494 expected("{");
1495
1496 // statement
1497 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1498 expected("do sub-statement");
1499 return false;
1500 }
1501
1502 if (! acceptTokenClass(EHTokRightBrace))
1503 expected("}");
1504
1505 // WHILE
1506 if (! acceptTokenClass(EHTokWhile)) {
1507 expected("while");
1508 return false;
1509 }
1510
1511 // LEFT_PAREN condition RIGHT_PAREN
1512 TIntermTyped* condition;
1513 if (! acceptParenExpression(condition))
1514 return false;
1515
1516 if (! acceptTokenClass(EHTokSemicolon))
1517 expected(";");
1518
1519 parseContext.unnestLooping();
1520
1521 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1522
1523 return true;
1524
1525 case EHTokFor:
1526 {
1527 // LEFT_PAREN
1528 if (! acceptTokenClass(EHTokLeftParen))
1529 expected("(");
1530
1531 // so that something declared in the condition is scoped to the lifetime
1532 // of the for sub-statement
1533 parseContext.pushScope();
1534
1535 // initializer SEMI_COLON
1536 TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
1537 acceptExpression(initializer);
1538 if (! acceptTokenClass(EHTokSemicolon))
1539 expected(";");
1540
1541 parseContext.nestLooping();
1542
1543 // condition SEMI_COLON
1544 acceptExpression(condition);
1545 if (! acceptTokenClass(EHTokSemicolon))
1546 expected(";");
1547
1548 // iterator SEMI_COLON
1549 TIntermTyped* iterator = nullptr;
1550 acceptExpression(iterator);
1551 if (! acceptTokenClass(EHTokRightParen))
1552 expected(")");
1553
1554 // statement
1555 if (! acceptScopedStatement(statement)) {
1556 expected("for sub-statement");
1557 return false;
1558 }
1559
1560 statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
1561
1562 parseContext.popScope();
1563 parseContext.unnestLooping();
1564
1565 return true;
1566 }
1567
1568 default:
1569 return false;
1570 }
John Kessenich21472ae2016-06-04 11:46:33 -06001571}
1572
1573// jump_statement
1574// : CONTINUE SEMICOLON
1575// | BREAK SEMICOLON
1576// | DISCARD SEMICOLON
1577// | RETURN SEMICOLON
1578// | RETURN expression SEMICOLON
1579//
1580bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1581{
1582 switch (peek()) {
1583 case EHTokContinue:
1584 case EHTokBreak:
1585 case EHTokDiscard:
1586 // TODO
1587 return false;
1588
1589 case EHTokReturn:
1590 // return
1591 if (acceptTokenClass(EHTokReturn)) {
1592 // expression
1593 TIntermTyped* node;
1594 if (acceptExpression(node)) {
1595 // hook it up
1596 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1597 } else
1598 statement = intermediate.addBranch(EOpReturn, token.loc);
1599
1600 // SEMICOLON
1601 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001602 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001603 return false;
1604 }
1605
1606 return true;
1607 }
1608
1609 default:
1610 return false;
1611 }
1612}
1613
1614
1615bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1616{
1617 return false;
1618}
1619
John Kessenich630dd7d2016-06-12 23:52:12 -06001620// post_decls
1621// : COLON semantic // optional
1622// COLON PACKOFFSET LEFT_PAREN ... RIGHT_PAREN // optional
1623// COLON REGISTER // optional
1624// annotations // optional
1625//
1626void HlslGrammar::acceptPostDecls(TType& type)
John Kessenich078d7f22016-03-14 10:02:11 -06001627{
John Kessenich630dd7d2016-06-12 23:52:12 -06001628 do {
1629 // COLON
1630 if (acceptTokenClass(EHTokColon)) {
1631 HlslToken idToken;
1632 if (acceptTokenClass(EHTokPackOffset)) {
1633 if (! acceptTokenClass(EHTokLeftParen)) {
1634 expected("(");
1635 return;
1636 }
1637 acceptTokenClass(EHTokIdentifier);
1638 acceptTokenClass(EHTokDot);
1639 acceptTokenClass(EHTokIdentifier);
1640 if (! acceptTokenClass(EHTokRightParen)) {
1641 expected(")");
1642 break;
1643 }
1644 // TODO: process the packoffset information
1645 } else if (! acceptIdentifier(idToken)) {
1646 expected("semantic or packoffset or register");
1647 return;
1648 } else if (*idToken.string == "register") {
1649 if (! acceptTokenClass(EHTokLeftParen)) {
1650 expected("(");
1651 return;
1652 }
1653 acceptTokenClass(EHTokIdentifier);
1654 acceptTokenClass(EHTokComma);
1655 acceptTokenClass(EHTokIdentifier);
1656 acceptTokenClass(EHTokLeftBracket);
1657 if (peekTokenClass(EHTokIntConstant))
1658 advanceToken();
1659 acceptTokenClass(EHTokRightBracket);
1660 if (! acceptTokenClass(EHTokRightParen)) {
1661 expected(")");
1662 break;
1663 }
1664 // TODO: process the register information
1665 } else {
1666 // semantic, in idToken.string
1667 parseContext.handleSemantic(type, *idToken.string);
1668 }
1669 } else if (acceptTokenClass(EHTokLeftAngle)) {
1670 // TODO: process annotations, just accepting them for now
1671 do {
1672 if (peekTokenClass(EHTokNone))
1673 return;
1674 if (acceptTokenClass(EHTokRightAngle))
1675 break;
1676 advanceToken();
1677 } while (true);
1678 } else
1679 break;
John Kessenich078d7f22016-03-14 10:02:11 -06001680
John Kessenich630dd7d2016-06-12 23:52:12 -06001681 } while (true);
John Kessenich078d7f22016-03-14 10:02:11 -06001682}
1683
John Kesseniche01a9bc2016-03-12 20:11:22 -07001684} // end namespace glslang