diff --git a/crates/uroborosql-fmt/src/cst/expr/unary.rs b/crates/uroborosql-fmt/src/cst/expr/unary.rs index d9f301b..cc79c0d 100644 --- a/crates/uroborosql-fmt/src/cst/expr/unary.rs +++ b/crates/uroborosql-fmt/src/cst/expr/unary.rs @@ -51,7 +51,10 @@ impl UnaryExpr { let mut result = String::new(); result.push_str(&self.operator); - result.push('\t'); + // `NOT` のときは空白が必要 + if self.operator.to_uppercase().as_str() == "NOT" { + result.push('\t'); + } result.push_str(&self.operand.render(depth)?); Ok(result) diff --git a/crates/uroborosql-fmt/src/visitor/expr.rs b/crates/uroborosql-fmt/src/visitor/expr.rs index ff37521..e1a68eb 100644 --- a/crates/uroborosql-fmt/src/visitor/expr.rs +++ b/crates/uroborosql-fmt/src/visitor/expr.rs @@ -11,6 +11,7 @@ mod is; mod paren; mod subquery; mod type_cast; +mod unary; use tree_sitter::TreeCursor; @@ -137,6 +138,10 @@ impl Visitor { "all_some_any_subquery_expression" => { Expr::Aligned(Box::new(self.visit_all_some_any_subquery(cursor, src)?)) } + "unary_expression" => { + let unary = self.visit_unary_expr(cursor, src)?; + Expr::Unary(Box::new(unary)) + } _ => { // todo return Err(UroboroSQLFmtError::Unimplemented(format!( diff --git a/crates/uroborosql-fmt/src/visitor/expr/unary.rs b/crates/uroborosql-fmt/src/visitor/expr/unary.rs new file mode 100644 index 0000000..7d09193 --- /dev/null +++ b/crates/uroborosql-fmt/src/visitor/expr/unary.rs @@ -0,0 +1,34 @@ +use tree_sitter::TreeCursor; + +use crate::{ + cst::{unary::UnaryExpr, Location}, + error::UroboroSQLFmtError, + visitor::{ensure_kind, Visitor}, +}; + +impl Visitor { + pub(crate) fn visit_unary_expr( + &mut self, + cursor: &mut TreeCursor, + src: &str, + ) -> Result { + // cursor -> unary_expression + + let mut loc = Location::new(cursor.node().range()); + + cursor.goto_first_child(); + // cursor -> op ("+", "-", "!!", "~", "@", "|/", "||/", "NOT") + let operator = cursor.node().utf8_text(src.as_bytes()).unwrap(); + + cursor.goto_next_sibling(); + // cursor -> _expression + + let operand = self.visit_expr(cursor, src)?; + loc.append(operand.loc()); + + cursor.goto_parent(); + ensure_kind(cursor, "unary_expression", src)?; + + Ok(UnaryExpr::new(operator, operand, loc)) + } +} diff --git a/crates/uroborosql-fmt/testfiles/dst/select/unary.sql b/crates/uroborosql-fmt/testfiles/dst/select/unary.sql new file mode 100644 index 0000000..9dc2f63 --- /dev/null +++ b/crates/uroborosql-fmt/testfiles/dst/select/unary.sql @@ -0,0 +1,39 @@ +select + +5 as positive_value +; +select + +5 as positive_value +; +select + -10 as negative_value +; +select + -10 as negative_value +; +select + not true as not_true +; +select + ~5 as bitwise_not +; +select + ~5 as bitwise_not +; +select + @-5 as absolute_value +; +select + @-5 as absolute_value +; +select + |/25 as square_root +; +select + |/25 as square_root +; +select + ||/8 as cube_root +; +select + ||/8 as cube_root +; diff --git a/crates/uroborosql-fmt/testfiles/src/select/unary.sql b/crates/uroborosql-fmt/testfiles/src/select/unary.sql new file mode 100644 index 0000000..1a9a502 --- /dev/null +++ b/crates/uroborosql-fmt/testfiles/src/select/unary.sql @@ -0,0 +1,19 @@ +select +5 as positive_value +select + 5 as positive_value + +select -10 as negative_value +select - 10 as negative_value + +select not true as not_true + +select ~5 as bitwise_not +select ~ 5 as bitwise_not + +select @-5 as absolute_value +select @ -5 as absolute_value + +select |/25 as square_root +select |/ 25 as square_root + +select ||/8 as cube_root +select ||/ 8 as cube_root \ No newline at end of file