diff --git a/src/mizugaki/parser/sql_driver.cpp b/src/mizugaki/parser/sql_driver.cpp index e66e4f0..f4ee9ee 100644 --- a/src/mizugaki/parser/sql_driver.cpp +++ b/src/mizugaki/parser/sql_driver.cpp @@ -9,6 +9,9 @@ #include #include +#include +#include +#include #include #include @@ -163,5 +166,42 @@ sql_driver::to_delimited_identifier(ast::common::chars const& str, location_type location); } +sql_driver::node_ptr +sql_driver::try_fold_literal(node_ptr expression) { + if (expression->node_kind() != ast::scalar::unary_expression::tag) { + return expression; + } + + auto&& unary = unsafe_downcast(*expression); + if (unary.operator_kind() != ast::scalar::unary_operator::plus && + unary.operator_kind() != ast::scalar::unary_operator::minus) { + return expression; + } + if (unary.operand()->node_kind() != ast::scalar::literal_expression::tag) { + return expression; + } + + auto&& literal = unsafe_downcast(*unary.operand()).value(); + if (literal->node_kind() != ast::literal::kind::exact_numeric && + literal->node_kind() != ast::literal::kind::approximate_numeric) { + return expression; + } + + // only set if the original literal does not have a sign + auto&& value = unsafe_downcast(*literal); + if (value.sign().has_value()) { + return expression; + } + + if (unary.operator_kind() == ast::scalar::unary_operator::plus) { + value.sign() = { ast::literal::sign::plus, unary.operator_kind().region() }; + } else { + value.sign() = { ast::literal::sign::minus, unary.operator_kind().region() }; + } + unary.operand()->region() = expression->region(); + + return std::move(unary.operand()); +} + } // namespace mizugaki::parser diff --git a/src/mizugaki/parser/sql_driver.h b/src/mizugaki/parser/sql_driver.h index 7267a65..33cb66d 100644 --- a/src/mizugaki/parser/sql_driver.h +++ b/src/mizugaki/parser/sql_driver.h @@ -2,7 +2,6 @@ #include - #include #include #include @@ -90,6 +89,8 @@ class sql_driver { [[nodiscard]] node_ptr try_build_type(node_ptr& expr); + [[nodiscard]] node_ptr try_fold_literal(node_ptr expression); + private: ::takatori::util::maybe_shared_ptr document_; std::vector comments_; diff --git a/src/mizugaki/parser/sql_parser.yy b/src/mizugaki/parser/sql_parser.yy index f457e5d..da5c47d 100644 --- a/src/mizugaki/parser/sql_parser.yy +++ b/src/mizugaki/parser/sql_parser.yy @@ -2839,17 +2839,19 @@ scalar_value_expression } | "+"[o] scalar_value_expression[e] %prec UNARY_PLUS { - $$ = driver.node( - regioned { ast::scalar::unary_operator::plus, @o }, - $e, - @$); + $$ = driver.try_fold_literal( + driver.node( + regioned { ast::scalar::unary_operator::plus, @o }, + $e, + @$)); } | "-"[o] scalar_value_expression[e] %prec UNARY_MINUS { - $$ = driver.node( - regioned { ast::scalar::unary_operator::minus, @o }, - $e, - @$); + $$ = driver.try_fold_literal( + driver.node( + regioned { ast::scalar::unary_operator::minus, @o }, + $e, + @$)); } // 6.28 -