// arguments // : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN // // The arguments are pushed onto the 'function' argument list and // onto the 'arguments' aggregate. // bool HlslGrammar::acceptArguments(TFunction* function, TIntermAggregate*& arguments) { // LEFT_PAREN if (! acceptTokenClass(EHTokLeftParen)) return false; do { // expression TIntermTyped* arg; if (! acceptExpression(arg)) break; // hook it up parseContext.handleFunctionArgument(function, arguments, arg); // COMMA if (! acceptTokenClass(EHTokComma)) break; } while (true); // RIGHT_PAREN if (! acceptTokenClass(EHTokRightParen)) { expected("right parenthesis"); return false; } return true; }
// declaration // : SEMICOLON // : fully_specified_type SEMICOLON // | fully_specified_type identifier SEMICOLON // | fully_specified_type identifier = expression SEMICOLON // | fully_specified_type identifier function_parameters SEMICOLON // function prototype // | fully_specified_type identifier function_parameters COLON semantic compound_statement // function definition // // 'node' could get created if the declaration creates code, like an initializer // or a function body. // bool HlslGrammar::acceptDeclaration(TIntermNode*& node) { node = nullptr; // fully_specified_type TType type; if (! acceptFullySpecifiedType(type)) return false; // identifier HlslToken idToken; if (acceptIdentifier(idToken)) { // = expression TIntermTyped* expressionNode = nullptr; if (acceptTokenClass(EHTokEqual)) { if (! acceptExpression(expressionNode)) { expected("initializer"); return false; } } // SEMICOLON if (acceptTokenClass(EHTokSemicolon)) { node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode); return true; } // function_parameters TFunction* function = new TFunction(idToken.string, type); if (acceptFunctionParameters(*function)) { // COLON semantic acceptSemantic(); // compound_statement if (peekTokenClass(EHTokLeftBrace)) return acceptFunctionDefinition(*function, node); // SEMICOLON if (acceptTokenClass(EHTokSemicolon)) return true; return false; } } // SEMICOLON if (acceptTokenClass(EHTokSemicolon)) return true; return true; }
// expression // : identifier // | identifier operator identifier // todo: generalize to all expressions // | LEFT_PAREN expression RIGHT_PAREN // | constructor // | literal // bool HlslGrammar::acceptExpression(TIntermTyped*& node) { // identifier HlslToken idToken; if (acceptIdentifier(idToken)) { TIntermTyped* left = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string); // operator? TOperator op; if (! acceptOperator(op)) return true; TSourceLoc loc = token.loc; // identifier if (acceptIdentifier(idToken)) { TIntermTyped* right = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string); node = intermediate.addBinaryMath(op, left, right, loc); return true; } return false; } // LEFT_PAREN expression RIGHT_PAREN if (acceptTokenClass(EHTokLeftParen)) { if (! acceptExpression(node)) { expected("expression"); return false; } if (! acceptTokenClass(EHTokRightParen)) { expected("right parenthesis"); return false; } return true; } // literal if (acceptLiteral(node)) return true; // constructor if (acceptConstructor(node)) return true; return false; }
// compound_statement // : { statement statement ... } // bool HlslGrammar::acceptCompoundStatement(TIntermAggregate*& compoundStatement) { // { if (! acceptTokenClass(EHTokLeftBrace)) return false; // statement statement ... TIntermNode* statement = nullptr; while (acceptStatement(statement)) { // hook it up compoundStatement = intermediate.growAggregate(compoundStatement, statement); } compoundStatement->setOperator(EOpSequence); // } return acceptTokenClass(EHTokRightBrace); }
// COLON semantic bool HlslGrammar::acceptSemantic() { // COLON if (acceptTokenClass(EHTokColon)) { // semantic HlslToken idToken; if (! acceptIdentifier(idToken)) { expected("semantic"); return false; } } return true; }
// statement // : compound_statement // | return SEMICOLON // | return expression SEMICOLON // | expression SEMICOLON // bool HlslGrammar::acceptStatement(TIntermNode*& statement) { // compound_statement TIntermAggregate* compoundStatement = nullptr; if (acceptCompoundStatement(compoundStatement)) { statement = compoundStatement; return true; } // RETURN if (acceptTokenClass(EHTokReturn)) { // expression TIntermTyped* node; if (acceptExpression(node)) { // hook it up statement = intermediate.addBranch(EOpReturn, node, token.loc); } else statement = intermediate.addBranch(EOpReturn, token.loc); // SEMICOLON if (! acceptTokenClass(EHTokSemicolon)) return false; return true; } // expression TIntermTyped* node; if (acceptExpression(node)) statement = node; // SEMICOLON if (! acceptTokenClass(EHTokSemicolon)) return false; return true; }
// function_parameters // : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN // bool HlslGrammar::acceptFunctionParameters(TFunction& function) { // LEFT_PAREN if (! acceptTokenClass(EHTokLeftParen)) return false; do { // parameter_declaration if (! acceptParameterDeclaration(function)) break; // COMMA if (! acceptTokenClass(EHTokComma)) break; } while (true); // RIGHT_PAREN if (! acceptTokenClass(EHTokRightParen)) { expected("right parenthesis"); return false; } return true; }
// postfix_expression // : LEFT_PAREN expression RIGHT_PAREN // | literal // | constructor // | identifier // | function_call // | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET // | postfix_expression DOT IDENTIFIER // | postfix_expression INC_OP // | postfix_expression DEC_OP // bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) { // Not implemented as self-recursive: // The logical "right recursion" is done with an loop at the end // idToken will pick up either a variable or a function name in a function call HlslToken idToken; // LEFT_PAREN expression RIGHT_PAREN if (acceptTokenClass(EHTokLeftParen)) { if (! acceptExpression(node)) { expected("expression"); return false; } if (! acceptTokenClass(EHTokRightParen)) { expected("right parenthesis"); return false; } } else if (acceptLiteral(node)) { // literal (nothing else to do yet), go on to the } else if (acceptConstructor(node)) { // constructor (nothing else to do yet) } else if (acceptIdentifier(idToken)) { // identifier or function_call name if (! peekTokenClass(EHTokLeftParen)) { node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string); } else if (acceptFunctionCall(idToken, node)) { // function_call (nothing else to do yet) } else { expected("function call arguments"); return false; } } do { TSourceLoc loc = token.loc; TOperator postOp = HlslOpMap::postUnary(peek()); // Consume only a valid post-unary operator, otherwise we are done. switch (postOp) { case EOpIndexDirectStruct: case EOpIndexIndirect: case EOpPostIncrement: case EOpPostDecrement: advanceToken(); break; default: return true; } // We have a valid post-unary operator, process it. switch (postOp) { case EOpIndexDirectStruct: // todo break; case EOpIndexIndirect: { TIntermTyped* indexNode = nullptr; if (! acceptExpression(indexNode) || ! peekTokenClass(EHTokRightBracket)) { expected("expression followed by ']'"); return false; } // todo: node = intermediate.addBinaryMath( } case EOpPostIncrement: case EOpPostDecrement: node = intermediate.addUnaryMath(postOp, node, loc); break; default: assert(0); break; } } while (true); }