blob: 4528a19174737c85335c75b1d70fcdea209b4bdd [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
71// Load 'token' with the next token in the stream of tokens.
72void HlslGrammar::advanceToken()
73{
John Kessenich078d7f22016-03-14 10:02:11 -060074 scanner.tokenize(token);
John Kesseniche01a9bc2016-03-12 20:11:22 -070075}
76
77// Return true and advance to the next token if the current token is the
78// expected (passed in) token class.
79bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass)
80{
81 if (token.tokenClass == tokenClass) {
82 advanceToken();
83 return true;
84 }
85
86 return false;
87}
88
John Kessenich078d7f22016-03-14 10:02:11 -060089// Return true, without advancing to the next token, if the current token is
90// the expected (passed in) token class.
91bool HlslGrammar::peekTokenClass(EHlslTokenClass tokenClass)
92{
93 return token.tokenClass == tokenClass;
94}
95
John Kessenichaecd4972016-03-14 10:46:34 -060096// Only process the next token if it is an identifier.
97// Return true if it was an identifier.
98bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
99{
100 if (peekTokenClass(EHTokIdentifier)) {
101 idToken = token;
102 advanceToken();
103 return true;
104 }
105
106 return false;
107}
108
John Kesseniche01a9bc2016-03-12 20:11:22 -0700109// compilationUnit
110// : list of externalDeclaration
111//
112bool HlslGrammar::acceptCompilationUnit()
113{
John Kessenichd016be12016-03-13 11:24:20 -0600114 TIntermNode* unitNode = nullptr;
115
John Kesseniche01a9bc2016-03-12 20:11:22 -0700116 while (token.tokenClass != EHTokNone) {
John Kessenichd016be12016-03-13 11:24:20 -0600117 // externalDeclaration
118 TIntermNode* declarationNode;
119 if (! acceptDeclaration(declarationNode))
John Kesseniche01a9bc2016-03-12 20:11:22 -0700120 return false;
John Kessenichd016be12016-03-13 11:24:20 -0600121
122 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600123 unitNode = intermediate.growAggregate(unitNode, declarationNode);
John Kesseniche01a9bc2016-03-12 20:11:22 -0700124 }
125
John Kessenichd016be12016-03-13 11:24:20 -0600126 // set root of AST
John Kessenich078d7f22016-03-14 10:02:11 -0600127 intermediate.setTreeRoot(unitNode);
John Kessenichd016be12016-03-13 11:24:20 -0600128
John Kesseniche01a9bc2016-03-12 20:11:22 -0700129 return true;
130}
131
132// declaration
John Kessenich078d7f22016-03-14 10:02:11 -0600133// : SEMICOLON
134// : fully_specified_type SEMICOLON
135// | fully_specified_type identifier SEMICOLON
136// | fully_specified_type identifier = expression SEMICOLON
137// | fully_specified_type identifier function_parameters SEMICOLON // function prototype
138// | fully_specified_type identifier function_parameters COLON semantic compound_statement // function definition
John Kessenich87142c72016-03-12 20:24:24 -0700139//
John Kessenichd016be12016-03-13 11:24:20 -0600140// 'node' could get created if the declaration creates code, like an initializer
141// or a function body.
142//
143bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
John Kesseniche01a9bc2016-03-12 20:11:22 -0700144{
John Kessenichd016be12016-03-13 11:24:20 -0600145 node = nullptr;
146
John Kessenich87142c72016-03-12 20:24:24 -0700147 // fully_specified_type
148 TType type;
149 if (! acceptFullySpecifiedType(type))
150 return false;
151
152 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600153 HlslToken idToken;
154 if (acceptIdentifier(idToken)) {
John Kessenich87142c72016-03-12 20:24:24 -0700155 // = expression
156 TIntermTyped* expressionNode = nullptr;
157 if (acceptTokenClass(EHTokEqual)) {
158 if (! acceptExpression(expressionNode)) {
159 expected("initializer");
160 return false;
161 }
162 }
163
John Kessenich078d7f22016-03-14 10:02:11 -0600164 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700165 if (acceptTokenClass(EHTokSemicolon)) {
John Kessenichaecd4972016-03-14 10:46:34 -0600166 node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
John Kessenich87142c72016-03-12 20:24:24 -0700167 return true;
168 }
John Kessenich5f934b02016-03-13 17:58:25 -0600169
170 // function_parameters
John Kessenichaecd4972016-03-14 10:46:34 -0600171 TFunction* function = new TFunction(idToken.string, type);
John Kessenich5f934b02016-03-13 17:58:25 -0600172 if (acceptFunctionParameters(*function)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600173 // COLON semantic
174 acceptSemantic();
175
John Kessenich5f934b02016-03-13 17:58:25 -0600176 // compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600177 if (peekTokenClass(EHTokLeftBrace))
John Kessenich5f934b02016-03-13 17:58:25 -0600178 return acceptFunctionDefinition(*function, node);
179
John Kessenich078d7f22016-03-14 10:02:11 -0600180 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600181 if (acceptTokenClass(EHTokSemicolon))
182 return true;
183
184 return false;
185 }
John Kessenich87142c72016-03-12 20:24:24 -0700186 }
187
John Kessenich078d7f22016-03-14 10:02:11 -0600188 // SEMICOLON
John Kessenich87142c72016-03-12 20:24:24 -0700189 if (acceptTokenClass(EHTokSemicolon))
190 return true;
191
John Kesseniche01a9bc2016-03-12 20:11:22 -0700192 return true;
193}
194
John Kessenich87142c72016-03-12 20:24:24 -0700195// fully_specified_type
196// : type_specifier
197// | type_qualifier type_specifier
198//
199bool HlslGrammar::acceptFullySpecifiedType(TType& type)
200{
201 // type_qualifier
202 TQualifier qualifier;
203 qualifier.clear();
204 acceptQualifier(qualifier);
205
206 // type_specifier
207 if (! acceptType(type))
208 return false;
209 type.getQualifier() = qualifier;
210
211 return true;
212}
213
214// If token is a qualifier, return its token class and advance to the next
215// qualifier. Otherwise, return false, and don't advance.
216void HlslGrammar::acceptQualifier(TQualifier& qualifier)
217{
218 switch (token.tokenClass) {
219 case EHTokUniform:
220 qualifier.storage = EvqUniform;
221 break;
222 case EHTokConst:
223 qualifier.storage = EvqConst;
224 break;
225 default:
226 return;
227 }
228
229 advanceToken();
230}
231
232// If token is for a type, update 'type' with the type information,
233// and return true and advance.
234// Otherwise, return false, and don't advance
235bool HlslGrammar::acceptType(TType& type)
236{
237 if (! token.isType)
238 return false;
239
240 switch (token.tokenClass) {
241 case EHTokInt:
242 case EHTokInt1:
243 case EHTokDword:
244 new(&type) TType(EbtInt);
245 break;
246 case EHTokFloat:
247 case EHTokFloat1:
248 new(&type) TType(EbtFloat);
249 break;
250
251 case EHTokFloat2:
252 new(&type) TType(EbtFloat, EvqTemporary, 2);
253 break;
254 case EHTokFloat3:
255 new(&type) TType(EbtFloat, EvqTemporary, 3);
256 break;
257 case EHTokFloat4:
258 new(&type) TType(EbtFloat, EvqTemporary, 4);
259 break;
260
261 case EHTokInt2:
262 new(&type) TType(EbtInt, EvqTemporary, 2);
263 break;
264 case EHTokInt3:
265 new(&type) TType(EbtInt, EvqTemporary, 3);
266 break;
267 case EHTokInt4:
268 new(&type) TType(EbtInt, EvqTemporary, 4);
269 break;
270
271 case EHTokBool2:
272 new(&type) TType(EbtBool, EvqTemporary, 2);
273 break;
274 case EHTokBool3:
275 new(&type) TType(EbtBool, EvqTemporary, 3);
276 break;
277 case EHTokBool4:
278 new(&type) TType(EbtBool, EvqTemporary, 4);
279 break;
280
281 case EHTokFloat2x2:
282 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
283 break;
284 case EHTokFloat2x3:
285 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
286 break;
287 case EHTokFloat2x4:
288 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
289 break;
290 case EHTokFloat3x2:
291 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
292 break;
293 case EHTokFloat3x3:
294 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
295 break;
296 case EHTokFloat3x4:
297 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
298 break;
299 case EHTokFloat4x2:
300 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
301 break;
302 case EHTokFloat4x3:
303 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
304 break;
305 case EHTokFloat4x4:
306 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
307 break;
308
309 default:
310 return false;
311 }
312
313 advanceToken();
314
315 return true;
316}
317
John Kessenich5f934b02016-03-13 17:58:25 -0600318// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600319// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600320//
321bool HlslGrammar::acceptFunctionParameters(TFunction& function)
322{
John Kessenich078d7f22016-03-14 10:02:11 -0600323 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600324 if (! acceptTokenClass(EHTokLeftParen))
325 return false;
326
327 do {
328 // parameter_declaration
329 if (! acceptParameterDeclaration(function))
330 break;
331
John Kessenich078d7f22016-03-14 10:02:11 -0600332 // COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600333 if (! acceptTokenClass(EHTokComma))
334 break;
335 } while (true);
336
John Kessenich078d7f22016-03-14 10:02:11 -0600337 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600338 if (! acceptTokenClass(EHTokRightParen)) {
339 expected("right parenthesis");
340 return false;
341 }
342
343 return true;
344}
345
346// parameter_declaration
347// : fully_specified_type
348// | fully_specified_type identifier
349//
350bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
351{
352 // fully_specified_type
353 TType* type = new TType;
354 if (! acceptFullySpecifiedType(*type))
355 return false;
356
357 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600358 HlslToken idToken;
359 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600360
John Kessenichaecd4972016-03-14 10:46:34 -0600361 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600362 function.addParameter(param);
363
364 return true;
365}
366
367// Do the work to create the function definition in addition to
368// parsing the body (compound_statement).
369bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
370{
371 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
372
373 // This does a symbol table push
374 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
375
376 // compound_statement
377 TIntermAggregate* functionBody = nullptr;
378 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600379 node = intermediate.growAggregate(node, functionBody);
380 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600381 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
382 parseContext.symbolTable.pop(nullptr);
383
384 return true;
385 }
386
387 return false;
388}
389
John Kessenich87142c72016-03-12 20:24:24 -0700390// expression
391// : identifier
John Kessenich078d7f22016-03-14 10:02:11 -0600392// | identifier operator identifier // todo: generalize to all expressions
393// | LEFT_PAREN expression RIGHT_PAREN
394// | constructor
John Kessenich87142c72016-03-12 20:24:24 -0700395// | literal
John Kessenich87142c72016-03-12 20:24:24 -0700396//
397bool HlslGrammar::acceptExpression(TIntermTyped*& node)
398{
399 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600400 HlslToken idToken;
401 if (acceptIdentifier(idToken)) {
402 TIntermTyped* left = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich5f934b02016-03-13 17:58:25 -0600403
404 // operator?
405 TOperator op;
406 if (! acceptOperator(op))
407 return true;
408 TSourceLoc loc = token.loc;
409
410 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600411 if (acceptIdentifier(idToken)) {
412 TIntermTyped* right = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich078d7f22016-03-14 10:02:11 -0600413 node = intermediate.addBinaryMath(op, left, right, loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600414 return true;
415 }
416
417 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700418 }
419
John Kessenich078d7f22016-03-14 10:02:11 -0600420 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700421 if (acceptTokenClass(EHTokLeftParen)) {
422 if (! acceptExpression(node)) {
423 expected("expression");
424 return false;
425 }
426 if (! acceptTokenClass(EHTokRightParen)) {
427 expected("right parenthesis");
428 return false;
429 }
430
431 return true;
432 }
433
434 // literal
435 if (acceptLiteral(node))
436 return true;
437
John Kessenich078d7f22016-03-14 10:02:11 -0600438 // constructor
John Kessenichd016be12016-03-13 11:24:20 -0600439 if (acceptConstructor(node))
John Kessenich87142c72016-03-12 20:24:24 -0700440 return true;
John Kessenich87142c72016-03-12 20:24:24 -0700441
John Kessenich5f934b02016-03-13 17:58:25 -0600442 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700443}
444
John Kessenichd016be12016-03-13 11:24:20 -0600445// constructor
John Kessenich078d7f22016-03-14 10:02:11 -0600446// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -0600447//
448bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
449{
450 // type
451 TType type;
452 if (acceptType(type)) {
453 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
454 if (constructorFunction == nullptr)
455 return false;
456
457 // arguments
458 TIntermAggregate* arguments = nullptr;
459 if (! acceptArguments(constructorFunction, arguments)) {
460 expected("constructor arguments");
461 return false;
462 }
463
464 // hook it up
465 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
466
467 return true;
468 }
469
470 return false;
471}
472
John Kessenich87142c72016-03-12 20:24:24 -0700473// arguments
John Kessenich078d7f22016-03-14 10:02:11 -0600474// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700475//
John Kessenichd016be12016-03-13 11:24:20 -0600476// The arguments are pushed onto the 'function' argument list and
477// onto the 'arguments' aggregate.
478//
479bool HlslGrammar::acceptArguments(TFunction* function, TIntermAggregate*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -0700480{
John Kessenich078d7f22016-03-14 10:02:11 -0600481 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700482 if (! acceptTokenClass(EHTokLeftParen))
483 return false;
484
485 do {
John Kessenichd016be12016-03-13 11:24:20 -0600486 // expression
John Kessenich87142c72016-03-12 20:24:24 -0700487 TIntermTyped* arg;
488 if (! acceptExpression(arg))
489 break;
John Kessenichd016be12016-03-13 11:24:20 -0600490
491 // hook it up
492 parseContext.handleFunctionArgument(function, arguments, arg);
493
John Kessenich078d7f22016-03-14 10:02:11 -0600494 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -0700495 if (! acceptTokenClass(EHTokComma))
496 break;
497 } while (true);
498
John Kessenich078d7f22016-03-14 10:02:11 -0600499 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700500 if (! acceptTokenClass(EHTokRightParen)) {
501 expected("right parenthesis");
502 return false;
503 }
504
505 return true;
506}
507
508bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
509{
510 switch (token.tokenClass) {
511 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600512 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700513 break;
514 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600515 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700516 break;
517 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600518 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700519 break;
520 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600521 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700522 break;
523
524 default:
525 return false;
526 }
527
528 advanceToken();
529
530 return true;
531}
532
John Kessenich5f934b02016-03-13 17:58:25 -0600533// operator
John Kessenich078d7f22016-03-14 10:02:11 -0600534// : PLUS | DASH | STAR | SLASH | ...
John Kessenich87142c72016-03-12 20:24:24 -0700535bool HlslGrammar::acceptOperator(TOperator& op)
536{
537 switch (token.tokenClass) {
John Kessenich5f934b02016-03-13 17:58:25 -0600538 case EHTokEqual:
539 op = EOpAssign;
540 break;
John Kessenich87142c72016-03-12 20:24:24 -0700541 case EHTokPlus:
542 op = EOpAdd;
543 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600544 case EHTokDash:
545 op = EOpSub;
546 break;
547 case EHTokStar:
548 op = EOpMul;
549 break;
550 case EHTokSlash:
551 op = EOpDiv;
552 break;
John Kessenich87142c72016-03-12 20:24:24 -0700553 default:
554 return false;
555 }
556
557 advanceToken();
558
559 return true;
560}
561
John Kessenich5f934b02016-03-13 17:58:25 -0600562// compound_statement
563// : { statement statement ... }
564//
565bool HlslGrammar::acceptCompoundStatement(TIntermAggregate*& compoundStatement)
John Kessenich87142c72016-03-12 20:24:24 -0700566{
John Kessenich5f934b02016-03-13 17:58:25 -0600567 // {
568 if (! acceptTokenClass(EHTokLeftBrace))
569 return false;
570
571 // statement statement ...
572 TIntermNode* statement = nullptr;
573 while (acceptStatement(statement)) {
574 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600575 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -0600576 }
577 compoundStatement->setOperator(EOpSequence);
578
579 // }
580 return acceptTokenClass(EHTokRightBrace);
581}
582
583// statement
584// : compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600585// | return SEMICOLON
586// | return expression SEMICOLON
587// | expression SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600588//
589bool HlslGrammar::acceptStatement(TIntermNode*& statement)
590{
591 // compound_statement
592 TIntermAggregate* compoundStatement = nullptr;
593 if (acceptCompoundStatement(compoundStatement)) {
594 statement = compoundStatement;
595 return true;
596 }
597
John Kessenich078d7f22016-03-14 10:02:11 -0600598 // RETURN
John Kessenich5f934b02016-03-13 17:58:25 -0600599 if (acceptTokenClass(EHTokReturn)) {
600 // expression
601 TIntermTyped* node;
602 if (acceptExpression(node)) {
603 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600604 statement = intermediate.addBranch(EOpReturn, node, token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600605 } else
John Kessenich078d7f22016-03-14 10:02:11 -0600606 statement = intermediate.addBranch(EOpReturn, token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600607
John Kessenich078d7f22016-03-14 10:02:11 -0600608 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600609 if (! acceptTokenClass(EHTokSemicolon))
610 return false;
611
612 return true;
613 }
614
615 // expression
616 TIntermTyped* node;
617 if (acceptExpression(node))
618 statement = node;
619
John Kessenich078d7f22016-03-14 10:02:11 -0600620 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600621 if (! acceptTokenClass(EHTokSemicolon))
622 return false;
623
624 return true;
John Kessenich87142c72016-03-12 20:24:24 -0700625}
626
John Kessenich078d7f22016-03-14 10:02:11 -0600627// COLON semantic
628bool HlslGrammar::acceptSemantic()
629{
630 // COLON
631 if (acceptTokenClass(EHTokColon)) {
632 // semantic
John Kessenichaecd4972016-03-14 10:46:34 -0600633 HlslToken idToken;
634 if (! acceptIdentifier(idToken)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600635 expected("semantic");
636 return false;
637 }
638 }
639
640 return true;
641}
642
John Kesseniche01a9bc2016-03-12 20:11:22 -0700643} // end namespace glslang