blob: 40c35cae868d7fe76fedaf9ca7aaf33b75dc7f75 [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;
132 if (acceptTokenClass(EHTokEqual)) {
133 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{
212 if (! token.isType)
213 return false;
214
John Kessenich9c86c6a2016-05-03 22:49:24 -0600215 switch (peek()) {
John Kessenich87142c72016-03-12 20:24:24 -0700216 case EHTokInt:
217 case EHTokInt1:
218 case EHTokDword:
219 new(&type) TType(EbtInt);
220 break;
221 case EHTokFloat:
222 case EHTokFloat1:
223 new(&type) TType(EbtFloat);
224 break;
225
226 case EHTokFloat2:
227 new(&type) TType(EbtFloat, EvqTemporary, 2);
228 break;
229 case EHTokFloat3:
230 new(&type) TType(EbtFloat, EvqTemporary, 3);
231 break;
232 case EHTokFloat4:
233 new(&type) TType(EbtFloat, EvqTemporary, 4);
234 break;
235
236 case EHTokInt2:
237 new(&type) TType(EbtInt, EvqTemporary, 2);
238 break;
239 case EHTokInt3:
240 new(&type) TType(EbtInt, EvqTemporary, 3);
241 break;
242 case EHTokInt4:
243 new(&type) TType(EbtInt, EvqTemporary, 4);
244 break;
245
246 case EHTokBool2:
247 new(&type) TType(EbtBool, EvqTemporary, 2);
248 break;
249 case EHTokBool3:
250 new(&type) TType(EbtBool, EvqTemporary, 3);
251 break;
252 case EHTokBool4:
253 new(&type) TType(EbtBool, EvqTemporary, 4);
254 break;
255
256 case EHTokFloat2x2:
257 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
258 break;
259 case EHTokFloat2x3:
260 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
261 break;
262 case EHTokFloat2x4:
263 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
264 break;
265 case EHTokFloat3x2:
266 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
267 break;
268 case EHTokFloat3x3:
269 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
270 break;
271 case EHTokFloat3x4:
272 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
273 break;
274 case EHTokFloat4x2:
275 new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
276 break;
277 case EHTokFloat4x3:
278 new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
279 break;
280 case EHTokFloat4x4:
281 new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
282 break;
283
284 default:
285 return false;
286 }
287
288 advanceToken();
289
290 return true;
291}
292
John Kessenich5f934b02016-03-13 17:58:25 -0600293// function_parameters
John Kessenich078d7f22016-03-14 10:02:11 -0600294// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600295//
296bool HlslGrammar::acceptFunctionParameters(TFunction& function)
297{
John Kessenich078d7f22016-03-14 10:02:11 -0600298 // LEFT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600299 if (! acceptTokenClass(EHTokLeftParen))
300 return false;
301
302 do {
303 // parameter_declaration
304 if (! acceptParameterDeclaration(function))
305 break;
306
John Kessenich078d7f22016-03-14 10:02:11 -0600307 // COMMA
John Kessenich5f934b02016-03-13 17:58:25 -0600308 if (! acceptTokenClass(EHTokComma))
309 break;
310 } while (true);
311
John Kessenich078d7f22016-03-14 10:02:11 -0600312 // RIGHT_PAREN
John Kessenich5f934b02016-03-13 17:58:25 -0600313 if (! acceptTokenClass(EHTokRightParen)) {
314 expected("right parenthesis");
315 return false;
316 }
317
318 return true;
319}
320
321// parameter_declaration
322// : fully_specified_type
323// | fully_specified_type identifier
324//
325bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
326{
327 // fully_specified_type
328 TType* type = new TType;
329 if (! acceptFullySpecifiedType(*type))
330 return false;
331
332 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600333 HlslToken idToken;
334 acceptIdentifier(idToken);
John Kessenich5f934b02016-03-13 17:58:25 -0600335
John Kessenichaecd4972016-03-14 10:46:34 -0600336 TParameter param = { idToken.string, type };
John Kessenich5f934b02016-03-13 17:58:25 -0600337 function.addParameter(param);
338
339 return true;
340}
341
342// Do the work to create the function definition in addition to
343// parsing the body (compound_statement).
344bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node)
345{
346 TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
347
348 // This does a symbol table push
349 node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator);
350
351 // compound_statement
352 TIntermAggregate* functionBody = nullptr;
353 if (acceptCompoundStatement(functionBody)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600354 node = intermediate.growAggregate(node, functionBody);
355 intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600356 node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str());
357 parseContext.symbolTable.pop(nullptr);
358
359 return true;
360 }
361
362 return false;
363}
364
John Kessenich87142c72016-03-12 20:24:24 -0700365// expression
366// : identifier
John Kessenich078d7f22016-03-14 10:02:11 -0600367// | identifier operator identifier // todo: generalize to all expressions
368// | LEFT_PAREN expression RIGHT_PAREN
369// | constructor
John Kessenich87142c72016-03-12 20:24:24 -0700370// | literal
John Kessenich87142c72016-03-12 20:24:24 -0700371//
372bool HlslGrammar::acceptExpression(TIntermTyped*& node)
373{
374 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600375 HlslToken idToken;
376 if (acceptIdentifier(idToken)) {
377 TIntermTyped* left = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich5f934b02016-03-13 17:58:25 -0600378
379 // operator?
380 TOperator op;
381 if (! acceptOperator(op))
382 return true;
383 TSourceLoc loc = token.loc;
384
385 // identifier
John Kessenichaecd4972016-03-14 10:46:34 -0600386 if (acceptIdentifier(idToken)) {
387 TIntermTyped* right = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
John Kessenich078d7f22016-03-14 10:02:11 -0600388 node = intermediate.addBinaryMath(op, left, right, loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600389 return true;
390 }
391
392 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700393 }
394
John Kessenich078d7f22016-03-14 10:02:11 -0600395 // LEFT_PAREN expression RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700396 if (acceptTokenClass(EHTokLeftParen)) {
397 if (! acceptExpression(node)) {
398 expected("expression");
399 return false;
400 }
401 if (! acceptTokenClass(EHTokRightParen)) {
402 expected("right parenthesis");
403 return false;
404 }
405
406 return true;
407 }
408
409 // literal
410 if (acceptLiteral(node))
411 return true;
412
John Kessenich078d7f22016-03-14 10:02:11 -0600413 // constructor
John Kessenichd016be12016-03-13 11:24:20 -0600414 if (acceptConstructor(node))
John Kessenich87142c72016-03-12 20:24:24 -0700415 return true;
John Kessenich87142c72016-03-12 20:24:24 -0700416
John Kessenich5f934b02016-03-13 17:58:25 -0600417 return false;
John Kessenich87142c72016-03-12 20:24:24 -0700418}
419
John Kessenichd016be12016-03-13 11:24:20 -0600420// constructor
John Kessenich078d7f22016-03-14 10:02:11 -0600421// : type argument_list
John Kessenichd016be12016-03-13 11:24:20 -0600422//
423bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
424{
425 // type
426 TType type;
427 if (acceptType(type)) {
428 TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
429 if (constructorFunction == nullptr)
430 return false;
431
432 // arguments
433 TIntermAggregate* arguments = nullptr;
434 if (! acceptArguments(constructorFunction, arguments)) {
435 expected("constructor arguments");
436 return false;
437 }
438
439 // hook it up
440 node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
441
442 return true;
443 }
444
445 return false;
446}
447
John Kessenich87142c72016-03-12 20:24:24 -0700448// arguments
John Kessenich078d7f22016-03-14 10:02:11 -0600449// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700450//
John Kessenichd016be12016-03-13 11:24:20 -0600451// The arguments are pushed onto the 'function' argument list and
452// onto the 'arguments' aggregate.
453//
454bool HlslGrammar::acceptArguments(TFunction* function, TIntermAggregate*& arguments)
John Kessenich87142c72016-03-12 20:24:24 -0700455{
John Kessenich078d7f22016-03-14 10:02:11 -0600456 // LEFT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700457 if (! acceptTokenClass(EHTokLeftParen))
458 return false;
459
460 do {
John Kessenichd016be12016-03-13 11:24:20 -0600461 // expression
John Kessenich87142c72016-03-12 20:24:24 -0700462 TIntermTyped* arg;
463 if (! acceptExpression(arg))
464 break;
John Kessenichd016be12016-03-13 11:24:20 -0600465
466 // hook it up
467 parseContext.handleFunctionArgument(function, arguments, arg);
468
John Kessenich078d7f22016-03-14 10:02:11 -0600469 // COMMA
John Kessenich87142c72016-03-12 20:24:24 -0700470 if (! acceptTokenClass(EHTokComma))
471 break;
472 } while (true);
473
John Kessenich078d7f22016-03-14 10:02:11 -0600474 // RIGHT_PAREN
John Kessenich87142c72016-03-12 20:24:24 -0700475 if (! acceptTokenClass(EHTokRightParen)) {
476 expected("right parenthesis");
477 return false;
478 }
479
480 return true;
481}
482
483bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
484{
485 switch (token.tokenClass) {
486 case EHTokIntConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600487 node = intermediate.addConstantUnion(token.i, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700488 break;
489 case EHTokFloatConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600490 node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700491 break;
492 case EHTokDoubleConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600493 node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700494 break;
495 case EHTokBoolConstant:
John Kessenich078d7f22016-03-14 10:02:11 -0600496 node = intermediate.addConstantUnion(token.b, token.loc, true);
John Kessenich87142c72016-03-12 20:24:24 -0700497 break;
498
499 default:
500 return false;
501 }
502
503 advanceToken();
504
505 return true;
506}
507
John Kessenich5f934b02016-03-13 17:58:25 -0600508// operator
John Kessenich078d7f22016-03-14 10:02:11 -0600509// : PLUS | DASH | STAR | SLASH | ...
John Kessenich87142c72016-03-12 20:24:24 -0700510bool HlslGrammar::acceptOperator(TOperator& op)
511{
512 switch (token.tokenClass) {
John Kessenich5f934b02016-03-13 17:58:25 -0600513 case EHTokEqual:
514 op = EOpAssign;
515 break;
John Kessenich87142c72016-03-12 20:24:24 -0700516 case EHTokPlus:
517 op = EOpAdd;
518 break;
John Kessenich5f934b02016-03-13 17:58:25 -0600519 case EHTokDash:
520 op = EOpSub;
521 break;
522 case EHTokStar:
523 op = EOpMul;
524 break;
525 case EHTokSlash:
526 op = EOpDiv;
527 break;
John Kessenich87142c72016-03-12 20:24:24 -0700528 default:
529 return false;
530 }
531
532 advanceToken();
533
534 return true;
535}
536
John Kessenich5f934b02016-03-13 17:58:25 -0600537// compound_statement
538// : { statement statement ... }
539//
540bool HlslGrammar::acceptCompoundStatement(TIntermAggregate*& compoundStatement)
John Kessenich87142c72016-03-12 20:24:24 -0700541{
John Kessenich5f934b02016-03-13 17:58:25 -0600542 // {
543 if (! acceptTokenClass(EHTokLeftBrace))
544 return false;
545
546 // statement statement ...
547 TIntermNode* statement = nullptr;
548 while (acceptStatement(statement)) {
549 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600550 compoundStatement = intermediate.growAggregate(compoundStatement, statement);
John Kessenich5f934b02016-03-13 17:58:25 -0600551 }
552 compoundStatement->setOperator(EOpSequence);
553
554 // }
555 return acceptTokenClass(EHTokRightBrace);
556}
557
558// statement
559// : compound_statement
John Kessenich078d7f22016-03-14 10:02:11 -0600560// | return SEMICOLON
561// | return expression SEMICOLON
562// | expression SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600563//
564bool HlslGrammar::acceptStatement(TIntermNode*& statement)
565{
566 // compound_statement
567 TIntermAggregate* compoundStatement = nullptr;
568 if (acceptCompoundStatement(compoundStatement)) {
569 statement = compoundStatement;
570 return true;
571 }
572
John Kessenich078d7f22016-03-14 10:02:11 -0600573 // RETURN
John Kessenich5f934b02016-03-13 17:58:25 -0600574 if (acceptTokenClass(EHTokReturn)) {
575 // expression
576 TIntermTyped* node;
577 if (acceptExpression(node)) {
578 // hook it up
John Kessenich078d7f22016-03-14 10:02:11 -0600579 statement = intermediate.addBranch(EOpReturn, node, token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600580 } else
John Kessenich078d7f22016-03-14 10:02:11 -0600581 statement = intermediate.addBranch(EOpReturn, token.loc);
John Kessenich5f934b02016-03-13 17:58:25 -0600582
John Kessenich078d7f22016-03-14 10:02:11 -0600583 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600584 if (! acceptTokenClass(EHTokSemicolon))
585 return false;
586
587 return true;
588 }
589
590 // expression
591 TIntermTyped* node;
592 if (acceptExpression(node))
593 statement = node;
594
John Kessenich078d7f22016-03-14 10:02:11 -0600595 // SEMICOLON
John Kessenich5f934b02016-03-13 17:58:25 -0600596 if (! acceptTokenClass(EHTokSemicolon))
597 return false;
598
599 return true;
John Kessenich87142c72016-03-12 20:24:24 -0700600}
601
John Kessenich078d7f22016-03-14 10:02:11 -0600602// COLON semantic
603bool HlslGrammar::acceptSemantic()
604{
605 // COLON
606 if (acceptTokenClass(EHTokColon)) {
607 // semantic
John Kessenichaecd4972016-03-14 10:46:34 -0600608 HlslToken idToken;
609 if (! acceptIdentifier(idToken)) {
John Kessenich078d7f22016-03-14 10:02:11 -0600610 expected("semantic");
611 return false;
612 }
613 }
614
615 return true;
616}
617
John Kesseniche01a9bc2016-03-12 20:11:22 -0700618} // end namespace glslang