From 4ba33f03a0c98b00818f2598f155f6910adc3a5c Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 24 Dec 2023 01:01:17 +0100 Subject: [PATCH] Support comma in brackets and braces in preprocessor args --- .../Parsing/Impl/DefinesStreamProxy.cpp | 19 ++++++++-- .../Parsing/Impl/DefinesStreamProxyTests.cpp | 38 +++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index ac3417b38..0f955803e 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -510,10 +510,10 @@ void DefinesStreamProxy::ContinueMacroParameters(const ParserLine& line, unsigne m_macro_parameter_state = ParameterState::AFTER_COMMA; } } - else if (c == '(') + else if (c == '(' || c == '[' || c == '{') { m_macro_parameter_state = ParameterState::AFTER_PARAM; - m_macro_bracket_depth.push('('); + m_macro_bracket_depth.push(c); m_current_macro_parameter << c; } else if (c == ')') @@ -523,8 +523,8 @@ void DefinesStreamProxy::ContinueMacroParameters(const ParserLine& line, unsigne if (m_macro_bracket_depth.top() != '(') throw ParsingException(CreatePos(line, pos), "Unbalanced brackets in macro parameters"); - m_macro_parameter_state = ParameterState::AFTER_PARAM; m_macro_bracket_depth.pop(); + m_macro_parameter_state = ParameterState::AFTER_PARAM; m_current_macro_parameter << c; } else if (m_macro_parameter_state == ParameterState::AFTER_COMMA) @@ -537,6 +537,19 @@ void DefinesStreamProxy::ContinueMacroParameters(const ParserLine& line, unsigne m_macro_parameter_state = ParameterState::NOT_IN_PARAMETERS; } } + else if (c == ']' || c == '}') + { + if (!m_macro_bracket_depth.empty()) + { + const auto otherBracket = c == ']' ? '[' : '{'; + if (m_macro_bracket_depth.top() != otherBracket) + throw ParsingException(CreatePos(line, pos), "Unbalanced brackets in macro parameters"); + m_macro_bracket_depth.pop(); + } + + m_macro_parameter_state = ParameterState::AFTER_PARAM; + m_current_macro_parameter << c; + } else if (m_macro_parameter_state == ParameterState::AFTER_PARAM || !isspace(c)) { m_macro_parameter_state = ParameterState::AFTER_PARAM; diff --git a/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp b/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp index 36b6160e0..6ca696363 100644 --- a/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp +++ b/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp @@ -729,6 +729,44 @@ namespace test::parsing::impl::defines_stream_proxy REQUIRE(proxy.Eof()); } + TEST_CASE("DefinesStreamProxy: Ensure throws error on unclosed parenthesis in params", "[parsing][parsingstream]") + { + const std::vector lines{ + "#define someStuff(param1) Hello param1 World", + "someStuff(A sentence with [brackets and a , character and stuff)", + "someStuff(A sentence with {braces and a , character and stuff)", + }; + + MockParserLineStream mockStream(lines); + DefinesStreamProxy proxy(&mockStream); + + ExpectLine(&proxy, 1, ""); + ExpectErrorInLine(&proxy, 2, 64); + ExpectErrorInLine(&proxy, 3, 62); + + REQUIRE(proxy.Eof()); + } + + TEST_CASE("DefinesStreamProxy: Ensure throws error on parenthesis in params closed with wrong equivalent", "[parsing][parsingstream]") + { + const std::vector lines{ + "#define someStuff(param1) Hello param1 World", + "someStuff(A sentence with (parenthesis and a , character] and stuff)", + "someStuff(A sentence with [brackets and a , character} and stuff)", + "someStuff(A sentence with {braces and a , character) and stuff)", + }; + + MockParserLineStream mockStream(lines); + DefinesStreamProxy proxy(&mockStream); + + ExpectLine(&proxy, 1, ""); + ExpectErrorInLine(&proxy, 2, 57); + ExpectErrorInLine(&proxy, 3, 54); + ExpectErrorInLine(&proxy, 4, 52); + + REQUIRE(proxy.Eof()); + } + TEST_CASE("DefinesStreamProxy: Ensure defines can go over multiple lines", "[parsing][parsingstream]") { const std::vector lines{