// 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; }
// 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); }