From d0b9c96edde85b7b1cd60632a914dfe06355a8fd Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Sun, 7 Dec 2025 23:28:36 -0500 Subject: [PATCH] parser: add syntax node ptr & update grammar --- crates/squawk_ide/src/expand_selection.rs | 2 + .../src/generated/syntax_kind.rs | 3 + crates/squawk_parser/src/grammar.rs | 51 ++++-- .../tests/snapshots/tests__analyze_ok.snap | 138 +++++++------- .../snapshots/tests__create_function_ok.snap | 74 ++++---- .../snapshots/tests__create_procedure_ok.snap | 36 ++-- .../tests/snapshots/tests__misc_ok.snap | 22 +-- .../tests/snapshots/tests__vacuum_ok.snap | 84 +++++---- .../squawk_syntax/src/ast/generated/nodes.rs | 169 ++++++++++++++++-- crates/squawk_syntax/src/lib.rs | 2 +- crates/squawk_syntax/src/postgresql.ungram | 30 +++- crates/squawk_syntax/src/syntax_node.rs | 1 + 12 files changed, 412 insertions(+), 200 deletions(-) diff --git a/crates/squawk_ide/src/expand_selection.rs b/crates/squawk_ide/src/expand_selection.rs index 84282a6c..f39260d0 100644 --- a/crates/squawk_ide/src/expand_selection.rs +++ b/crates/squawk_ide/src/expand_selection.rs @@ -37,6 +37,7 @@ const DELIMITED_LIST_KINDS: &[SyntaxKind] = &[ SyntaxKind::ALTER_OPTION_LIST, SyntaxKind::ARG_LIST, SyntaxKind::ATTRIBUTE_LIST, + SyntaxKind::BEGIN_FUNC_OPTION_LIST, SyntaxKind::COLUMN_LIST, SyntaxKind::CONFLICT_INDEX_ITEM_LIST, SyntaxKind::CONSTRAINT_EXCLUSION_LIST, @@ -60,6 +61,7 @@ const DELIMITED_LIST_KINDS: &[SyntaxKind] = &[ SyntaxKind::SET_EXPR_LIST, SyntaxKind::SET_OPTIONS_LIST, SyntaxKind::SORT_BY_LIST, + SyntaxKind::TABLE_AND_COLUMNS_LIST, SyntaxKind::TABLE_ARG_LIST, SyntaxKind::TABLE_LIST, SyntaxKind::TARGET_LIST, diff --git a/crates/squawk_parser/src/generated/syntax_kind.rs b/crates/squawk_parser/src/generated/syntax_kind.rs index bf8c57e2..5366e75c 100644 --- a/crates/squawk_parser/src/generated/syntax_kind.rs +++ b/crates/squawk_parser/src/generated/syntax_kind.rs @@ -610,6 +610,7 @@ pub enum SyntaxKind { AT_TIME_ZONE, BEGIN, BEGIN_FUNC_OPTION, + BEGIN_FUNC_OPTION_LIST, BETWEEN_EXPR, BIN_EXPR, BIT_TYPE, @@ -1096,6 +1097,8 @@ pub enum SyntaxKind { TABLE, TABLESAMPLE_CLAUSE, TABLESPACE, + TABLE_AND_COLUMNS, + TABLE_AND_COLUMNS_LIST, TABLE_ARG_LIST, TABLE_LIST, TARGET, diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 926c4cd5..70a01dcb 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -8173,7 +8173,7 @@ fn analyze(p: &mut Parser<'_>) -> CompletedMarker { if !p.eat(VERBOSE_KW) { opt_option_list(p); } - opt_relation_list(p); + opt_table_and_columns_list(p); m.complete(p, ANALYZE) } @@ -11691,7 +11691,7 @@ fn vacuum(p: &mut Parser<'_>) -> CompletedMarker { // [ ANALYZE ] let _ = p.eat(ANALYZE_KW) || p.eat(ANALYSE_KW); opt_vacuum_option_list(p); - opt_relation_list(p); + opt_table_and_columns_list(p); m.complete(p, VACUUM) } @@ -11715,16 +11715,29 @@ fn opt_vacuum_option_list(p: &mut Parser<'_>) { // [ table_and_columns [, ...] ] // where table_and_coumns is: // table_name [ ( column_name [, ...] ) ] -fn opt_relation_list(p: &mut Parser<'_>) { +fn opt_table_and_columns_list(p: &mut Parser<'_>) { + let m = p.start(); while !p.at(EOF) { - if opt_relation_name(p).is_none() { - break; + if !opt_table_and_columns(p) { + m.abandon(p); + return; } - opt_column_list(p); if !p.eat(COMMA) { break; } } + m.complete(p, TABLE_AND_COLUMNS_LIST); +} + +fn opt_table_and_columns(p: &mut Parser<'_>) -> bool { + let m = p.start(); + if opt_relation_name(p).is_none() { + m.abandon(p); + return false; + } + opt_column_list(p); + m.complete(p, TABLE_AND_COLUMNS); + true } const VACUUM_OPTION_FIRST: TokenSet = NON_RESERVED_WORD @@ -13194,20 +13207,13 @@ fn opt_function_option(p: &mut Parser<'_>) -> bool { if p.eat(SEMICOLON) { continue; } - // sql standard - if p.eat(RETURN_KW) { - if expr(p).is_none() { - p.error("expected expr") - } - } else { - stmt(p, &StmtRestrictions::default()); - } + begin_func_option(p); if p.at(END_KW) { p.expect(SEMICOLON); } } p.expect(END_KW); - BEGIN_FUNC_OPTION + BEGIN_FUNC_OPTION_LIST } _ => { m.abandon(p); @@ -13218,6 +13224,21 @@ fn opt_function_option(p: &mut Parser<'_>) -> bool { true } +fn begin_func_option(p: &mut Parser<'_>) { + let m = p.start(); + if p.at(RETURN_KW) { + let m = p.start(); + p.bump(RETURN_KW); + if expr(p).is_none() { + p.error("expected expr") + } + m.complete(p, RETURN_FUNC_OPTION); + } else { + stmt(p, &StmtRestrictions::default()); + } + m.complete(p, BEGIN_FUNC_OPTION); +} + // SET configuration_parameter { TO | = } { value | DEFAULT } // SET configuration_parameter FROM CURRENT fn set_configuration_param(p: &mut Parser<'_>) { diff --git a/crates/squawk_parser/tests/snapshots/tests__analyze_ok.snap b/crates/squawk_parser/tests/snapshots/tests__analyze_ok.snap index 580abe87..9049ea17 100644 --- a/crates/squawk_parser/tests/snapshots/tests__analyze_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__analyze_ok.snap @@ -20,51 +20,55 @@ SOURCE_FILE WHITESPACE " " VERBOSE_KW "verbose" WHITESPACE " " - RELATION_NAME - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "foo" - DOT "." - PATH_SEGMENT - NAME_REF - IDENT "bar" - COMMA "," - WHITESPACE " " - RELATION_NAME - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "foo" - DOT "." - PATH_SEGMENT - NAME_REF - IDENT "bar" - COLUMN_LIST - L_PAREN "(" - COLUMN - NAME_REF - IDENT "a" + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + DOT "." + PATH_SEGMENT + NAME_REF + IDENT "bar" COMMA "," WHITESPACE " " - COLUMN - NAME_REF - IDENT "b" + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + DOT "." + PATH_SEGMENT + NAME_REF + IDENT "bar" + COLUMN_LIST + L_PAREN "(" + COLUMN + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + COLUMN + NAME_REF + IDENT "b" + COMMA "," + WHITESPACE " " + COLUMN + NAME_REF + IDENT "c" + R_PAREN ")" COMMA "," WHITESPACE " " - COLUMN - NAME_REF - IDENT "c" - R_PAREN ")" - COMMA "," - WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "foo" + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- full_parens" @@ -92,31 +96,33 @@ SOURCE_FILE INT_NUMBER "10" R_PAREN ")" WHITESPACE " " - RELATION_NAME - PATH - PATH - PATH_SEGMENT + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + DOT "." + PATH_SEGMENT + NAME_REF + IDENT "bar" + COLUMN_LIST + L_PAREN "(" + COLUMN NAME_REF - IDENT "foo" - DOT "." - PATH_SEGMENT - NAME_REF - IDENT "bar" - COLUMN_LIST - L_PAREN "(" - COLUMN - NAME_REF - IDENT "a" - COMMA "," - WHITESPACE " " - COLUMN - NAME_REF - IDENT "b" - COMMA "," - WHITESPACE " " - COLUMN - NAME_REF - IDENT "c" - R_PAREN ")" + IDENT "a" + COMMA "," + WHITESPACE " " + COLUMN + NAME_REF + IDENT "b" + COMMA "," + WHITESPACE " " + COLUMN + NAME_REF + IDENT "c" + R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_parser/tests/snapshots/tests__create_function_ok.snap b/crates/squawk_parser/tests/snapshots/tests__create_function_ok.snap index bf71d3a7..b02c9f8d 100644 --- a/crates/squawk_parser/tests/snapshots/tests__create_function_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__create_function_ok.snap @@ -1783,29 +1783,31 @@ SOURCE_FILE WHITESPACE " " SQL_KW "sql" WHITESPACE "\n" - BEGIN_FUNC_OPTION + BEGIN_FUNC_OPTION_LIST BEGIN_KW "begin" WHITESPACE " " ATOMIC_KW "atomic" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" SEMICOLON ";" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "2" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "2" SEMICOLON ";" WHITESPACE "\n" END_KW "end" @@ -1839,19 +1841,20 @@ SOURCE_FILE WHITESPACE " " SQL_KW "sql" WHITESPACE "\n" - BEGIN_FUNC_OPTION + BEGIN_FUNC_OPTION_LIST BEGIN_KW "begin" WHITESPACE " " ATOMIC_KW "atomic" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" SEMICOLON ";" WHITESPACE "\n " END_KW "end" @@ -1891,7 +1894,7 @@ SOURCE_FILE WHITESPACE " " SQL_KW "sql" WHITESPACE "\n" - BEGIN_FUNC_OPTION + BEGIN_FUNC_OPTION_LIST BEGIN_KW "begin" WHITESPACE " " ATOMIC_KW "atomic" @@ -1904,14 +1907,15 @@ SOURCE_FILE WHITESPACE "\n" SEMICOLON ";" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" SEMICOLON ";" WHITESPACE "\n" SEMICOLON ";" diff --git a/crates/squawk_parser/tests/snapshots/tests__create_procedure_ok.snap b/crates/squawk_parser/tests/snapshots/tests__create_procedure_ok.snap index bd6b9e85..f8cbab73 100644 --- a/crates/squawk_parser/tests/snapshots/tests__create_procedure_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__create_procedure_ok.snap @@ -254,29 +254,31 @@ SOURCE_FILE WHITESPACE " " SQL_KW "sql" WHITESPACE "\n" - BEGIN_FUNC_OPTION + BEGIN_FUNC_OPTION_LIST BEGIN_KW "begin" WHITESPACE " " ATOMIC_KW "atomic" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "1" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "1" SEMICOLON ";" WHITESPACE "\n " - SELECT - SELECT_CLAUSE - SELECT_KW "select" - WHITESPACE " " - TARGET_LIST - TARGET - LITERAL - INT_NUMBER "2" + BEGIN_FUNC_OPTION + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + LITERAL + INT_NUMBER "2" SEMICOLON ";" WHITESPACE "\n" END_KW "end" diff --git a/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap b/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap index 3f22c54d..da29372c 100644 --- a/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__misc_ok.snap @@ -1880,16 +1880,18 @@ SOURCE_FILE WHITESPACE " " ANALYZE_KW "ANALYZE" WHITESPACE " " - RELATION_NAME - PATH - PATH - PATH_SEGMENT - NAME_REF - IDENT "partman_test" - DOT "." - PATH_SEGMENT - NAME_REF - IDENT "time_taptest_table" + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "partman_test" + DOT "." + PATH_SEGMENT + NAME_REF + IDENT "time_taptest_table" SEMICOLON ";" WHITESPACE "\n\n" SELECT diff --git a/crates/squawk_parser/tests/snapshots/tests__vacuum_ok.snap b/crates/squawk_parser/tests/snapshots/tests__vacuum_ok.snap index 1772a3ca..232a2ac7 100644 --- a/crates/squawk_parser/tests/snapshots/tests__vacuum_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__vacuum_ok.snap @@ -24,11 +24,13 @@ SOURCE_FILE ANALYZE_KW "ANALYZE" R_PAREN ")" WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "onek" + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "onek" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- full" @@ -223,11 +225,13 @@ SOURCE_FILE WHITESPACE "\n" R_PAREN ")" WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "t1" + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "t1" SEMICOLON ";" WHITESPACE "\n\n" COMMENT "-- pre_pg_9_syntax" @@ -243,35 +247,39 @@ SOURCE_FILE WHITESPACE " " ANALYZE_KW "analyze" WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "foo" - COMMA "," - WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "bar" - COLUMN_LIST - L_PAREN "(" - COLUMN - NAME_REF - IDENT "a" + TABLE_AND_COLUMNS_LIST + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" COMMA "," WHITESPACE " " - COLUMN - NAME_REF - IDENT "b" - R_PAREN ")" - COMMA "," - WHITESPACE " " - RELATION_NAME - PATH - PATH_SEGMENT - NAME_REF - IDENT "c" + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "bar" + COLUMN_LIST + L_PAREN "(" + COLUMN + NAME_REF + IDENT "a" + COMMA "," + WHITESPACE " " + COLUMN + NAME_REF + IDENT "b" + R_PAREN ")" + COMMA "," + WHITESPACE " " + TABLE_AND_COLUMNS + RELATION_NAME + PATH + PATH_SEGMENT + NAME_REF + IDENT "c" SEMICOLON ";" WHITESPACE "\n\n" diff --git a/crates/squawk_syntax/src/ast/generated/nodes.rs b/crates/squawk_syntax/src/ast/generated/nodes.rs index c038b9ec..15100b1f 100644 --- a/crates/squawk_syntax/src/ast/generated/nodes.rs +++ b/crates/squawk_syntax/src/ast/generated/nodes.rs @@ -1696,8 +1696,12 @@ impl Analyze { support::child(&self.syntax) } #[inline] - pub fn relation_names(&self) -> AstChildren { - support::children(&self.syntax) + pub fn table_and_columns_list(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn analyse_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::ANALYSE_KW) } #[inline] pub fn analyze_token(&self) -> Option { @@ -2045,6 +2049,29 @@ pub struct BeginFuncOption { pub(crate) syntax: SyntaxNode, } impl BeginFuncOption { + #[inline] + pub fn return_func_option(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn stmt(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn semicolon_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::SEMICOLON) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct BeginFuncOptionList { + pub(crate) syntax: SyntaxNode, +} +impl BeginFuncOptionList { + #[inline] + pub fn begin_func_options(&self) -> AstChildren { + support::children(&self.syntax) + } #[inline] pub fn atomic_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::ATOMIC_KW) @@ -2997,6 +3024,10 @@ impl Copy { pub fn to_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::TO_KW) } + #[inline] + pub fn with_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::WITH_KW) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -7291,9 +7322,21 @@ impl Explain { support::child(&self.syntax) } #[inline] + pub fn analyse_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::ANALYSE_KW) + } + #[inline] + pub fn analyze_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::ANALYZE_KW) + } + #[inline] pub fn explain_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::EXPLAIN_KW) } + #[inline] + pub fn verbose_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::VERBOSE_KW) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -14682,6 +14725,32 @@ impl Table { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TableAndColumns { + pub(crate) syntax: SyntaxNode, +} +impl TableAndColumns { + #[inline] + pub fn column_list(&self) -> Option { + support::child(&self.syntax) + } + #[inline] + pub fn relation_name(&self) -> Option { + support::child(&self.syntax) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TableAndColumnsList { + pub(crate) syntax: SyntaxNode, +} +impl TableAndColumnsList { + #[inline] + pub fn table_and_columnss(&self) -> AstChildren { + support::children(&self.syntax) + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TableArgList { pub(crate) syntax: SyntaxNode, @@ -15234,7 +15303,7 @@ pub struct Vacuum { } impl Vacuum { #[inline] - pub fn relation_name(&self) -> Option { + pub fn table_and_columns_list(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -15242,9 +15311,29 @@ impl Vacuum { support::child(&self.syntax) } #[inline] + pub fn analyse_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::ANALYSE_KW) + } + #[inline] + pub fn analyze_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::ANALYZE_KW) + } + #[inline] + pub fn freeze_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::FREEZE_KW) + } + #[inline] + pub fn full_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::FULL_KW) + } + #[inline] pub fn vacuum_token(&self) -> Option { support::token(&self.syntax, SyntaxKind::VACUUM_KW) } + #[inline] + pub fn verbose_token(&self) -> Option { + support::token(&self.syntax, SyntaxKind::VERBOSE_KW) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -15253,8 +15342,8 @@ pub struct VacuumOption { } impl VacuumOption { #[inline] - pub fn full_token(&self) -> Option { - support::token(&self.syntax, SyntaxKind::FULL_KW) + pub fn literal(&self) -> Option { + support::child(&self.syntax) } } @@ -16412,7 +16501,7 @@ pub enum Expr { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum FuncOption { AsFuncOption(AsFuncOption), - BeginFuncOption(BeginFuncOption), + BeginFuncOptionList(BeginFuncOptionList), CostFuncOption(CostFuncOption), LanguageFuncOption(LanguageFuncOption), LeakproofFuncOption(LeakproofFuncOption), @@ -18036,6 +18125,24 @@ impl AstNode for BeginFuncOption { &self.syntax } } +impl AstNode for BeginFuncOptionList { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + kind == SyntaxKind::BEGIN_FUNC_OPTION_LIST + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} impl AstNode for BetweenExpr { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -26748,6 +26855,42 @@ impl AstNode for Table { &self.syntax } } +impl AstNode for TableAndColumns { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + kind == SyntaxKind::TABLE_AND_COLUMNS + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl AstNode for TableAndColumnsList { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + kind == SyntaxKind::TABLE_AND_COLUMNS_LIST + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} impl AstNode for TableArgList { #[inline] fn can_cast(kind: SyntaxKind) -> bool { @@ -29479,7 +29622,7 @@ impl AstNode for FuncOption { matches!( kind, SyntaxKind::AS_FUNC_OPTION - | SyntaxKind::BEGIN_FUNC_OPTION + | SyntaxKind::BEGIN_FUNC_OPTION_LIST | SyntaxKind::COST_FUNC_OPTION | SyntaxKind::LANGUAGE_FUNC_OPTION | SyntaxKind::LEAKPROOF_FUNC_OPTION @@ -29500,8 +29643,8 @@ impl AstNode for FuncOption { fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { SyntaxKind::AS_FUNC_OPTION => FuncOption::AsFuncOption(AsFuncOption { syntax }), - SyntaxKind::BEGIN_FUNC_OPTION => { - FuncOption::BeginFuncOption(BeginFuncOption { syntax }) + SyntaxKind::BEGIN_FUNC_OPTION_LIST => { + FuncOption::BeginFuncOptionList(BeginFuncOptionList { syntax }) } SyntaxKind::COST_FUNC_OPTION => FuncOption::CostFuncOption(CostFuncOption { syntax }), SyntaxKind::LANGUAGE_FUNC_OPTION => { @@ -29549,7 +29692,7 @@ impl AstNode for FuncOption { fn syntax(&self) -> &SyntaxNode { match self { FuncOption::AsFuncOption(it) => &it.syntax, - FuncOption::BeginFuncOption(it) => &it.syntax, + FuncOption::BeginFuncOptionList(it) => &it.syntax, FuncOption::CostFuncOption(it) => &it.syntax, FuncOption::LanguageFuncOption(it) => &it.syntax, FuncOption::LeakproofFuncOption(it) => &it.syntax, @@ -29573,10 +29716,10 @@ impl From for FuncOption { FuncOption::AsFuncOption(node) } } -impl From for FuncOption { +impl From for FuncOption { #[inline] - fn from(node: BeginFuncOption) -> FuncOption { - FuncOption::BeginFuncOption(node) + fn from(node: BeginFuncOptionList) -> FuncOption { + FuncOption::BeginFuncOptionList(node) } } impl From for FuncOption { diff --git a/crates/squawk_syntax/src/lib.rs b/crates/squawk_syntax/src/lib.rs index f0a332dc..935eafe8 100644 --- a/crates/squawk_syntax/src/lib.rs +++ b/crates/squawk_syntax/src/lib.rs @@ -42,7 +42,7 @@ pub use squawk_parser::SyntaxKind; use ast::AstNode; use rowan::GreenNode; use syntax_error::SyntaxError; -pub use syntax_node::{SyntaxNode, SyntaxToken}; +pub use syntax_node::{SyntaxNode, SyntaxNodePtr, SyntaxToken}; pub use token_text::TokenText; /// `Parse` is the result of the parsing: a syntax tree and a collection of diff --git a/crates/squawk_syntax/src/postgresql.ungram b/crates/squawk_syntax/src/postgresql.ungram index 8ebb77fd..892c3b90 100644 --- a/crates/squawk_syntax/src/postgresql.ungram +++ b/crates/squawk_syntax/src/postgresql.ungram @@ -1128,8 +1128,14 @@ OrReplace = RetType = 'returns' Type +BeginFuncOptionList = + 'begin' 'atomic' + BeginFuncOption* + 'end' + BeginFuncOption = - 'begin' 'atomic' 'end' + Stmt ';' +| ReturnFuncOption ';' ReturnFuncOption = 'return' Expr @@ -1138,7 +1144,7 @@ FuncOptionList = options:(FuncOption*) FuncOption = - BeginFuncOption + BeginFuncOptionList | ReturnFuncOption | AsFuncOption | SetFuncOption @@ -2068,7 +2074,9 @@ AlterView = 'alter' 'view' Path Analyze = - 'analyze' 'verbose'? OptionItemList? RelationName* + ('analyze' | 'analyse') + ('verbose' | OptionItemList)? + TableAndColumnsList? // suffix it with `On` to avoid conflicting with comment nodes CommentOn = @@ -2427,6 +2435,7 @@ DropView = Explain = 'explain' + ('analyze' | 'analyse' | 'verbose')? ExplainStmt ExplainStmt = @@ -2608,11 +2617,21 @@ VacuumOptionList = Vacuum = 'vacuum' + 'full'? + 'freeze'? + 'verbose'? + ('analyze' | 'analyse')? VacuumOptionList? - RelationName + TableAndColumnsList? + +TableAndColumnsList = + TableAndColumns (',' TableAndColumns)* + +TableAndColumns = + RelationName ColumnList? VacuumOption = - 'full' + Literal? Copy = 'copy' @@ -2621,6 +2640,7 @@ Copy = ('from' ('stdin' | 'program'? Literal)) | ('to' ('stdout' | 'program'? Literal)) ) + 'with'? WhereClause? Call = diff --git a/crates/squawk_syntax/src/syntax_node.rs b/crates/squawk_syntax/src/syntax_node.rs index 13658cb9..cf59b8ec 100644 --- a/crates/squawk_syntax/src/syntax_node.rs +++ b/crates/squawk_syntax/src/syntax_node.rs @@ -44,6 +44,7 @@ impl Language for Sql { pub type SyntaxNode = rowan::SyntaxNode; pub type SyntaxToken = rowan::SyntaxToken; +pub type SyntaxNodePtr = rowan::ast::SyntaxNodePtr; // pub type SyntaxElement = rowan::SyntaxElement; pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren; // pub type SyntaxElementChildren = rowan::SyntaxElementChildren;