| 2792 | } |
| 2793 | |
| 2794 | bool HLSLParser::ParseBinaryExpression(int priority, HLSLExpression*& expression) |
| 2795 | { |
| 2796 | const char* fileName = GetFileName(); |
| 2797 | int line = GetLineNumber(); |
| 2798 | |
| 2799 | bool needsEndParen; |
| 2800 | |
| 2801 | if (!ParseTerminalExpression(expression, needsEndParen)) { |
| 2802 | return false; |
| 2803 | } |
| 2804 | |
| 2805 | // reset priority cause openned parenthesis |
| 2806 | if (needsEndParen) |
| 2807 | priority = 0; |
| 2808 | |
| 2809 | while (1) { |
| 2810 | HLSLBinaryOp binaryOp; |
| 2811 | if (AcceptBinaryOperator(priority, binaryOp)) { |
| 2812 | HLSLExpression* expression2 = NULL; |
| 2813 | ASSERT(binaryOp < sizeof(_binaryOpPriority) / sizeof(int)); |
| 2814 | if (!ParseBinaryExpression(_binaryOpPriority[binaryOp], expression2)) { |
| 2815 | return false; |
| 2816 | } |
| 2817 | HLSLBinaryExpression* binaryExpression = m_tree->AddNode<HLSLBinaryExpression>(fileName, line); |
| 2818 | binaryExpression->binaryOp = binaryOp; |
| 2819 | binaryExpression->expression1 = expression; |
| 2820 | binaryExpression->expression2 = expression2; |
| 2821 | if (!GetBinaryOpResultType(binaryOp, expression->expressionType, expression2->expressionType, binaryExpression->expressionType)) { |
| 2822 | const char* typeName1 = GetTypeNameHLSL(binaryExpression->expression1->expressionType); |
| 2823 | const char* typeName2 = GetTypeNameHLSL(binaryExpression->expression2->expressionType); |
| 2824 | m_tokenizer.Error("binary '%s' : no global operator found which takes types '%s' and '%s' (or there is no acceptable conversion)", |
| 2825 | GetBinaryOpName(binaryOp), typeName1, typeName2); |
| 2826 | |
| 2827 | return false; |
| 2828 | } |
| 2829 | |
| 2830 | // Propagate constness. |
| 2831 | binaryExpression->expressionType.flags = (expression->expressionType.flags | expression2->expressionType.flags) & HLSLTypeFlag_Const; |
| 2832 | |
| 2833 | expression = binaryExpression; |
| 2834 | } |
| 2835 | else if (_conditionalOpPriority > priority && Accept('?')) { |
| 2836 | HLSLConditionalExpression* conditionalExpression = m_tree->AddNode<HLSLConditionalExpression>(fileName, line); |
| 2837 | conditionalExpression->condition = expression; |
| 2838 | |
| 2839 | HLSLExpression* expression1 = NULL; |
| 2840 | HLSLExpression* expression2 = NULL; |
| 2841 | if (!ParseBinaryExpression(_conditionalOpPriority, expression1) || !Expect(':') || !ParseBinaryExpression(_conditionalOpPriority, expression2)) { |
| 2842 | return false; |
| 2843 | } |
| 2844 | |
| 2845 | // Make sure both cases have compatible types. |
| 2846 | if (GetTypeCastRank(m_tree, expression1->expressionType, expression2->expressionType) == -1) { |
| 2847 | const char* srcTypeName = GetTypeNameHLSL(expression2->expressionType); |
| 2848 | const char* dstTypeName = GetTypeNameHLSL(expression1->expressionType); |
| 2849 | m_tokenizer.Error("':' no possible conversion from from '%s' to '%s'", srcTypeName, dstTypeName); |
| 2850 | return false; |
| 2851 | } |
nothing calls this directly
no test coverage detected