blob: 9ea14daed3afd5c8941ba47faa34cf8632dc5b83 [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
110// | fully_specified_type identifier SEMICOLON
111// | fully_specified_type identifier = expression SEMICOLON
112// | fully_specified_type identifier function_parameters SEMICOLON // function prototype
113// | fully_specified_type identifier function_parameters COLON semantic 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 Kessenich87142c72016-03-12 20:24:24 -0700130 // = expression
131 TIntermTyped* expressionNode = nullptr;
John Kessenich34fb0362016-05-03 23:17:20 -0600132 if (acceptTokenClass(EHTokAssign)) {
John Kessenich87142c72016-03-12 20:24:24 -0700133 if (! acceptExpression(expressionNode)) {
134 expected("initializer");
135 return false;
136 }
137 }
138
John Kessenich078d7f22016-03-14 10:02:11 -0600139 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700140 if (acceptTokenClass(EHTokSemicolon)) {
John Kessenichaecd4972016-03-14 10:46:34 -0600141 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
John Kessenich87142c72016-03-12 20:24:24 -0700142 return true;
143 }
John Kessenich5f934b02016-03-13 17:58:25 -0600144
145 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600146 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600147 if (acceptFunctionParameters(*function)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600148 // COLON semantic
149 acceptSemantic();
150
John Kessenich5f934b02016-03-13 17:58:25 -0600151 // compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600152 if (peekTokenClass(EHTokLeftBrace))
John Kessenich5f934b02016-03-13 17:58:25 -0600153 return acceptFunctionDefinition(*function, node);
154
John Kessenich078d7f22016-03-14 10:02:11 -0600155 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600156 if (acceptTokenClass(EHTokSemicolon))
157 return true;
158
159 return false;
160 }
John Kessenich87142c72016-03-12 20:24:24 -0700161 }
162
John Kessenich078d7f22016-03-14 10:02:11 -0600163 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700164 if (acceptTokenClass(EHTokSemicolon))
165 return true;
166
John Kesseniche01a9bc2016-03-12 20:11:22 -0700167 return true;
168}
169
John Kessenich87142c72016-03-12 20:24:24 -0700170// fully_specified_type
171// : type_specifier
172// | type_qualifier type_specifier
173//
174bool HlslGrammar::acceptFullySpecifiedType(TType& type)
175{
176 // type_qualifier
177 TQualifier qualifier;
178 qualifier.clear();
179 acceptQualifier(qualifier);
180
181 // type_specifier
182 if (! acceptType(type))
183 return false;
184 type.getQualifier() = qualifier;
185
186 return true;
187}
188
189// If token is a qualifier, return its token class and advance to the next
190// qualifier. Otherwise, return false, and don't advance.
191void HlslGrammar::acceptQualifier(TQualifier& qualifier)
192{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600193 switch (peek()) {
John Kessenich87142c72016-03-12 20:24:24 -0700194 case EHTokUniform:
195 qualifier.storage = EvqUniform;
196 break;
197 case EHTokConst:
198 qualifier.storage = EvqConst;
199 break;
200 default:
201 return;
202 }
203
204 advanceToken();
205}
206
207// If token is for a type, update 'type' with the type information,
208// and return true and advance.
209// Otherwise, return false, and don't advance
210bool HlslGrammar::acceptType(TType& type)
211{
John Kessenich9c86c6a2016-05-03 22:49:24 -0600212 switch (peek()) {
John Kessenich71351de2016-06-08 12:50:56 -0600213 case EHTokVoid:
214 new(&type) TType(EbtVoid);
John Kessenich87142c72016-03-12 20:24:24 -0700215 break;
John Kessenich71351de2016-06-08 12:50:56 -0600216
John Kessenich87142c72016-03-12 20:24:24 -0700217 case EHTokFloat:
John Kessenich8d72f1a2016-05-20 12:06:03 -0600218 new(&type) TType(EbtFloat);
219 break;
John Kessenich87142c72016-03-12 20:24:24 -0700220 case EHTokFloat1:
221 new(&type) TType(EbtFloat);
John Kessenich8d72f1a2016-05-20 12:06:03 -0600222 type.makeVector();
John Kessenich87142c72016-03-12 20:24:24 -0700223 break;
John Kessenich87142c72016-03-12 20:24:24 -0700224 case EHTokFloat2:
225 new(&type) TType(EbtFloat, EvqTemporary, 2);
226 break;
227 case EHTokFloat3:
228 new(&type) TType(EbtFloat, EvqTemporary, 3);
229 break;
230 case EHTokFloat4:
231 new(&type) TType(EbtFloat, EvqTemporary, 4);
232 break;
233
John Kessenich71351de2016-06-08 12:50:56 -0600234 case EHTokDouble:
235 new(&type) TType(EbtDouble);
236 break;
237 case EHTokDouble1:
238 new(&type) TType(EbtDouble);
239 type.makeVector();
240 break;
241 case EHTokDouble2:
242 new(&type) TType(EbtDouble, EvqTemporary, 2);
243 break;
244 case EHTokDouble3:
245 new(&type) TType(EbtDouble, EvqTemporary, 3);
246 break;
247 case EHTokDouble4:
248 new(&type) TType(EbtDouble, EvqTemporary, 4);
249 break;
250
251 case EHTokInt:
252 case EHTokDword:
253 new(&type) TType(EbtInt);
254 break;
255 case EHTokInt1:
256 new(&type) TType(EbtInt);
257 type.makeVector();
258 break;
John Kessenich87142c72016-03-12 20:24:24 -0700259 case EHTokInt2:
260 new(&type) TType(EbtInt, EvqTemporary, 2);
261 break;
262 case EHTokInt3:
263 new(&type) TType(EbtInt, EvqTemporary, 3);
264 break;
265 case EHTokInt4:
266 new(&type) TType(EbtInt, EvqTemporary, 4);
267 break;
268
John Kessenich71351de2016-06-08 12:50:56 -0600269 case EHTokUint:
270 new(&type) TType(EbtUint);
271 break;
272 case EHTokUint1:
273 new(&type) TType(EbtUint);
274 type.makeVector();
275 break;
276 case EHTokUint2:
277 new(&type) TType(EbtUint, EvqTemporary, 2);
278 break;
279 case EHTokUint3:
280 new(&type) TType(EbtUint, EvqTemporary, 3);
281 break;
282 case EHTokUint4:
283 new(&type) TType(EbtUint, EvqTemporary, 4);
284 break;
285
286 case EHTokBool:
287 new(&type) TType(EbtBool);
288 break;
289 case EHTokBool1:
290 new(&type) TType(EbtBool);
291 type.makeVector();
292 break;
John Kessenich87142c72016-03-12 20:24:24 -0700293 case EHTokBool2:
294 new(&type) TType(EbtBool, EvqTemporary, 2);
295 break;
296 case EHTokBool3:
297 new(&type) TType(EbtBool, EvqTemporary, 3);
298 break;
299 case EHTokBool4:
300 new(&type) TType(EbtBool, EvqTemporary, 4);
301 break;
302
John Kessenich0133c122016-05-20 12:17:26 -0600303 case EHTokInt1x1:
304 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
305 break;
306 case EHTokInt1x2:
307 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
308 break;
309 case EHTokInt1x3:
310 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
311 break;
312 case EHTokInt1x4:
313 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
314 break;
315 case EHTokInt2x1:
316 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
317 break;
318 case EHTokInt2x2:
319 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
320 break;
321 case EHTokInt2x3:
322 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
323 break;
324 case EHTokInt2x4:
325 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
326 break;
327 case EHTokInt3x1:
328 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
329 break;
330 case EHTokInt3x2:
331 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
332 break;
333 case EHTokInt3x3:
334 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
335 break;
336 case EHTokInt3x4:
337 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
338 break;
339 case EHTokInt4x1:
340 new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
341 break;
342 case EHTokInt4x2:
343 new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
344 break;
345 case EHTokInt4x3:
346 new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
347 break;
348 case EHTokInt4x4:
349 new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
350 break;
351
John Kessenich71351de2016-06-08 12:50:56 -0600352 case EHTokUint1x1:
353 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
354 break;
355 case EHTokUint1x2:
356 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
357 break;
358 case EHTokUint1x3:
359 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
360 break;
361 case EHTokUint1x4:
362 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
363 break;
364 case EHTokUint2x1:
365 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
366 break;
367 case EHTokUint2x2:
368 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
369 break;
370 case EHTokUint2x3:
371 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
372 break;
373 case EHTokUint2x4:
374 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
375 break;
376 case EHTokUint3x1:
377 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
378 break;
379 case EHTokUint3x2:
380 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
381 break;
382 case EHTokUint3x3:
383 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
384 break;
385 case EHTokUint3x4:
386 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
387 break;
388 case EHTokUint4x1:
389 new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
390 break;
391 case EHTokUint4x2:
392 new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
393 break;
394 case EHTokUint4x3:
395 new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
396 break;
397 case EHTokUint4x4:
398 new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
399 break;
400
401 case EHTokBool1x1:
402 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
403 break;
404 case EHTokBool1x2:
405 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
406 break;
407 case EHTokBool1x3:
408 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
409 break;
410 case EHTokBool1x4:
411 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
412 break;
413 case EHTokBool2x1:
414 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
415 break;
416 case EHTokBool2x2:
417 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
418 break;
419 case EHTokBool2x3:
420 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
421 break;
422 case EHTokBool2x4:
423 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
424 break;
425 case EHTokBool3x1:
426 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
427 break;
428 case EHTokBool3x2:
429 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
430 break;
431 case EHTokBool3x3:
432 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
433 break;
434 case EHTokBool3x4:
435 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
436 break;
437 case EHTokBool4x1:
438 new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
439 break;
440 case EHTokBool4x2:
441 new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
442 break;
443 case EHTokBool4x3:
444 new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
445 break;
446 case EHTokBool4x4:
447 new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
448 break;
449
John Kessenich0133c122016-05-20 12:17:26 -0600450 case EHTokFloat1x1:
451 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
452 break;
453 case EHTokFloat1x2:
454 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
455 break;
456 case EHTokFloat1x3:
457 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
458 break;
459 case EHTokFloat1x4:
460 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
461 break;
462 case EHTokFloat2x1:
463 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
464 break;
John Kessenich87142c72016-03-12 20:24:24 -0700465 case EHTokFloat2x2:
466 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
467 break;
468 case EHTokFloat2x3:
469 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
470 break;
471 case EHTokFloat2x4:
472 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
473 break;
John Kessenich0133c122016-05-20 12:17:26 -0600474 case EHTokFloat3x1:
475 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
476 break;
John Kessenich87142c72016-03-12 20:24:24 -0700477 case EHTokFloat3x2:
478 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
479 break;
480 case EHTokFloat3x3:
481 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
482 break;
483 case EHTokFloat3x4:
484 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
485 break;
John Kessenich0133c122016-05-20 12:17:26 -0600486 case EHTokFloat4x1:
487 new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
488 break;
John Kessenich87142c72016-03-12 20:24:24 -0700489 case EHTokFloat4x2:
490 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
491 break;
492 case EHTokFloat4x3:
493 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
494 break;
495 case EHTokFloat4x4:
496 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
497 break;
498
John Kessenich0133c122016-05-20 12:17:26 -0600499 case EHTokDouble1x1:
500 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
501 break;
502 case EHTokDouble1x2:
503 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
504 break;
505 case EHTokDouble1x3:
506 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
507 break;
508 case EHTokDouble1x4:
509 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
510 break;
511 case EHTokDouble2x1:
512 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
513 break;
514 case EHTokDouble2x2:
515 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
516 break;
517 case EHTokDouble2x3:
518 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
519 break;
520 case EHTokDouble2x4:
521 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
522 break;
523 case EHTokDouble3x1:
524 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
525 break;
526 case EHTokDouble3x2:
527 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
528 break;
529 case EHTokDouble3x3:
530 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
531 break;
532 case EHTokDouble3x4:
533 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
534 break;
535 case EHTokDouble4x1:
536 new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
537 break;
538 case EHTokDouble4x2:
539 new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
540 break;
541 case EHTokDouble4x3:
542 new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
543 break;
544 case EHTokDouble4x4:
545 new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
546 break;
547
John Kessenich87142c72016-03-12 20:24:24 -0700548 default:
549 return false;
550 }
551
552 advanceToken();
553
554 return true;
555}
556
John Kessenich5f934b02016-03-13 17:58:25 -0600557// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600558// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich71351de2016-06-08 12:50:56 -0600559// | LEFT_PAREN VOID RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600560//
561bool HlslGrammar::acceptFunctionParameters(TFunction& function)
562{
John Kessenich078d7f22016-03-14 10:02:11 -0600563 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600564 if (! acceptTokenClass(EHTokLeftParen))
565 return false;
566
John Kessenich71351de2016-06-08 12:50:56 -0600567 // VOID RIGHT_PAREN
568 if (! acceptTokenClass(EHTokVoid)) {
569 do {
570 // parameter_declaration
571 if (! acceptParameterDeclaration(function))
572 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600573
John Kessenich71351de2016-06-08 12:50:56 -0600574 // COMMA
575 if (! acceptTokenClass(EHTokComma))
576 break;
577 } while (true);
578 }
John Kessenich5f934b02016-03-13 17:58:25 -0600579
John Kessenich078d7f22016-03-14 10:02:11 -0600580 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600581 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600582 expected(")");
John Kessenich5f934b02016-03-13 17:58:25 -0600583 return false;
584 }
585
586 return true;
587}
588
589// parameter_declaration
590// : fully_specified_type
591// | fully_specified_type identifier
592//
593bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
594{
595 // fully_specified_type
596 TType* type = new TType;
597 if (! acceptFullySpecifiedType(*type))
598 return false;
599
600 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600601 HlslToken idToken;
602 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600603
John Kessenichaecd4972016-03-14 10:46:34 -0600604 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600605 function.addParameter(param);
606
607 return true;
608}
609
610// Do the work to create the function definition in addition to
611// parsing the body (compound_statement).
612bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
613{
614 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
615
John Kessenich077e0522016-06-09 02:02:17 -0600616 // This does a pushScope()
John Kessenich5f934b02016-03-13 17:58:25 -0600617 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
618
619 // compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -0600620 TIntermNode* functionBody = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -0600621 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600622 node = intermediate.growAggregate(node, functionBody);
623 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600624 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
John Kessenich077e0522016-06-09 02:02:17 -0600625 parseContext.popScope();
John Kessenich5f934b02016-03-13 17:58:25 -0600626
627 return true;
628 }
629
630 return false;
631}
632
John Kessenich0d2b6de2016-06-05 11:23:11 -0600633// Accept an expression with parenthesis around it, where
634// the parenthesis ARE NOT expression parenthesis, but the
635// syntactically required ones like in "if ( expression )"
636//
637// Note this one is not set up to be speculative; as it gives
638// errors if not found.
639//
640bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
641{
642 // LEFT_PAREN
643 if (! acceptTokenClass(EHTokLeftParen))
644 expected("(");
645
646 if (! acceptExpression(expression)) {
647 expected("expression");
648 return false;
649 }
650
651 // RIGHT_PAREN
652 if (! acceptTokenClass(EHTokRightParen))
653 expected(")");
654
655 return true;
656}
657
John Kessenich34fb0362016-05-03 23:17:20 -0600658// The top-level full expression recognizer.
659//
John Kessenich87142c72016-03-12 20:24:24 -0700660// expression
John Kessenich34fb0362016-05-03 23:17:20 -0600661// : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
John Kessenich87142c72016-03-12 20:24:24 -0700662//
663bool HlslGrammar::acceptExpression(TIntermTyped*& node)
664{
LoopDawgef764a22016-06-03 09:17:51 -0600665 node = nullptr;
666
John Kessenich34fb0362016-05-03 23:17:20 -0600667 // assignment_expression
668 if (! acceptAssignmentExpression(node))
669 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600670
John Kessenich34fb0362016-05-03 23:17:20 -0600671 if (! peekTokenClass(EHTokComma))
672 return true;
673
674 do {
675 // ... COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600676 TSourceLoc loc = token.loc;
John Kessenich34fb0362016-05-03 23:17:20 -0600677 advanceToken();
John Kessenich5f934b02016-03-13 17:58:25 -0600678
John Kessenich34fb0362016-05-03 23:17:20 -0600679 // ... assignment_expression
680 TIntermTyped* rightNode = nullptr;
681 if (! acceptAssignmentExpression(rightNode)) {
682 expected("assignment expression");
683 return false;
John Kessenich5f934b02016-03-13 17:58:25 -0600684 }
685
John Kessenich34fb0362016-05-03 23:17:20 -0600686 node = intermediate.addComma(node, rightNode, loc);
687
688 if (! peekTokenClass(EHTokComma))
689 return true;
690 } while (true);
691}
692
693// Accept an assignment expression, where assignment operations
694// associate right-to-left. This is, it is implicit, for example
695//
696// a op (b op (c op d))
697//
698// assigment_expression
699// : binary_expression op binary_expression op binary_expression ...
700//
701bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
702{
703 if (! acceptBinaryExpression(node, PlLogicalOr))
704 return false;
705
706 TOperator assignOp = HlslOpMap::assignment(peek());
707 if (assignOp == EOpNull)
708 return true;
709
710 // ... op
711 TSourceLoc loc = token.loc;
712 advanceToken();
713
714 // ... binary_expression
715 // But, done by recursing this function, which automatically
716 // gets the right-to-left associativity.
717 TIntermTyped* rightNode = nullptr;
718 if (! acceptAssignmentExpression(rightNode)) {
719 expected("assignment expression");
John Kessenich5f934b02016-03-13 17:58:25 -0600720 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700721 }
722
John Kessenich34fb0362016-05-03 23:17:20 -0600723 node = intermediate.addAssign(assignOp, node, rightNode, loc);
724
725 if (! peekTokenClass(EHTokComma))
726 return true;
727
728 return true;
729}
730
731// Accept a binary expression, for binary operations that
732// associate left-to-right. This is, it is implicit, for example
733//
734// ((a op b) op c) op d
735//
736// binary_expression
737// : expression op expression op expression ...
738//
739// where 'expression' is the next higher level in precedence.
740//
741bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
742{
743 if (precedenceLevel > PlMul)
744 return acceptUnaryExpression(node);
745
746 // assignment_expression
747 if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
748 return false;
749
750 TOperator op = HlslOpMap::binary(peek());
751 PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
752 if (tokenLevel < precedenceLevel)
753 return true;
754
755 do {
756 // ... op
757 TSourceLoc loc = token.loc;
758 advanceToken();
759
760 // ... expression
761 TIntermTyped* rightNode = nullptr;
762 if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
763 expected("expression");
764 return false;
765 }
766
767 node = intermediate.addBinaryMath(op, node, rightNode, loc);
768
769 if (! peekTokenClass(EHTokComma))
770 return true;
771 } while (true);
772}
773
774// unary_expression
John Kessenich1cc1a282016-06-03 16:55:49 -0600775// : (type) unary_expression
776// | + unary_expression
John Kessenich34fb0362016-05-03 23:17:20 -0600777// | - unary_expression
778// | ! unary_expression
779// | ~ unary_expression
780// | ++ unary_expression
781// | -- unary_expression
782// | postfix_expression
783//
784bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
785{
John Kessenich1cc1a282016-06-03 16:55:49 -0600786 // (type) unary_expression
787 // Have to look two steps ahead, because this could be, e.g., a
788 // postfix_expression instead, since that also starts with at "(".
789 if (acceptTokenClass(EHTokLeftParen)) {
790 TType castType;
791 if (acceptType(castType)) {
792 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600793 expected(")");
John Kessenich1cc1a282016-06-03 16:55:49 -0600794 return false;
795 }
796
797 // We've matched "(type)" now, get the expression to cast
798 TSourceLoc loc = token.loc;
799 if (! acceptUnaryExpression(node))
800 return false;
801
802 // Hook it up like a constructor
803 TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
804 if (constructorFunction == nullptr) {
805 expected("type that can be constructed");
806 return false;
807 }
808 TIntermTyped* arguments = nullptr;
809 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
810 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
811
812 return true;
813 } else {
814 // This isn't a type cast, but it still started "(", so if it is a
815 // unary expression, it can only be a postfix_expression, so try that.
816 // Back it up first.
817 recedeToken();
818 return acceptPostfixExpression(node);
819 }
820 }
821
822 // peek for "op unary_expression"
John Kessenich34fb0362016-05-03 23:17:20 -0600823 TOperator unaryOp = HlslOpMap::preUnary(peek());
824
John Kessenich1cc1a282016-06-03 16:55:49 -0600825 // postfix_expression (if no unary operator)
John Kessenich34fb0362016-05-03 23:17:20 -0600826 if (unaryOp == EOpNull)
827 return acceptPostfixExpression(node);
828
829 // op unary_expression
830 TSourceLoc loc = token.loc;
831 advanceToken();
832 if (! acceptUnaryExpression(node))
833 return false;
834
835 // + is a no-op
836 if (unaryOp == EOpAdd)
837 return true;
838
839 node = intermediate.addUnaryMath(unaryOp, node, loc);
840
841 return node != nullptr;
842}
843
844// postfix_expression
845// : LEFT_PAREN expression RIGHT_PAREN
846// | literal
847// | constructor
848// | identifier
849// | function_call
850// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
851// | postfix_expression DOT IDENTIFIER
852// | postfix_expression INC_OP
853// | postfix_expression DEC_OP
854//
855bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
856{
857 // Not implemented as self-recursive:
858 // The logical "right recursion" is done with an loop at the end
859
860 // idToken will pick up either a variable or a function name in a function call
861 HlslToken idToken;
862
John Kessenich21472ae2016-06-04 11:46:33 -0600863 // Find something before the postfix operations, as they can't operate
864 // on nothing. So, no "return true", they fall through, only "return false".
John Kessenich87142c72016-03-12 20:24:24 -0700865 if (acceptTokenClass(EHTokLeftParen)) {
John Kessenich21472ae2016-06-04 11:46:33 -0600866 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700867 if (! acceptExpression(node)) {
868 expected("expression");
869 return false;
870 }
871 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -0600872 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -0700873 return false;
874 }
John Kessenich34fb0362016-05-03 23:17:20 -0600875 } else if (acceptLiteral(node)) {
876 // literal (nothing else to do yet), go on to the
877 } else if (acceptConstructor(node)) {
878 // constructor (nothing else to do yet)
879 } else if (acceptIdentifier(idToken)) {
880 // identifier or function_call name
881 if (! peekTokenClass(EHTokLeftParen)) {
John Kessenich077e0522016-06-09 02:02:17 -0600882 node = parseContext.handleVariable(idToken.loc, token.string);
John Kessenich34fb0362016-05-03 23:17:20 -0600883 } else if (acceptFunctionCall(idToken, node)) {
884 // function_call (nothing else to do yet)
885 } else {
886 expected("function call arguments");
887 return false;
888 }
John Kessenich21472ae2016-06-04 11:46:33 -0600889 } else {
890 // nothing found, can't post operate
891 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700892 }
893
John Kessenich21472ae2016-06-04 11:46:33 -0600894 // Something was found, chain as many postfix operations as exist.
John Kessenich34fb0362016-05-03 23:17:20 -0600895 do {
896 TSourceLoc loc = token.loc;
897 TOperator postOp = HlslOpMap::postUnary(peek());
John Kessenich87142c72016-03-12 20:24:24 -0700898
John Kessenich34fb0362016-05-03 23:17:20 -0600899 // Consume only a valid post-unary operator, otherwise we are done.
900 switch (postOp) {
901 case EOpIndexDirectStruct:
902 case EOpIndexIndirect:
903 case EOpPostIncrement:
904 case EOpPostDecrement:
905 advanceToken();
906 break;
907 default:
908 return true;
909 }
John Kessenich87142c72016-03-12 20:24:24 -0700910
John Kessenich34fb0362016-05-03 23:17:20 -0600911 // We have a valid post-unary operator, process it.
912 switch (postOp) {
913 case EOpIndexDirectStruct:
914 // todo
915 break;
916 case EOpIndexIndirect:
917 {
918 TIntermTyped* indexNode = nullptr;
919 if (! acceptExpression(indexNode) ||
920 ! peekTokenClass(EHTokRightBracket)) {
921 expected("expression followed by ']'");
922 return false;
923 }
924 // todo: node = intermediate.addBinaryMath(
925 }
926 case EOpPostIncrement:
927 case EOpPostDecrement:
928 node = intermediate.addUnaryMath(postOp, node, loc);
929 break;
930 default:
931 assert(0);
932 break;
933 }
934 } while (true);
John Kessenich87142c72016-03-12 20:24:24 -0700935}
936
John Kessenichd016be12016-03-13 11:24:20 -0600937// constructor
John Kessenich078d7f22016-03-14 10:02:11 -0600938// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -0600939//
940bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
941{
942 // type
943 TType type;
944 if (acceptType(type)) {
945 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
946 if (constructorFunction == nullptr)
947 return false;
948
949 // arguments
John Kessenich4678ca92016-05-13 09:33:42 -0600950 TIntermTyped* arguments = nullptr;
John Kessenichd016be12016-03-13 11:24:20 -0600951 if (! acceptArguments(constructorFunction, arguments)) {
952 expected("constructor arguments");
953 return false;
954 }
955
956 // hook it up
957 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
958
959 return true;
960 }
961
962 return false;
963}
964
John Kessenich34fb0362016-05-03 23:17:20 -0600965// The function_call identifier was already recognized, and passed in as idToken.
966//
967// function_call
968// : [idToken] arguments
969//
John Kessenich4678ca92016-05-13 09:33:42 -0600970bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
John Kessenich34fb0362016-05-03 23:17:20 -0600971{
John Kessenich4678ca92016-05-13 09:33:42 -0600972 // arguments
973 TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
974 TIntermTyped* arguments = nullptr;
975 if (! acceptArguments(function, arguments))
976 return false;
977
978 node = parseContext.handleFunctionCall(idToken.loc, function, arguments);
979
980 return true;
John Kessenich34fb0362016-05-03 23:17:20 -0600981}
982
John Kessenich87142c72016-03-12 20:24:24 -0700983// arguments
John Kessenich078d7f22016-03-14 10:02:11 -0600984// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700985//
John Kessenichd016be12016-03-13 11:24:20 -0600986// The arguments are pushed onto the 'function' argument list and
987// onto the 'arguments' aggregate.
988//
John Kessenich4678ca92016-05-13 09:33:42 -0600989bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -0700990{
John Kessenich078d7f22016-03-14 10:02:11 -0600991 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700992 if (! acceptTokenClass(EHTokLeftParen))
993 return false;
994
995 do {
John Kessenichd016be12016-03-13 11:24:20 -0600996 // expression
John Kessenich87142c72016-03-12 20:24:24 -0700997 TIntermTyped* arg;
John Kessenich4678ca92016-05-13 09:33:42 -0600998 if (! acceptAssignmentExpression(arg))
John Kessenich87142c72016-03-12 20:24:24 -0700999 break;
John Kessenichd016be12016-03-13 11:24:20 -06001000
1001 // hook it up
1002 parseContext.handleFunctionArgument(function, arguments, arg);
1003
John Kessenich078d7f22016-03-14 10:02:11 -06001004 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -07001005 if (! acceptTokenClass(EHTokComma))
1006 break;
1007 } while (true);
1008
John Kessenich078d7f22016-03-14 10:02:11 -06001009 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -07001010 if (! acceptTokenClass(EHTokRightParen)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001011 expected(")");
John Kessenich87142c72016-03-12 20:24:24 -07001012 return false;
1013 }
1014
1015 return true;
1016}
1017
1018bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
1019{
1020 switch (token.tokenClass) {
1021 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001022 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001023 break;
1024 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001025 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001026 break;
1027 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001028 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001029 break;
1030 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -06001031 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -07001032 break;
1033
1034 default:
1035 return false;
1036 }
1037
1038 advanceToken();
1039
1040 return true;
1041}
1042
John Kessenich5f934b02016-03-13 17:58:25 -06001043// compound_statement
John Kessenich34fb0362016-05-03 23:17:20 -06001044// : LEFT_CURLY statement statement ... RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001045//
John Kessenich21472ae2016-06-04 11:46:33 -06001046bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
John Kessenich87142c72016-03-12 20:24:24 -07001047{
John Kessenich21472ae2016-06-04 11:46:33 -06001048 TIntermAggregate* compoundStatement = nullptr;
1049
John Kessenich34fb0362016-05-03 23:17:20 -06001050 // LEFT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001051 if (! acceptTokenClass(EHTokLeftBrace))
1052 return false;
1053
1054 // statement statement ...
1055 TIntermNode* statement = nullptr;
1056 while (acceptStatement(statement)) {
1057 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -06001058 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001059 }
John Kessenich34fb0362016-05-03 23:17:20 -06001060 if (compoundStatement)
1061 compoundStatement->setOperator(EOpSequence);
John Kessenich5f934b02016-03-13 17:58:25 -06001062
John Kessenich21472ae2016-06-04 11:46:33 -06001063 retStatement = compoundStatement;
1064
John Kessenich34fb0362016-05-03 23:17:20 -06001065 // RIGHT_CURLY
John Kessenich5f934b02016-03-13 17:58:25 -06001066 return acceptTokenClass(EHTokRightBrace);
1067}
1068
John Kessenich0d2b6de2016-06-05 11:23:11 -06001069bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
1070{
1071 parseContext.pushScope();
John Kessenich077e0522016-06-09 02:02:17 -06001072 bool result = acceptStatement(statement);
John Kessenich0d2b6de2016-06-05 11:23:11 -06001073 parseContext.popScope();
1074
1075 return result;
1076}
1077
John Kessenich077e0522016-06-09 02:02:17 -06001078bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
John Kessenich0d2b6de2016-06-05 11:23:11 -06001079{
John Kessenich077e0522016-06-09 02:02:17 -06001080 parseContext.pushScope();
1081 bool result = acceptCompoundStatement(statement);
1082 parseContext.popScope();
John Kessenich0d2b6de2016-06-05 11:23:11 -06001083
1084 return result;
1085}
1086
John Kessenich5f934b02016-03-13 17:58:25 -06001087// statement
John Kessenich21472ae2016-06-04 11:46:33 -06001088// : attributes attributed_statement
1089//
1090// attributed_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001091// : compound_statement
John Kessenich21472ae2016-06-04 11:46:33 -06001092// | SEMICOLON
John Kessenich078d7f22016-03-14 10:02:11 -06001093// | expression SEMICOLON
John Kessenich21472ae2016-06-04 11:46:33 -06001094// | declaration_statement
1095// | selection_statement
1096// | switch_statement
1097// | case_label
1098// | iteration_statement
1099// | jump_statement
John Kessenich5f934b02016-03-13 17:58:25 -06001100//
1101bool HlslGrammar::acceptStatement(TIntermNode*& statement)
1102{
John Kessenich21472ae2016-06-04 11:46:33 -06001103 statement = nullptr;
John Kessenich5f934b02016-03-13 17:58:25 -06001104
John Kessenich21472ae2016-06-04 11:46:33 -06001105 // attributes
1106 acceptAttributes();
John Kessenich5f934b02016-03-13 17:58:25 -06001107
John Kessenich21472ae2016-06-04 11:46:33 -06001108 // attributed_statement
1109 switch (peek()) {
1110 case EHTokLeftBrace:
John Kessenich077e0522016-06-09 02:02:17 -06001111 return acceptScopedCompoundStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001112
John Kessenich21472ae2016-06-04 11:46:33 -06001113 case EHTokIf:
1114 return acceptSelectionStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001115
John Kessenich21472ae2016-06-04 11:46:33 -06001116 case EHTokSwitch:
1117 return acceptSwitchStatement(statement);
John Kessenich5f934b02016-03-13 17:58:25 -06001118
John Kessenich21472ae2016-06-04 11:46:33 -06001119 case EHTokFor:
1120 case EHTokDo:
1121 case EHTokWhile:
1122 return acceptIterationStatement(statement);
1123
1124 case EHTokContinue:
1125 case EHTokBreak:
1126 case EHTokDiscard:
1127 case EHTokReturn:
1128 return acceptJumpStatement(statement);
1129
1130 case EHTokCase:
1131 return acceptCaseLabel(statement);
1132
1133 case EHTokSemicolon:
1134 return acceptTokenClass(EHTokSemicolon);
1135
1136 case EHTokRightBrace:
1137 // Performance: not strictly necessary, but stops a bunch of hunting early,
1138 // and is how sequences of statements end.
John Kessenich5f934b02016-03-13 17:58:25 -06001139 return false;
1140
John Kessenich21472ae2016-06-04 11:46:33 -06001141 default:
1142 {
1143 // declaration
1144 if (acceptDeclaration(statement))
1145 return true;
1146
1147 // expression
1148 TIntermTyped* node;
1149 if (acceptExpression(node))
1150 statement = node;
1151 else
1152 return false;
1153
1154 // SEMICOLON (following an expression)
1155 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001156 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001157 return false;
1158 }
1159 }
1160 }
1161
John Kessenich5f934b02016-03-13 17:58:25 -06001162 return true;
John Kessenich87142c72016-03-12 20:24:24 -07001163}
1164
John Kessenich21472ae2016-06-04 11:46:33 -06001165// attributes
1166// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
1167//
1168// attribute:
1169// : UNROLL
1170// | UNROLL LEFT_PAREN literal RIGHT_PAREN
1171// | FASTOPT
1172// | ALLOW_UAV_CONDITION
1173// | BRANCH
1174// | FLATTEN
1175// | FORCECASE
1176// | CALL
1177//
1178void HlslGrammar::acceptAttributes()
1179{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001180 // For now, accept the [ XXX(X) ] syntax, but drop.
1181 // TODO: subset to correct set? Pass on?
1182 do {
1183 // LEFT_BRACKET?
1184 if (! acceptTokenClass(EHTokLeftBracket))
1185 return;
1186
1187 // attribute
1188 if (peekTokenClass(EHTokIdentifier)) {
1189 // 'token.string' is the attribute
1190 advanceToken();
1191 } else if (! peekTokenClass(EHTokRightBracket)) {
1192 expected("identifier");
1193 advanceToken();
1194 }
1195
1196 // (x)
1197 if (acceptTokenClass(EHTokLeftParen)) {
1198 TIntermTyped* node;
1199 if (! acceptLiteral(node))
1200 expected("literal");
1201 // 'node' has the literal in it
1202 if (! acceptTokenClass(EHTokRightParen))
1203 expected(")");
1204 }
1205
1206 // RIGHT_BRACKET
1207 if (acceptTokenClass(EHTokRightBracket))
1208 continue;
1209
1210 expected("]");
1211 return;
1212
1213 } while (true);
John Kessenich21472ae2016-06-04 11:46:33 -06001214}
1215
John Kessenich0d2b6de2016-06-05 11:23:11 -06001216// selection_statement
1217// : IF LEFT_PAREN expression RIGHT_PAREN statement
1218// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
1219//
John Kessenich21472ae2016-06-04 11:46:33 -06001220bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
1221{
John Kessenich0d2b6de2016-06-05 11:23:11 -06001222 TSourceLoc loc = token.loc;
1223
1224 // IF
1225 if (! acceptTokenClass(EHTokIf))
1226 return false;
1227
1228 // so that something declared in the condition is scoped to the lifetimes
1229 // of the then-else statements
1230 parseContext.pushScope();
1231
1232 // LEFT_PAREN expression RIGHT_PAREN
1233 TIntermTyped* condition;
1234 if (! acceptParenExpression(condition))
1235 return false;
1236
1237 // create the child statements
1238 TIntermNodePair thenElse = { nullptr, nullptr };
1239
1240 // then statement
1241 if (! acceptScopedStatement(thenElse.node1)) {
1242 expected("then statement");
1243 return false;
1244 }
1245
1246 // ELSE
1247 if (acceptTokenClass(EHTokElse)) {
1248 // else statement
1249 if (! acceptScopedStatement(thenElse.node2)) {
1250 expected("else statement");
1251 return false;
1252 }
1253 }
1254
1255 // Put the pieces together
1256 statement = intermediate.addSelection(condition, thenElse, loc);
1257 parseContext.popScope();
1258
1259 return true;
John Kessenich21472ae2016-06-04 11:46:33 -06001260}
1261
1262bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
1263{
1264 return false;
1265}
1266
John Kessenich119f8f62016-06-05 15:44:07 -06001267// iteration_statement
1268// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
1269// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
1270// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
1271//
1272// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
John Kessenich21472ae2016-06-04 11:46:33 -06001273bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
1274{
John Kessenich119f8f62016-06-05 15:44:07 -06001275 TSourceLoc loc = token.loc;
1276 TIntermTyped* condition = nullptr;
1277
1278 EHlslTokenClass loop = peek();
1279 assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
1280
1281 // WHILE or DO or FOR
1282 advanceToken();
1283
1284 switch (loop) {
1285 case EHTokWhile:
1286 // so that something declared in the condition is scoped to the lifetime
1287 // of the while sub-statement
1288 parseContext.pushScope();
1289 parseContext.nestLooping();
1290
1291 // LEFT_PAREN condition RIGHT_PAREN
1292 if (! acceptParenExpression(condition))
1293 return false;
1294
1295 // statement
1296 if (! acceptScopedStatement(statement)) {
1297 expected("while sub-statement");
1298 return false;
1299 }
1300
1301 parseContext.unnestLooping();
1302 parseContext.popScope();
1303
1304 statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
1305
1306 return true;
1307
1308 case EHTokDo:
1309 parseContext.nestLooping();
1310
1311 if (! acceptTokenClass(EHTokLeftBrace))
1312 expected("{");
1313
1314 // statement
1315 if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
1316 expected("do sub-statement");
1317 return false;
1318 }
1319
1320 if (! acceptTokenClass(EHTokRightBrace))
1321 expected("}");
1322
1323 // WHILE
1324 if (! acceptTokenClass(EHTokWhile)) {
1325 expected("while");
1326 return false;
1327 }
1328
1329 // LEFT_PAREN condition RIGHT_PAREN
1330 TIntermTyped* condition;
1331 if (! acceptParenExpression(condition))
1332 return false;
1333
1334 if (! acceptTokenClass(EHTokSemicolon))
1335 expected(";");
1336
1337 parseContext.unnestLooping();
1338
1339 statement = intermediate.addLoop(statement, condition, 0, false, loc);
1340
1341 return true;
1342
1343 case EHTokFor:
1344 {
1345 // LEFT_PAREN
1346 if (! acceptTokenClass(EHTokLeftParen))
1347 expected("(");
1348
1349 // so that something declared in the condition is scoped to the lifetime
1350 // of the for sub-statement
1351 parseContext.pushScope();
1352
1353 // initializer SEMI_COLON
1354 TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
1355 acceptExpression(initializer);
1356 if (! acceptTokenClass(EHTokSemicolon))
1357 expected(";");
1358
1359 parseContext.nestLooping();
1360
1361 // condition SEMI_COLON
1362 acceptExpression(condition);
1363 if (! acceptTokenClass(EHTokSemicolon))
1364 expected(";");
1365
1366 // iterator SEMI_COLON
1367 TIntermTyped* iterator = nullptr;
1368 acceptExpression(iterator);
1369 if (! acceptTokenClass(EHTokRightParen))
1370 expected(")");
1371
1372 // statement
1373 if (! acceptScopedStatement(statement)) {
1374 expected("for sub-statement");
1375 return false;
1376 }
1377
1378 statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
1379
1380 parseContext.popScope();
1381 parseContext.unnestLooping();
1382
1383 return true;
1384 }
1385
1386 default:
1387 return false;
1388 }
John Kessenich21472ae2016-06-04 11:46:33 -06001389}
1390
1391// jump_statement
1392// : CONTINUE SEMICOLON
1393// | BREAK SEMICOLON
1394// | DISCARD SEMICOLON
1395// | RETURN SEMICOLON
1396// | RETURN expression SEMICOLON
1397//
1398bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
1399{
1400 switch (peek()) {
1401 case EHTokContinue:
1402 case EHTokBreak:
1403 case EHTokDiscard:
1404 // TODO
1405 return false;
1406
1407 case EHTokReturn:
1408 // return
1409 if (acceptTokenClass(EHTokReturn)) {
1410 // expression
1411 TIntermTyped* node;
1412 if (acceptExpression(node)) {
1413 // hook it up
1414 statement = intermediate.addBranch(EOpReturn, node, token.loc);
1415 } else
1416 statement = intermediate.addBranch(EOpReturn, token.loc);
1417
1418 // SEMICOLON
1419 if (! acceptTokenClass(EHTokSemicolon)) {
John Kessenich0d2b6de2016-06-05 11:23:11 -06001420 expected(";");
John Kessenich21472ae2016-06-04 11:46:33 -06001421 return false;
1422 }
1423
1424 return true;
1425 }
1426
1427 default:
1428 return false;
1429 }
1430}
1431
1432
1433bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
1434{
1435 return false;
1436}
1437
John Kessenich078d7f22016-03-14 10:02:11 -06001438// COLON semantic
1439bool HlslGrammar::acceptSemantic()
1440{
1441 // COLON
1442 if (acceptTokenClass(EHTokColon)) {
1443 // semantic
John Kessenichaecd4972016-03-14 10:46:34 -06001444 HlslToken idToken;
1445 if (! acceptIdentifier(idToken)) {
John Kessenich078d7f22016-03-14 10:02:11 -06001446 expected("semantic");
1447 return false;
1448 }
1449 }
1450
1451 return true;
1452}
1453
John Kesseniche01a9bc2016-03-12 20:11:22 -07001454} // end namespace glslang