From 011f7c1fee9a568f18a0832dbde4ce75524975ae Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Thu, 21 May 2026 20:00:08 -0400 Subject: [PATCH] parser/ide: improve lexer validation + goto def for t.c%type --- crates/squawk_ide/src/classify.rs | 25 ++++++ crates/squawk_ide/src/goto_definition.rs | 80 +++++++++++++++++++ crates/squawk_ide/src/hover.rs | 2 +- crates/squawk_ide/src/infer.rs | 2 +- crates/squawk_lexer/src/lib.rs | 75 +++++++++-------- .../squawk_lexer__tests__numeric.snap | 20 ++--- ...lexer__tests__numeric_with_seperators.snap | 2 +- crates/squawk_lexer/src/token.rs | 6 +- crates/squawk_parser/src/event.rs | 10 +-- .../src/generated/syntax_kind.rs | 2 +- crates/squawk_parser/src/grammar.rs | 6 +- crates/squawk_parser/src/lexed_str.rs | 4 +- crates/squawk_parser/src/lib.rs | 6 +- crates/squawk_parser/src/output.rs | 6 +- crates/squawk_parser/src/shortcuts.rs | 22 ++--- .../tests__alter_materialized_view_ok.snap | 2 +- .../snapshots/tests__alter_table_ok.snap | 2 +- .../snapshots/tests__create_table_ok.snap | 2 +- .../tests/snapshots/tests__execute_ok.snap | 2 +- .../tests/snapshots/tests__insert_ok.snap | 12 +-- .../tests/snapshots/tests__misc_ok.snap | 4 +- .../tests/snapshots/tests__schemas_ok.snap | 2 +- .../snapshots/tests__select_funcs_ok.snap | 4 +- .../snapshots/tests__select_literal_err.snap | 22 ++--- .../tests/snapshots/tests__select_ok.snap | 4 +- .../snapshots/tests__select_operators_ok.snap | 20 ++--- .../tests/snapshots/tests__select_xml_ok.snap | 4 +- .../tests/snapshots/tests__update_ok.snap | 2 +- .../tests/snapshots/tests__values_ok.snap | 4 +- crates/squawk_syntax/src/ast/node_ext.rs | 4 +- crates/squawk_syntax/src/postgresql.ungram | 2 +- 31 files changed, 235 insertions(+), 125 deletions(-) diff --git a/crates/squawk_ide/src/classify.rs b/crates/squawk_ide/src/classify.rs index 2a1a914c0..91579d3ef 100644 --- a/crates/squawk_ide/src/classify.rs +++ b/crates/squawk_ide/src/classify.rs @@ -305,6 +305,31 @@ pub(crate) fn classify_name_ref(node: &SyntaxNode) -> Option { } } + // %type clause paths (max 3 segments): + // column%type, table.column%type, schema.table.column%type + if let Some(parent) = node.parent() + && let Some(mut path) = ast::PathSegment::cast(parent) + .and_then(|p| p.syntax().parent().and_then(ast::Path::cast)) + { + let mut hops_up = 0; + while let Some(next) = path.syntax().parent().and_then(ast::Path::cast) { + path = next; + hops_up += 1; + } + if path + .syntax() + .parent() + .is_some_and(|p| ast::PercentType::can_cast(p.kind())) + { + return match hops_up { + 0 => Some(NameRefClass::QualifiedColumn), + 1 => Some(NameRefClass::Table), + 2 => Some(NameRefClass::Schema), + _ => None, + }; + } + } + if let Some(parent) = node.parent() && let Some(inner_path) = ast::PathSegment::cast(parent) .and_then(|p| p.syntax().parent().and_then(ast::Path::cast)) diff --git a/crates/squawk_ide/src/goto_definition.rs b/crates/squawk_ide/src/goto_definition.rs index ad99de134..f848f41b5 100644 --- a/crates/squawk_ide/src/goto_definition.rs +++ b/crates/squawk_ide/src/goto_definition.rs @@ -10032,4 +10032,84 @@ select 1 from graph_table (myshop$0 ╰╴ ─ 1. source "); } + + #[test] + fn goto_create_function_param_percent_type_column() { + assert_snapshot!(goto(" +create schema s; +create table s.t (a int, b text); +create function f(x s.t.a$0%type) returns s.t.b%type + as $$ select 'hello'::text $$ language sql; +"), @" + ╭▸ + 3 │ create table s.t (a int, b text); + │ ─ 2. destination + 4 │ create function f(x s.t.a%type) returns s.t.b%type + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_create_function_param_percent_type_table() { + assert_snapshot!(goto(" +create schema s; +create table s.t (a int, b text); +create function f(x s.t$0.a%type) returns s.t.b%type + as $$ select 'hello'::text $$ language sql; +"), @" + ╭▸ + 3 │ create table s.t (a int, b text); + │ ─ 2. destination + 4 │ create function f(x s.t.a%type) returns s.t.b%type + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_create_function_param_percent_type_schema() { + assert_snapshot!(goto(" +create schema s; +create table s.t (a int, b text); +create function f(x s$0.t.a%type) returns s.t.b%type + as $$ select 'hello'::text $$ language sql; +"), @" + ╭▸ + 2 │ create schema s; + │ ─ 2. destination + 3 │ create table s.t (a int, b text); + 4 │ create function f(x s.t.a%type) returns s.t.b%type + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_create_function_returns_percent_type_column() { + assert_snapshot!(goto(" +create schema s; +create table s.t (a int, b text); +create function f(x s.t.a%type) returns s.t.b$0%type + as $$ select 'hello'::text $$ language sql; +"), @" + ╭▸ + 3 │ create table s.t (a int, b text); + │ ─ 2. destination + 4 │ create function f(x s.t.a%type) returns s.t.b%type + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_create_function_param_percent_type_two_part() { + assert_snapshot!(goto(" +create table t (a int, b text); +create function f(x t.a$0%type) returns t.b%type + as $$ select 'hello'::text $$ language sql; +"), @" + ╭▸ + 2 │ create table t (a int, b text); + │ ─ 2. destination + 3 │ create function f(x t.a%type) returns t.b%type + ╰╴ ─ 1. source + "); + } } diff --git a/crates/squawk_ide/src/hover.rs b/crates/squawk_ide/src/hover.rs index 7100ac61d..70054127d 100644 --- a/crates/squawk_ide/src/hover.rs +++ b/crates/squawk_ide/src/hover.rs @@ -181,9 +181,9 @@ fn hover_literal(literal: &ast::Literal) -> Option { } None => format!("value of literal: {}", markdown_inline_code(&value)), }, - LitKind::FloatNumber(_) => return None, LitKind::IntNumber(_) => return None, LitKind::Null(_) => return None, + LitKind::NumericNumber(_) => return None, LitKind::PositionalParam(_) => return None, }; diff --git a/crates/squawk_ide/src/infer.rs b/crates/squawk_ide/src/infer.rs index 6c08c06ad..2381305a9 100644 --- a/crates/squawk_ide/src/infer.rs +++ b/crates/squawk_ide/src/infer.rs @@ -89,7 +89,7 @@ pub(crate) fn infer_type_from_literal(literal: &ast::Literal) -> Option { let token = literal.syntax().first_token()?; match token.kind() { SyntaxKind::INT_NUMBER => Some(infer_int_type(token.text())), - SyntaxKind::FLOAT_NUMBER => Some(Type::Numeric), + SyntaxKind::NUMERIC_NUMBER => Some(Type::Numeric), // TODO: this isn't necessarily text, e.g., select 1 + '1'; // We need to look at the context of the string's usage to be sure. SyntaxKind::STRING diff --git a/crates/squawk_lexer/src/lib.rs b/crates/squawk_lexer/src/lib.rs index 4c41543fc..40d04bbc9 100644 --- a/crates/squawk_lexer/src/lib.rs +++ b/crates/squawk_lexer/src/lib.rs @@ -236,6 +236,9 @@ impl Cursor<'_> { fn number(&mut self, first_digit: char) -> LiteralKind { let mut base = Base::Decimal; + if first_digit == '.' { + return self.eat_fractional(base); + } if first_digit == '0' { // Attempt to parse encoding base. match self.first() { @@ -306,43 +309,13 @@ impl Cursor<'_> { }; match self.first() { - '.' => { - // might have stuff after the ., and if it does, it needs to start - // with a number - self.bump(); - let mut empty_exponent = false; - if self.first().is_ascii_digit() { - self.eat_decimal_digits(); - match self.first() { - 'e' | 'E' => { - self.bump(); - empty_exponent = !self.eat_float_exponent(); - } - _ => (), - } - } else { - match self.first() { - 'e' | 'E' => { - self.bump(); - empty_exponent = !self.eat_float_exponent(); - } - _ => (), - } - } - let trailing_junk_start = self.pos_within_token(); - self.eat_identifier(); - LiteralKind::Float { - base, - empty_exponent, - trailing_junk_start, - } - } + '.' => self.eat_fractional(base), 'e' | 'E' => { self.bump(); - let empty_exponent = !self.eat_float_exponent(); + let empty_exponent = !self.eat_numeric_exponent(); let trailing_junk_start = self.pos_within_token(); self.eat_identifier(); - LiteralKind::Float { + LiteralKind::Numeric { base, empty_exponent, trailing_junk_start, @@ -509,9 +482,9 @@ impl Cursor<'_> { has_digits } - /// Eats the float exponent. Returns true if at least one digit was met, + /// Eats the numeric exponent. Returns true if at least one digit was met, /// and returns false otherwise. - fn eat_float_exponent(&mut self) -> bool { + fn eat_numeric_exponent(&mut self) -> bool { if self.first() == '_' { return false; } @@ -526,6 +499,38 @@ impl Cursor<'_> { self.eat_while(is_ident_cont); } } + + pub(crate) fn eat_fractional(&mut self, base: Base) -> crate::LiteralKind { + // might have stuff after the ., and if it does, it needs to start + // with a number + self.bump(); + let mut empty_exponent = false; + if self.first().is_ascii_digit() { + self.eat_decimal_digits(); + match self.first() { + 'e' | 'E' => { + self.bump(); + empty_exponent = !self.eat_numeric_exponent(); + } + _ => (), + } + } else { + match self.first() { + 'e' | 'E' => { + self.bump(); + empty_exponent = !self.eat_numeric_exponent(); + } + _ => (), + } + } + let trailing_junk_start = self.pos_within_token(); + self.eat_identifier(); + LiteralKind::Numeric { + base, + empty_exponent, + trailing_junk_start, + } + } } /// Creates an iterator that produces tokens from the input string. diff --git a/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric.snap b/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric.snap index addf6bb52..50d2593f4 100644 --- a/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric.snap +++ b/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric.snap @@ -6,24 +6,24 @@ expression: "lex(r#\"\n42\n3.5\n4.\n.001\n.123e10\n5e2\n1.925e-3\n1e-10\n1e+10\n "\n" @ Whitespace, "42" @ Literal { kind: Int { base: Decimal, empty_int: false, trailing_junk_start: 2 } }, "\n" @ Whitespace, - "3.5" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 3 } }, + "3.5" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 3 } }, "\n" @ Whitespace, - "4." @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 2 } }, + "4." @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 2 } }, "\n" @ Whitespace, - ".001" @ Literal { kind: Int { base: Decimal, empty_int: false, trailing_junk_start: 4 } }, + ".001" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 4 } }, "\n" @ Whitespace, - ".123e10" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 7 } }, + ".123e10" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 7 } }, "\n" @ Whitespace, - "5e2" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 3 } }, + "5e2" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 3 } }, "\n" @ Whitespace, - "1.925e-3" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 8 } }, + "1.925e-3" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 8 } }, "\n" @ Whitespace, - "1e-10" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 5 } }, + "1e-10" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 5 } }, "\n" @ Whitespace, - "1e+10" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 5 } }, + "1e+10" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 5 } }, "\n" @ Whitespace, - "1e10" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 4 } }, + "1e10" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 4 } }, "\n" @ Whitespace, - "4664.E+5" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 8 } }, + "4664.E+5" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 8 } }, "\n" @ Whitespace, ] diff --git a/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_with_seperators.snap b/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_with_seperators.snap index bfc095b89..0e0fddb4e 100644 --- a/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_with_seperators.snap +++ b/crates/squawk_lexer/src/snapshots/squawk_lexer__tests__numeric_with_seperators.snap @@ -12,6 +12,6 @@ expression: "lex(r#\"\n1_500_000_000\n0b10001000_00000000\n0o_1_755\n0xFFFF_FFFF "\n" @ Whitespace, "0xFFFF_FFFF" @ Literal { kind: Int { base: Hexadecimal, empty_int: false, trailing_junk_start: 11 } }, "\n" @ Whitespace, - "1.618_034" @ Literal { kind: Float { base: Decimal, empty_exponent: false, trailing_junk_start: 9 } }, + "1.618_034" @ Literal { kind: Numeric { base: Decimal, empty_exponent: false, trailing_junk_start: 9 } }, "\n" @ Whitespace, ] diff --git a/crates/squawk_lexer/src/token.rs b/crates/squawk_lexer/src/token.rs index bec1b5b13..438225e00 100644 --- a/crates/squawk_lexer/src/token.rs +++ b/crates/squawk_lexer/src/token.rs @@ -4,7 +4,7 @@ pub enum TokenKind { /// Used when there's an error of some sort while lexing. Unknown, /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid - /// suffix, but may be present here on string and float literals. Users of + /// suffix, but may be present here on string and numeric literals. Users of /// this type will need to check for and reject that case. /// /// See [`LiteralKind`] for more details. @@ -132,10 +132,10 @@ pub enum LiteralKind { empty_int: bool, trailing_junk_start: u32, }, - /// Float Numeric, e.g., `1.925e-3` + /// Numeric literal with a decimal point or exponent, e.g., `1.925e-3` /// /// see: - Float { + Numeric { base: Base, empty_exponent: bool, trailing_junk_start: u32, diff --git a/crates/squawk_parser/src/event.rs b/crates/squawk_parser/src/event.rs index cbcb7ef1d..4b390496d 100644 --- a/crates/squawk_parser/src/event.rs +++ b/crates/squawk_parser/src/event.rs @@ -93,11 +93,11 @@ pub(crate) enum Event { kind: SyntaxKind, n_raw_tokens: u8, }, - /// When we parse `foo.0.0` or `foo. 0. 0` the lexer will hand us a float literal + /// When we parse `foo.0.0` or `foo. 0. 0` the lexer will hand us a numeric literal /// instead of an integer literal followed by a dot as the lexer has no contextual knowledge. - /// This event instructs whatever consumes the events to split the float literal into + /// This event instructs whatever consumes the events to split the numeric literal into /// the corresponding parts. - FloatSplitHack { + NumericSplitHack { ends_in_dot: bool, }, Error { @@ -159,8 +159,8 @@ pub(super) fn process(mut events: Vec) -> Output { Event::Token { kind, n_raw_tokens } => { res.token(kind, n_raw_tokens); } - Event::FloatSplitHack { ends_in_dot } => { - res.float_split_hack(ends_in_dot); + Event::NumericSplitHack { ends_in_dot } => { + res.numeric_split_hack(ends_in_dot); let ev = mem::replace(&mut events[i + 1], Event::tombstone()); assert!(matches!(ev, Event::Finish), "{ev:?}"); } diff --git a/crates/squawk_parser/src/generated/syntax_kind.rs b/crates/squawk_parser/src/generated/syntax_kind.rs index 0a280dd33..a3af15593 100644 --- a/crates/squawk_parser/src/generated/syntax_kind.rs +++ b/crates/squawk_parser/src/generated/syntax_kind.rs @@ -554,9 +554,9 @@ pub enum SyntaxKind { BYTE_STRING, DOLLAR_QUOTED_STRING, ESC_STRING, - FLOAT_NUMBER, INT_NUMBER, NULL, + NUMERIC_NUMBER, POSITIONAL_PARAM, STRING, UNICODE_ESC_STRING, diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 092894802..91426b424 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -2278,8 +2278,8 @@ fn field_expr( p.bump(DOT); if p.at(IDENT) || p.at_ts(TYPE_KEYWORDS) || p.at(INT_NUMBER) || p.at_ts(ALL_KEYWORDS) { name_ref_or_index(p); - } else if p.at(FLOAT_NUMBER) { - return match p.split_float(m) { + } else if p.at(NUMERIC_NUMBER) { + return match p.split_numeric(m) { (true, m) => { let lhs = m.complete(p, FIELD_EXPR); postfix_dot_expr(p, lhs, allow_calls) @@ -4901,7 +4901,7 @@ const LITERAL_FIRST: TokenSet = TokenSet::new(&[TRUE_KW, FALSE_KW, NULL_KW, DEFA .union(NUMERIC_FIRST) .union(STRING_FIRST); -const NUMERIC_FIRST: TokenSet = TokenSet::new(&[INT_NUMBER, FLOAT_NUMBER]); +const NUMERIC_FIRST: TokenSet = TokenSet::new(&[INT_NUMBER, NUMERIC_NUMBER]); const STRING_FIRST: TokenSet = TokenSet::new(&[ STRING, diff --git a/crates/squawk_parser/src/lexed_str.rs b/crates/squawk_parser/src/lexed_str.rs index e2bced591..003031f3b 100644 --- a/crates/squawk_parser/src/lexed_str.rs +++ b/crates/squawk_parser/src/lexed_str.rs @@ -246,7 +246,7 @@ impl<'a> Converter<'a> { } SyntaxKind::INT_NUMBER } - squawk_lexer::LiteralKind::Float { + squawk_lexer::LiteralKind::Numeric { empty_exponent, base: _, trailing_junk_start, @@ -256,7 +256,7 @@ impl<'a> Converter<'a> { } else if (trailing_junk_start as usize) < token_text.len() { err = Some("trailing junk after numeric literal".into()); } - SyntaxKind::FLOAT_NUMBER + SyntaxKind::NUMERIC_NUMBER } squawk_lexer::LiteralKind::Str { terminated } => { if !terminated { diff --git a/crates/squawk_parser/src/lib.rs b/crates/squawk_parser/src/lib.rs index cc45f73f8..8a41adf4a 100644 --- a/crates/squawk_parser/src/lib.rs +++ b/crates/squawk_parser/src/lib.rs @@ -527,8 +527,8 @@ impl<'t> Parser<'t> { } /// Advances the parser by one token - pub(crate) fn split_float(&mut self, mut marker: Marker) -> (bool, Marker) { - assert!(self.at(SyntaxKind::FLOAT_NUMBER)); + pub(crate) fn split_numeric(&mut self, mut marker: Marker) -> (bool, Marker) { + assert!(self.at(SyntaxKind::NUMERIC_NUMBER)); // we have parse `.` // ``.0.1 // here we need to insert an extra event @@ -554,7 +554,7 @@ impl<'t> Parser<'t> { marker = new_marker; }; self.pos += 1; - self.push_event(Event::FloatSplitHack { ends_in_dot }); + self.push_event(Event::NumericSplitHack { ends_in_dot }); (ends_in_dot, marker) } diff --git a/crates/squawk_parser/src/output.rs b/crates/squawk_parser/src/output.rs index f310f7add..7cdfa0d4c 100644 --- a/crates/squawk_parser/src/output.rs +++ b/crates/squawk_parser/src/output.rs @@ -54,7 +54,7 @@ pub(crate) enum Step<'a> { kind: SyntaxKind, n_input_tokens: u8, }, - FloatSplit { + NumericSplit { ends_in_dot: bool, }, Enter { @@ -107,7 +107,7 @@ impl Output { Step::Enter { kind } } Self::EXIT_EVENT => Step::Exit, - Self::SPLIT_EVENT => Step::FloatSplit { + Self::SPLIT_EVENT => Step::NumericSplit { ends_in_dot: event & Self::N_INPUT_TOKEN_MASK != 0, }, _ => unreachable!(), @@ -122,7 +122,7 @@ impl Output { self.event.push(e) } - pub(crate) fn float_split_hack(&mut self, ends_in_dot: bool) { + pub(crate) fn numeric_split_hack(&mut self, ends_in_dot: bool) { let e = (Self::SPLIT_EVENT as u32) << Self::TAG_SHIFT | ((ends_in_dot as u32) << Self::N_INPUT_TOKEN_SHIFT) | Self::EVENT_MASK; diff --git a/crates/squawk_parser/src/shortcuts.rs b/crates/squawk_parser/src/shortcuts.rs index affe15474..409a014dd 100644 --- a/crates/squawk_parser/src/shortcuts.rs +++ b/crates/squawk_parser/src/shortcuts.rs @@ -64,14 +64,14 @@ impl Builder<'_, '_> { self.do_token(kind, n_tokens as usize); } - fn float_split(&mut self, has_pseudo_dot: bool) { + fn numeric_split(&mut self, has_pseudo_dot: bool) { match mem::replace(&mut self.state, State::Normal) { State::PendingEnter => unreachable!(), State::PendingExit => (self.sink)(StrStep::Exit), State::Normal => (), } self.eat_trivias(); - self.do_float_split(has_pseudo_dot); + self.do_numeric_split(has_pseudo_dot); } fn enter(&mut self, kind: SyntaxKind) { @@ -133,7 +133,7 @@ impl Builder<'_, '_> { (self.sink)(StrStep::Token { kind, text }); } - fn do_float_split(&mut self, has_pseudo_dot: bool) { + fn do_numeric_split(&mut self, has_pseudo_dot: bool) { let text = &self.lexed.range_text(self.pos..self.pos + 1); match text.split_once('.') { @@ -175,17 +175,17 @@ impl Builder<'_, '_> { } } None => { - // illegal float literal which doesn't have dot in form (like 1e0) + // illegal numeric literal which doesn't have dot in form (like 1e0) // we should emit an error node here (self.sink)(StrStep::Error { - msg: "illegal float literal", + msg: "illegal numeric literal", pos: self.pos, }); (self.sink)(StrStep::Enter { kind: SyntaxKind::ERROR, }); (self.sink)(StrStep::Token { - kind: SyntaxKind::FLOAT_NUMBER, + kind: SyntaxKind::NUMERIC_NUMBER, text, }); (self.sink)(StrStep::Exit); @@ -227,10 +227,10 @@ impl LexedStr<'_> { res.was_joint(); } res.push(kind); - // Tag the token as joint if it is float with a fractional part + // Tag the token as joint if it is numeric with a fractional part // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - // if kind == SyntaxKind::FLOAT_NUMBER { + // event to emit when we encounter a numeric literal in a field access + // if kind == SyntaxKind::NUMERIC_NUMBER { // if !self.text(i).ends_with('.') { // res.was_joint(); // } else { @@ -259,9 +259,9 @@ impl LexedStr<'_> { kind, n_input_tokens: n_raw_tokens, } => builder.token(kind, n_raw_tokens), - Step::FloatSplit { + Step::NumericSplit { ends_in_dot: has_pseudo_dot, - } => builder.float_split(has_pseudo_dot), + } => builder.numeric_split(has_pseudo_dot), Step::Enter { kind } => builder.enter(kind), Step::Exit => builder.exit(), Step::Error { msg } => { diff --git a/crates/squawk_parser/tests/snapshots/tests__alter_materialized_view_ok.snap b/crates/squawk_parser/tests/snapshots/tests__alter_materialized_view_ok.snap index aad0adb49..2af1f2430 100644 --- a/crates/squawk_parser/tests/snapshots/tests__alter_materialized_view_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__alter_materialized_view_ok.snap @@ -407,7 +407,7 @@ SOURCE_FILE WHITESPACE " " ATTRIBUTE_VALUE LITERAL - FLOAT_NUMBER "1.0" + NUMERIC_NUMBER "1.0" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__alter_table_ok.snap b/crates/squawk_parser/tests/snapshots/tests__alter_table_ok.snap index 75af3190d..4186110ca 100644 --- a/crates/squawk_parser/tests/snapshots/tests__alter_table_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__alter_table_ok.snap @@ -222,7 +222,7 @@ SOURCE_FILE DEFAULT_KW "default" WHITESPACE " " LITERAL - FLOAT_NUMBER "7.77" + NUMERIC_NUMBER "7.77" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- remove column default" diff --git a/crates/squawk_parser/tests/snapshots/tests__create_table_ok.snap b/crates/squawk_parser/tests/snapshots/tests__create_table_ok.snap index 06d1e71fe..66ed9109e 100644 --- a/crates/squawk_parser/tests/snapshots/tests__create_table_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__create_table_ok.snap @@ -1124,7 +1124,7 @@ SOURCE_FILE WHITESPACE " " ATTRIBUTE_VALUE LITERAL - FLOAT_NUMBER "10.1" + NUMERIC_NUMBER "10.1" WHITESPACE "\n " COMMENT "-- others omitted" WHITESPACE "\n " diff --git a/crates/squawk_parser/tests/snapshots/tests__execute_ok.snap b/crates/squawk_parser/tests/snapshots/tests__execute_ok.snap index ca118341a..981e322b3 100644 --- a/crates/squawk_parser/tests/snapshots/tests__execute_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__execute_ok.snap @@ -25,7 +25,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "200.00" + NUMERIC_NUMBER "200.00" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap b/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap index 59b03126d..5aea3598c 100644 --- a/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap @@ -30,7 +30,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "9.99" + NUMERIC_NUMBER "9.99" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -76,7 +76,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "9.99" + NUMERIC_NUMBER "9.99" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" @@ -118,7 +118,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "9.99" + NUMERIC_NUMBER "9.99" COMMA "," WHITESPACE " " LITERAL @@ -183,7 +183,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "9.99" + NUMERIC_NUMBER "9.99" R_PAREN ")" COMMA "," WHITESPACE "\n " @@ -198,7 +198,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "1.99" + NUMERIC_NUMBER "1.99" R_PAREN ")" COMMA "," WHITESPACE "\n " @@ -213,7 +213,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "2.99" + NUMERIC_NUMBER "2.99" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap b/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap index a0fdaa4b0..311fc7c40 100644 --- a/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap @@ -5427,7 +5427,7 @@ SOURCE_FILE EQ "=" WHITESPACE " " LITERAL - FLOAT_NUMBER "0.001" + NUMERIC_NUMBER "0.001" SEMICOLON ";" WHITESPACE " " COMMENT "-- Lower = more parallelism" @@ -6896,7 +6896,7 @@ SOURCE_FILE ARG_LIST L_PAREN "(" LITERAL - FLOAT_NUMBER "0.75" + NUMERIC_NUMBER "0.75" R_PAREN ")" WHITESPACE " " WITHIN_CLAUSE diff --git a/crates/squawk_parser/tests/snapshots/tests__schemas_ok.snap b/crates/squawk_parser/tests/snapshots/tests__schemas_ok.snap index 6d7729120..352a73ab4 100644 --- a/crates/squawk_parser/tests/snapshots/tests__schemas_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__schemas_ok.snap @@ -565,7 +565,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "10.0" + NUMERIC_NUMBER "10.0" COMMA "," WHITESPACE " " LITERAL diff --git a/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap index 5215d6a6a..c33bdf316 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_funcs_ok.snap @@ -3090,7 +3090,7 @@ SOURCE_FILE ARG_LIST L_PAREN "(" LITERAL - FLOAT_NUMBER "1.5" + NUMERIC_NUMBER "1.5" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -3298,7 +3298,7 @@ SOURCE_FILE ARG_LIST L_PAREN "(" LITERAL - FLOAT_NUMBER "0.5" + NUMERIC_NUMBER "0.5" R_PAREN ")" WHITESPACE " " WITHIN_CLAUSE diff --git a/crates/squawk_parser/tests/snapshots/tests__select_literal_err.snap b/crates/squawk_parser/tests/snapshots/tests__select_literal_err.snap index 0172bd97c..691e1fb4c 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_literal_err.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_literal_err.snap @@ -30,7 +30,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "0.a" + NUMERIC_NUMBER "0.a" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -40,7 +40,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "0.0a" + NUMERIC_NUMBER "0.0a" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -50,7 +50,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - INT_NUMBER ".0a" + NUMERIC_NUMBER ".0a" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -60,7 +60,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "0.0e1a" + NUMERIC_NUMBER "0.0e1a" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -70,7 +70,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "0.0e" + NUMERIC_NUMBER "0.0e" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -80,7 +80,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "0.0e+a" + NUMERIC_NUMBER "0.0e+a" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -213,7 +213,7 @@ SOURCE_FILE IDENT "_1_000" TARGET LITERAL - INT_NUMBER ".5" + NUMERIC_NUMBER ".5" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -226,7 +226,7 @@ SOURCE_FILE INT_NUMBER "1_000_" TARGET LITERAL - INT_NUMBER ".5" + NUMERIC_NUMBER ".5" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -236,7 +236,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "1_000._5" + NUMERIC_NUMBER "1_000._5" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -246,7 +246,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "1_000.5_" + NUMERIC_NUMBER "1_000.5_" SEMICOLON ";" WHITESPACE "\n" SELECT @@ -256,7 +256,7 @@ SOURCE_FILE TARGET_LIST TARGET LITERAL - FLOAT_NUMBER "1_000.5e_1" + NUMERIC_NUMBER "1_000.5e_1" SEMICOLON ";" WHITESPACE "\n" SELECT diff --git a/crates/squawk_parser/tests/snapshots/tests__select_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_ok.snap index e490ee8b8..b26d998fb 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_ok.snap @@ -4523,7 +4523,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "1.99" + NUMERIC_NUMBER "1.99" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n" @@ -4544,7 +4544,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "1.99" + NUMERIC_NUMBER "1.99" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__select_operators_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_operators_ok.snap index 9be374171..2f3b7889e 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_operators_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_operators_ok.snap @@ -2686,7 +2686,7 @@ SOURCE_FILE TARGET BIN_EXPR LITERAL - FLOAT_NUMBER "1.5" + NUMERIC_NUMBER "1.5" WHITESPACE " " IS_KW "is" WHITESPACE " " @@ -2894,7 +2894,7 @@ SOURCE_FILE PLUS "+" WHITESPACE " " LITERAL - FLOAT_NUMBER "3.5" + NUMERIC_NUMBER "3.5" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- subtraction" @@ -2963,7 +2963,7 @@ SOURCE_FILE TARGET BIN_EXPR LITERAL - FLOAT_NUMBER "5.0" + NUMERIC_NUMBER "5.0" WHITESPACE " " SLASH "/" WHITESPACE " " @@ -3083,7 +3083,7 @@ SOURCE_FILE SLASH "/" WHITESPACE " " LITERAL - FLOAT_NUMBER "25.0" + NUMERIC_NUMBER "25.0" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- cube root" @@ -3101,7 +3101,7 @@ SOURCE_FILE SLASH "/" WHITESPACE " " LITERAL - FLOAT_NUMBER "64.0" + NUMERIC_NUMBER "64.0" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- absolute value" @@ -3119,7 +3119,7 @@ SOURCE_FILE PREFIX_EXPR MINUS "-" LITERAL - FLOAT_NUMBER "5.0" + NUMERIC_NUMBER "5.0" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- bitwise and" @@ -5218,11 +5218,11 @@ SOURCE_FILE ARG_LIST L_PAREN "(" LITERAL - FLOAT_NUMBER "1.1" + NUMERIC_NUMBER "1.1" COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "2.2" + NUMERIC_NUMBER "2.2" R_PAREN ")" WHITESPACE " " CUSTOM_OP @@ -5236,11 +5236,11 @@ SOURCE_FILE ARG_LIST L_PAREN "(" LITERAL - FLOAT_NUMBER "2.2" + NUMERIC_NUMBER "2.2" COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "3.3" + NUMERIC_NUMBER "3.3" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap index 0c3e94e20..48f3cad33 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_xml_ok.snap @@ -165,7 +165,7 @@ SOURCE_FILE DEFAULT_KW "default" WHITESPACE " " LITERAL - FLOAT_NUMBER "0.00" + NUMERIC_NUMBER "0.00" COMMA "," WHITESPACE "\n " XML_TABLE_COLUMN @@ -193,7 +193,7 @@ SOURCE_FILE DEFAULT_KW "default" WHITESPACE " " LITERAL - FLOAT_NUMBER "0.00" + NUMERIC_NUMBER "0.00" WHITESPACE " " XML_COLUMN_OPTION NULL_KW "null" diff --git a/crates/squawk_parser/tests/snapshots/tests__update_ok.snap b/crates/squawk_parser/tests/snapshots/tests__update_ok.snap index cd4fe156f..aab68a89d 100644 --- a/crates/squawk_parser/tests/snapshots/tests__update_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__update_ok.snap @@ -74,7 +74,7 @@ SOURCE_FILE STAR "*" WHITESPACE " " LITERAL - FLOAT_NUMBER "1.10" + NUMERIC_NUMBER "1.10" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- set muliple" diff --git a/crates/squawk_parser/tests/snapshots/tests__values_ok.snap b/crates/squawk_parser/tests/snapshots/tests__values_ok.snap index 5a12c1d79..91fa30230 100644 --- a/crates/squawk_parser/tests/snapshots/tests__values_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__values_ok.snap @@ -348,7 +348,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "1.2" + NUMERIC_NUMBER "1.2" R_PAREN ")" COMMA "," WHITESPACE " " @@ -363,7 +363,7 @@ SOURCE_FILE COMMA "," WHITESPACE " " LITERAL - FLOAT_NUMBER "1.4" + NUMERIC_NUMBER "1.4" R_PAREN ")" R_PAREN ")" WHITESPACE " " diff --git a/crates/squawk_syntax/src/ast/node_ext.rs b/crates/squawk_syntax/src/ast/node_ext.rs index 4eda92a7a..12f1b7118 100644 --- a/crates/squawk_syntax/src/ast/node_ext.rs +++ b/crates/squawk_syntax/src/ast/node_ext.rs @@ -47,9 +47,9 @@ pub enum LitKind { ByteString(SyntaxToken), DollarQuotedString(SyntaxToken), EscString(SyntaxToken), - FloatNumber(SyntaxToken), IntNumber(SyntaxToken), Null(SyntaxToken), + NumericNumber(SyntaxToken), PositionalParam(SyntaxToken), String(SyntaxToken), UnicodeEscString(SyntaxToken), @@ -61,7 +61,7 @@ impl ast::Literal { let kind = match token.kind() { SyntaxKind::STRING => LitKind::String(token), SyntaxKind::NULL_KW => LitKind::Null(token), - SyntaxKind::FLOAT_NUMBER => LitKind::FloatNumber(token), + SyntaxKind::NUMERIC_NUMBER => LitKind::NumericNumber(token), SyntaxKind::INT_NUMBER => LitKind::IntNumber(token), SyntaxKind::BYTE_STRING => LitKind::ByteString(token), SyntaxKind::BIT_STRING => LitKind::BitString(token), diff --git a/crates/squawk_syntax/src/postgresql.ungram b/crates/squawk_syntax/src/postgresql.ungram index 0cf2f0cb8..2cd387ad5 100644 --- a/crates/squawk_syntax/src/postgresql.ungram +++ b/crates/squawk_syntax/src/postgresql.ungram @@ -353,7 +353,7 @@ Literal = value:( '@string' | '@null' - | '@float_number' + | '@numeric_number' | '@int_number' | '@byte_string' | '@bit_string'