diff --git a/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp index 12df8e50..79b094c3 100644 --- a/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp +++ b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp @@ -12,7 +12,7 @@ static constexpr int CAPTURE_FUNCTION_NAME = SimpleExpressionMatchers::CAPTURE_O MenuExpressionMatchers::MenuExpressionMatchers() - : SimpleExpressionMatchers(true, true, true, true) + : SimpleExpressionMatchers(true, true, true, true, true) { } diff --git a/src/Parser/Parsing/Impl/Defines/DefinesIfExpressionMatchers.cpp b/src/Parser/Parsing/Impl/Defines/DefinesIfExpressionMatchers.cpp index 7d6c9cb1..4dc24b3e 100644 --- a/src/Parser/Parsing/Impl/Defines/DefinesIfExpressionMatchers.cpp +++ b/src/Parser/Parsing/Impl/Defines/DefinesIfExpressionMatchers.cpp @@ -8,7 +8,7 @@ DefinesIfExpressionMatchers::DefinesIfExpressionMatchers() } DefinesIfExpressionMatchers::DefinesIfExpressionMatchers(const DefinesIfDirectiveParsingState* state) - : SimpleExpressionMatchers(false, false, true, true), + : SimpleExpressionMatchers(false, false, true, true, false), m_state(state) { } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp new file mode 100644 index 00000000..5fb7775c --- /dev/null +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.cpp @@ -0,0 +1,22 @@ +#include "SimpleExpressionConditionalOperator.h" + +SimpleExpressionConditionalOperator::SimpleExpressionConditionalOperator() += default; + +SimpleExpressionConditionalOperator::SimpleExpressionConditionalOperator(std::unique_ptr condition, std::unique_ptr trueExpression, + std::unique_ptr falseExpression) + : m_condition(std::move(condition)), + m_true_value(std::move(trueExpression)), + m_false_value(std::move(falseExpression)) +{ +} + +bool SimpleExpressionConditionalOperator::IsStatic() +{ + return m_condition->IsStatic() && m_true_value->IsStatic() && m_false_value->IsStatic(); +} + +SimpleExpressionValue SimpleExpressionConditionalOperator::Evaluate() +{ + return m_condition->Evaluate().IsTruthy() ? m_true_value->Evaluate() : m_false_value->Evaluate(); +} diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h new file mode 100644 index 00000000..fa472f0b --- /dev/null +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h @@ -0,0 +1,16 @@ +#pragma once +#include "ISimpleExpression.h" + +class SimpleExpressionConditionalOperator final : public ISimpleExpression +{ +public: + std::unique_ptr m_condition; + std::unique_ptr m_true_value; + std::unique_ptr m_false_value; + + bool IsStatic() override; + SimpleExpressionValue Evaluate() override; + + SimpleExpressionConditionalOperator(); + SimpleExpressionConditionalOperator(std::unique_ptr condition, std::unique_ptr trueExpression, std::unique_ptr falseExpression); +}; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp index 1b7a5855..1c87d2cf 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp @@ -2,6 +2,7 @@ #include +#include "SimpleExpressionConditionalOperator.h" #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" #include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h" #include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h" @@ -14,21 +15,26 @@ static constexpr int TAG_PARENTHESIS_END = SimpleExpressionMatchers::TAG_OFFSET_ static constexpr int TAG_BINARY_OPERATION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 6; static constexpr int TAG_OPERAND_EXT = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 7; static constexpr int TAG_OPERAND_EXT_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 8; +static constexpr int TAG_CONDITIONAL_OPERATOR = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 9; +static constexpr int TAG_CONDITIONAL_OPERATOR_SEPARATOR = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 10; +static constexpr int TAG_CONDITIONAL_OPERATOR_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 11; static constexpr int CAPTURE_OPERAND = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 1; static constexpr int CAPTURE_UNARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 2; static constexpr int CAPTURE_BINARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 3; SimpleExpressionMatchers::SimpleExpressionMatchers() - : SimpleExpressionMatchers(true, true, true, true) + : SimpleExpressionMatchers(true, true, true, true, false) { } -SimpleExpressionMatchers::SimpleExpressionMatchers(const bool enableStringOperands, const bool enableIdentifierOperands, const bool enableFloatingPointOperands, const bool enableIntOperands) +SimpleExpressionMatchers::SimpleExpressionMatchers(const bool enableStringOperands, const bool enableIdentifierOperands, const bool enableFloatingPointOperands, const bool enableIntOperands, + const bool enableConditionalOperator) : m_enable_string_operands(enableStringOperands), m_enable_identifier_operands(enableIdentifierOperands), m_enable_floating_point_operands(enableFloatingPointOperands), - m_enable_int_operands(enableIntOperands) + m_enable_int_operands(enableIntOperands), + m_enable_conditional_operator(enableConditionalOperator) { } @@ -76,6 +82,21 @@ std::unique_ptr SimpleExpressionMatchers::ProcessExpressionIn return processedEvaluation; } +std::unique_ptr SimpleExpressionMatchers::ProcessConditionalOperation(std::unique_ptr condition, SequenceResult& result) const +{ + auto trueExpression = ProcessExpression(result); + + if (result.PeekAndRemoveIfTag(TAG_CONDITIONAL_OPERATOR_SEPARATOR) != TAG_CONDITIONAL_OPERATOR_SEPARATOR) + throw ParsingException(TokenPos(), "Expected conditional separator tag @ ProcessConditionalOperation"); + + auto falseExpression = ProcessExpression(result); + + if (result.PeekAndRemoveIfTag(TAG_CONDITIONAL_OPERATOR_END) != TAG_CONDITIONAL_OPERATOR_END) + throw ParsingException(TokenPos(), "Expected conditional end tag @ ProcessConditionalOperation"); + + return std::make_unique(std::move(condition), std::move(trueExpression), std::move(falseExpression)); +} + std::unique_ptr SimpleExpressionMatchers::ProcessOperand(SequenceResult& result) const { const auto& operandToken = result.NextCapture(CAPTURE_OPERAND); @@ -149,6 +170,12 @@ std::unique_ptr SimpleExpressionMatchers::ProcessExpression(S std::move(firstStatementPart)); } + if (result.PeekAndRemoveIfTag(TAG_CONDITIONAL_OPERATOR) == TAG_CONDITIONAL_OPERATOR) + { + operands.emplace_back(ProcessConditionalOperation(std::move(firstStatementPart), result)); + break; + } + operands.emplace_back(std::move(firstStatementPart)); if (result.PeekAndRemoveIfTag(TAG_BINARY_OPERATION) == TAG_BINARY_OPERATION) @@ -270,25 +297,41 @@ std::unique_ptr SimpleExpressionMatchers::P { unaryOperationsMatchers.emplace_back( create.MultiChar(MULTI_TOKEN_OFFSET_UNARY + static_cast(enabledUnaryOperation->m_id)) - .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); - })); + .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); + })); } else if (!enabledUnaryOperation->m_syntax.empty()) { unaryOperationsMatchers.emplace_back( create.Char(enabledUnaryOperation->m_syntax[0]) - .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); - })); + .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); + })); } } return create.Or(std::move(unaryOperationsMatchers)).Tag(TAG_UNARY_OPERATION).Capture(CAPTURE_UNARY_OPERATION_TYPE); } +std::unique_ptr SimpleExpressionMatchers::ParseConditionalOperator(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + if (!m_enable_conditional_operator) + return create.False(); + + return create.And({ + create.Char('?').Tag(TAG_CONDITIONAL_OPERATOR), + create.Label(LABEL_EXPRESSION), + create.Char(':').Tag(TAG_CONDITIONAL_OPERATOR_SEPARATOR), + create.Label(LABEL_EXPRESSION), + create.True().Tag(TAG_CONDITIONAL_OPERATOR_END) + }); +} + std::unique_ptr SimpleExpressionMatchers::Expression(const supplier_t* labelSupplier) const { const SimpleMatcherFactory create(labelSupplier); @@ -308,9 +351,12 @@ std::unique_ptr SimpleExpressionMatchers::E }), ParseOperand(labelSupplier) }), - create.Optional(create.And({ - ParseBinaryOperationType(labelSupplier), - create.Label(LABEL_EXPRESSION) - }).Tag(TAG_BINARY_OPERATION)) + create.Optional(create.Or({ + ParseConditionalOperator(labelSupplier), + create.And({ + ParseBinaryOperationType(labelSupplier), + create.Label(LABEL_EXPRESSION) + }).Tag(TAG_BINARY_OPERATION) + })) }).Tag(TAG_EXPRESSION); } diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h index 29332cc8..edb98876 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h @@ -31,10 +31,11 @@ private: bool m_enable_identifier_operands; bool m_enable_floating_point_operands; bool m_enable_int_operands; + bool m_enable_conditional_operator; public: SimpleExpressionMatchers(); - SimpleExpressionMatchers(bool enableStringOperands, bool enableIdentifierOperands, bool enableFloatingPointOperands, bool enableIntOperands); + SimpleExpressionMatchers(bool enableStringOperands, bool enableIdentifierOperands, bool enableFloatingPointOperands, bool enableIntOperands, bool enableConditionalOperator); virtual ~SimpleExpressionMatchers(); SimpleExpressionMatchers(const SimpleExpressionMatchers& other) = default; SimpleExpressionMatchers(SimpleExpressionMatchers&& other) noexcept = default; @@ -52,8 +53,10 @@ private: std::unique_ptr ParseBinaryOperationType(const supplier_t* labelSupplier) const; std::unique_ptr ParseOperand(const supplier_t* labelSupplier) const; std::unique_ptr ParseUnaryOperationType(const supplier_t* labelSupplier) const; + std::unique_ptr ParseConditionalOperator(const supplier_t* labelSupplier) const; std::unique_ptr ProcessExpressionInParenthesis(SequenceResult& result) const; + std::unique_ptr ProcessConditionalOperation(std::unique_ptr condition, SequenceResult& result) const; std::unique_ptr ProcessOperand(SequenceResult& result) const; public: diff --git a/test/ParserTests/Parsing/Simple/SimpleExpressionTests.cpp b/test/ParserTests/Parsing/Simple/SimpleExpressionTests.cpp index eab155f0..ce35b69a 100644 --- a/test/ParserTests/Parsing/Simple/SimpleExpressionTests.cpp +++ b/test/ParserTests/Parsing/Simple/SimpleExpressionTests.cpp @@ -22,7 +22,7 @@ namespace test::parsing::simple::expression public: SimpleExpressionSequence() - : m_expression_matchers(true, true, true, true) + : m_expression_matchers(true, true, true, true, true) { const SimpleMatcherFactory create(this); @@ -72,7 +72,7 @@ namespace test::parsing::simple::expression return m_sequence->MatchSequence(m_lexer.get(), m_state.get(), m_consumed_token_count); } }; - + TEST_CASE("SimpleExpressions: Can parse expression with add operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -96,7 +96,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1337); } - + TEST_CASE("SimpleExpressions: Can parse expression with subtract operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -120,7 +120,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } - + TEST_CASE("SimpleExpressions: Can parse expression with multiply operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -144,7 +144,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } - + TEST_CASE("SimpleExpressions: Can parse expression with divide operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -168,7 +168,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1337); } - + TEST_CASE("SimpleExpressions: Can parse expression with remainder operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -192,7 +192,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } - + TEST_CASE("SimpleExpressions: Can parse expression with bitwise and operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -216,7 +216,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 0x2AAAAAA0); } - + TEST_CASE("SimpleExpressions: Can parse expression with bitwise or operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -240,7 +240,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 7); } - + TEST_CASE("SimpleExpressions: Can parse expression with shift left operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -264,7 +264,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } - + TEST_CASE("SimpleExpressions: Can parse expression with shift right operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -288,7 +288,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1337); } - + TEST_CASE("SimpleExpressions: Can parse expression with greater operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -312,7 +312,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1); } - + TEST_CASE("SimpleExpressions: Can parse expression with greater equal operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -336,7 +336,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1); } - + TEST_CASE("SimpleExpressions: Can parse expression with less operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -360,7 +360,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1); } - + TEST_CASE("SimpleExpressions: Can parse expression with less equal operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -384,7 +384,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1); } - + TEST_CASE("SimpleExpressions: Can parse expression with equals operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -408,7 +408,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 1); } - + TEST_CASE("SimpleExpressions: Can parse expression with not equal operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -432,7 +432,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 0); } - + TEST_CASE("SimpleExpressions: Can parse expression with and operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -456,7 +456,7 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } - + TEST_CASE("SimpleExpressions: Can parse expression with or operation", "[parsing][simple][expression]") { SimpleExpressionTestsHelper helper; @@ -494,7 +494,7 @@ namespace test::parsing::simple::expression SimpleParserValue::Character(pos, '+'), SimpleParserValue::Integer(pos, 220), SimpleParserValue::EndOfFile(pos) - }); + }); const auto result = helper.PerformTest(); @@ -522,7 +522,7 @@ namespace test::parsing::simple::expression SimpleParserValue::Character(pos, '*'), SimpleParserValue::Integer(pos, 10), SimpleParserValue::EndOfFile(pos) - }); + }); const auto result = helper.PerformTest(); @@ -536,4 +536,206 @@ namespace test::parsing::simple::expression REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); REQUIRE(value.m_int_value == 420); } + + TEST_CASE("SimpleExpressions: Simple conditional operator can be used with true value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 5); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 420); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can be used with false value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Integer(pos, 0), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 5); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 1337); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can be used within parenthesis with true value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Character(pos, '('), + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 9); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 421); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can be used within parenthesis with false value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Character(pos, '('), + SimpleParserValue::Integer(pos, 0), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 9); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 1338); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can have an expression as condition", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Character(pos, '('), + SimpleParserValue::Integer(pos, -1), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::Integer(pos, 2), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 9); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 420); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can have an expression as true value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::Integer(pos, 210), + SimpleParserValue::Character(pos, '*'), + SimpleParserValue::Integer(pos, 2), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Integer(pos, 1337), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 9); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 420); + } + + TEST_CASE("SimpleExpressions: Simple conditional operator can have an expression as false value", "[parsing][simple][expression]") + { + SimpleExpressionTestsHelper helper; + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Integer(pos, 0), + SimpleParserValue::Character(pos, '?'), + SimpleParserValue::Integer(pos, 420), + SimpleParserValue::Character(pos, ':'), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::Integer(pos, 1336), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::EndOfFile(pos) + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 9); + + const auto& expression = helper.m_state->m_expression; + REQUIRE(expression->IsStatic()); + + const auto value = expression->Evaluate(); + REQUIRE(value.m_type == SimpleExpressionValue::Type::INT); + REQUIRE(value.m_int_value == 1337); + } }