diff --git a/tests/libprojectM/CMakeLists.txt b/tests/libprojectM/CMakeLists.txt index 016a15a9d..70f7e88f1 100644 --- a/tests/libprojectM/CMakeLists.txt +++ b/tests/libprojectM/CMakeLists.txt @@ -27,6 +27,7 @@ test_api_headers(TestMainAPIHeaders ) add_executable(projectM-unittest + HLSLParserTest.cpp LoggingTest.cpp PresetFileParserTest.cpp WaveformAlignerTest.cpp @@ -50,6 +51,7 @@ target_include_directories(projectM-unittest PRIVATE "${PROJECTM_SOURCE_DIR}/src/libprojectM" "${PROJECTM_SOURCE_DIR}" + "${PROJECTM_SOURCE_DIR}/vendor/hlslparser/src" ) target_link_libraries(projectM-unittest diff --git a/tests/libprojectM/HLSLParserTest.cpp b/tests/libprojectM/HLSLParserTest.cpp new file mode 100644 index 000000000..228a7e51c --- /dev/null +++ b/tests/libprojectM/HLSLParserTest.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include + +#include + +namespace { + +bool ParseHLSL(const char* code) +{ + M4::Allocator allocator; + M4::HLSLTree tree(&allocator); + M4::HLSLParser parser(&allocator, &tree); + return parser.Parse("test.hlsl", code, strlen(code)); +} + +} // namespace + +// Regression test for issue #940: parenthesized constructor with binary operator +// was rejected with "expected ';'" error. +TEST(HLSLParser, ParenthesizedConstructorWithMultiply) +{ + EXPECT_TRUE(ParseHLSL( + "float scalar = 2.0;\n" + "float2 var = (float2(1.0, 2.0)) * scalar;\n" + )); +} + +TEST(HLSLParser, ParenthesizedConstructorWithAdd) +{ + EXPECT_TRUE(ParseHLSL( + "float2 var = (float2(1.0, 2.0)) + float2(3.0, 4.0);\n" + )); +} + +TEST(HLSLParser, DoubleNestedParensWithOperator) +{ + EXPECT_TRUE(ParseHLSL( + "float2 var = ((float2(1.0, 2.0))) * 2.0;\n" + )); +} + +TEST(HLSLParser, BothOperandsParenthesized) +{ + EXPECT_TRUE(ParseHLSL( + "float2 var = (float2(1.0, 2.0)) * (float2(3.0, 4.0));\n" + )); +} + +TEST(HLSLParser, ChainedOperatorsAfterParens) +{ + EXPECT_TRUE(ParseHLSL( + "float a = 1.0; float b = 2.0; float c = 3.0;\n" + "float x = (a) * b + c;\n" + )); +} + +TEST(HLSLParser, ConstructorWithoutParensStillWorks) +{ + EXPECT_TRUE(ParseHLSL( + "float2 var = float2(1.0, 2.0) * 2.0;\n" + )); +} diff --git a/vendor/hlslparser/src/HLSLParser.cpp b/vendor/hlslparser/src/HLSLParser.cpp index aaf73007c..6b798d561 100644 --- a/vendor/hlslparser/src/HLSLParser.cpp +++ b/vendor/hlslparser/src/HLSLParser.cpp @@ -2283,6 +2283,20 @@ bool HLSLParser::ParseBinaryExpression(int priority, HLSLExpression*& expression } else { + // Before breaking, consume end char if needed and check for more operators + if( needsExpressionEndChar != 0 ) + { + if( !Expect(needsExpressionEndChar) ) + return false; + needsExpressionEndChar = 0; + + // After consuming end char, check if there's a binary operator to continue + if (AcceptBinaryOperator(priority, binaryOp)) + { + acceptBinaryOp = true; + continue; + } + } break; }