Skip to content

Commit

Permalink
feat: parser now folds numeric literal signs.
Browse files Browse the repository at this point in the history
  • Loading branch information
ashigeru committed Jul 3, 2024
1 parent 7a8134d commit 0a31789
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 18 deletions.
40 changes: 40 additions & 0 deletions src/mizugaki/parser/sql_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

#include <mizugaki/ast/name/qualified.h>
#include <mizugaki/ast/type/user_defined.h>
#include <mizugaki/ast/literal/numeric.h>
#include <mizugaki/ast/scalar/literal_expression.h>
#include <mizugaki/ast/scalar/unary_expression.h>
#include <mizugaki/ast/scalar/variable_reference.h>
#include <mizugaki/ast/scalar/builtin_function_invocation.h>

Expand Down Expand Up @@ -163,5 +166,42 @@ sql_driver::to_delimited_identifier(ast::common::chars const& str, location_type
location);
}

sql_driver::node_ptr<ast::scalar::expression>
sql_driver::try_fold_literal(node_ptr<ast::scalar::expression> expression) {
if (expression->node_kind() != ast::scalar::unary_expression::tag) {
return expression;
}

auto&& unary = unsafe_downcast<ast::scalar::unary_expression>(*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<ast::scalar::literal_expression>(*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<ast::literal::numeric>(*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

3 changes: 2 additions & 1 deletion src/mizugaki/parser/sql_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <cstddef>


#include <mizugaki/ast/common/vector.h>
#include <mizugaki/ast/name/name.h>
#include <mizugaki/ast/name/simple.h>
Expand Down Expand Up @@ -90,6 +89,8 @@ class sql_driver {

[[nodiscard]] node_ptr<ast::type::type> try_build_type(node_ptr<ast::scalar::expression>& expr);

[[nodiscard]] node_ptr<ast::scalar::expression> try_fold_literal(node_ptr<ast::scalar::expression> expression);

private:
::takatori::util::maybe_shared_ptr<document_type const> document_;
std::vector<location_type> comments_;
Expand Down
36 changes: 20 additions & 16 deletions src/mizugaki/parser/sql_parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -2839,17 +2839,19 @@ scalar_value_expression
}
| "+"[o] scalar_value_expression[e] %prec UNARY_PLUS
{
$$ = driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::plus, @o },
$e,
@$);
$$ = driver.try_fold_literal(
driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::plus, @o },
$e,
@$));
}
| "-"[o] scalar_value_expression[e] %prec UNARY_MINUS
{
$$ = driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::minus, @o },
$e,
@$);
$$ = driver.try_fold_literal(
driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::minus, @o },
$e,
@$));
}
// 6.28 <datetime value expression> - <time zone>
| value_expression_primary[e] AT[o1] LOCAL[o2]
Expand Down Expand Up @@ -2886,17 +2888,19 @@ scalar_value_expression
signed_value_expression_primary
: "+"[s] value_expression_primary[e]
{
$$ = driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::plus, @s },
$e,
@$);
$$ = driver.try_fold_literal(
driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::plus, @s },
$e,
@$));
}
| "-"[s] value_expression_primary[e]
{
$$ = driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::minus, @s },
$e,
@$);
$$ = driver.try_fold_literal(
driver.node<ast::scalar::unary_expression>(
regioned { ast::scalar::unary_operator::minus, @s },
$e,
@$));
}
| value_expression_primary[e]
{
Expand Down
27 changes: 26 additions & 1 deletion test/mizugaki/parser/sql_parser_scalar_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include <mizugaki/ast/statement/select_statement.h>

#include <mizugaki/ast/query/query.h>
#include <mizugaki/ast/query/table_value_constructor.h>
#include <mizugaki/ast/query/table_reference.h>

Expand Down Expand Up @@ -478,6 +477,32 @@ TEST_F(sql_parser_scalar_test, unary_expression_minus) {
}));
}

TEST_F(sql_parser_scalar_test, unary_expression_plus_literal) {
auto result = parse("+1");
ASSERT_TRUE(result) << diagnostics(result);

EXPECT_EQ(extract(result), (scalar::literal_expression {
ast::literal::numeric {
ast::literal::kind::exact_numeric,
ast::literal::sign::plus,
{ "1" },
},
}));
}

TEST_F(sql_parser_scalar_test, unary_expression_minus_literal) {
auto result = parse("-1");
ASSERT_TRUE(result) << diagnostics(result);

EXPECT_EQ(extract(result), (scalar::literal_expression {
ast::literal::numeric {
ast::literal::kind::exact_numeric,
ast::literal::sign::minus,
{ "1" },
},
}));
}

TEST_F(sql_parser_scalar_test, unary_expression_at_local) {
auto result = parse("a at local");
ASSERT_TRUE(result) << diagnostics(result);
Expand Down

0 comments on commit 0a31789

Please sign in to comment.