@@ -3532,16 +3532,11 @@ impl<'a> Parser<'a> {
35323532 // e.g. `SELECT 1, 2, FROM t`
35333533 // https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#trailing_commas
35343534 // https://docs.snowflake.com/en/release-notes/2024/8_11#select-supports-trailing-commas
3535- //
3536- // This pattern could be captured better with RAII type semantics, but it's quite a bit of
3537- // code to add for just one case, so we'll just do it manually here.
3538- let old_value = self.options.trailing_commas;
3539- self.options.trailing_commas |= self.dialect.supports_projection_trailing_commas();
35403535
3541- let ret = self.parse_comma_separated(|p| p.parse_select_item());
3542- self.options.trailing_commas = old_value ;
3536+ let trailing_commas =
3537+ self.options.trailing_commas | self.dialect.supports_projection_trailing_commas() ;
35433538
3544- ret
3539+ self.parse_comma_separated_with_trailing_commas(|p| p.parse_select_item(), trailing_commas)
35453540 }
35463541
35473542 pub fn parse_actions_list(&mut self) -> Result<Vec<ParsedAction>, ParserError> {
@@ -3568,11 +3563,12 @@ impl<'a> Parser<'a> {
35683563 }
35693564
35703565 /// Parse the comma of a comma-separated syntax element.
3566+ /// Allows for control over trailing commas
35713567 /// Returns true if there is a next element
3572- fn is_parse_comma_separated_end (&mut self) -> bool {
3568+ fn is_parse_comma_separated_end_with_trailing_commas (&mut self, trailing_commas: bool ) -> bool {
35733569 if !self.consume_token(&Token::Comma) {
35743570 true
3575- } else if self.options. trailing_commas {
3571+ } else if trailing_commas {
35763572 let token = self.peek_token().token;
35773573 match token {
35783574 Token::Word(ref kw)
@@ -3590,15 +3586,34 @@ impl<'a> Parser<'a> {
35903586 }
35913587 }
35923588
3589+ /// Parse the comma of a comma-separated syntax element.
3590+ /// Returns true if there is a next element
3591+ fn is_parse_comma_separated_end(&mut self) -> bool {
3592+ self.is_parse_comma_separated_end_with_trailing_commas(self.options.trailing_commas)
3593+ }
3594+
35933595 /// Parse a comma-separated list of 1+ items accepted by `F`
3594- pub fn parse_comma_separated<T, F>(&mut self, mut f: F) -> Result<Vec<T>, ParserError>
3596+ pub fn parse_comma_separated<T, F>(&mut self, f: F) -> Result<Vec<T>, ParserError>
3597+ where
3598+ F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
3599+ {
3600+ self.parse_comma_separated_with_trailing_commas(f, self.options.trailing_commas)
3601+ }
3602+
3603+ /// Parse a comma-separated list of 1+ items accepted by `F`
3604+ /// Allows for control over trailing commas
3605+ fn parse_comma_separated_with_trailing_commas<T, F>(
3606+ &mut self,
3607+ mut f: F,
3608+ trailing_commas: bool,
3609+ ) -> Result<Vec<T>, ParserError>
35953610 where
35963611 F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>,
35973612 {
35983613 let mut values = vec![];
35993614 loop {
36003615 values.push(f(self)?);
3601- if self.is_parse_comma_separated_end( ) {
3616+ if self.is_parse_comma_separated_end_with_trailing_commas(trailing_commas ) {
36023617 break;
36033618 }
36043619 }
0 commit comments