@@ -1556,6 +1556,43 @@ impl<'a> Parser<'a> {
15561556 Keyword::LAMBDA if self.dialect.supports_lambda_functions() => {
15571557 Ok(Some(self.parse_lambda_expr()?))
15581558 }
1559+ Keyword::FILTER
1560+ | Keyword::TRANSFORM
1561+ | Keyword::REDUCE if self.dialect.supports_lambda_functions() => {
1562+ self.expect_token(&Token::LParen)?;
1563+ let array = self.parse_expr()?;
1564+ self.expect_token(&Token::Comma)?;
1565+ let initial_value = if w.keyword == Keyword::REDUCE {
1566+ let initial_value = self.parse_expr()?;
1567+ self.expect_token(&Token::Comma)?;
1568+ Some(initial_value)
1569+ } else {
1570+ None
1571+ };
1572+ let lambda = self.parse_lambda_expr_with_typed_args()?;
1573+ let mut args = vec![
1574+ FunctionArg::Unnamed(FunctionArgExpr::Expr(array)),
1575+ FunctionArg::Unnamed(FunctionArgExpr::Expr(lambda)),
1576+ ];
1577+ if let Some(initial_value) = initial_value {
1578+ args.insert(1, FunctionArg::Unnamed(FunctionArgExpr::Expr(initial_value)));
1579+ }
1580+ self.expect_token(&Token::RParen)?;
1581+ Ok(Some(Expr::Function(Function {
1582+ name: ObjectName::from(vec![w.to_ident(w_span)]),
1583+ uses_odbc_syntax: false,
1584+ parameters: FunctionArguments::None,
1585+ args: FunctionArguments::List(FunctionArgumentList {
1586+ duplicate_treatment: None,
1587+ clauses: vec![],
1588+ args,
1589+ }),
1590+ filter: None,
1591+ null_treatment: None,
1592+ over: None,
1593+ within_group: vec![],
1594+ })))
1595+ }
15591596 _ if self.dialect.supports_geometric_types() => match w.keyword {
15601597 Keyword::CIRCLE => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Circle)?)),
15611598 Keyword::BOX => Ok(Some(self.parse_geometric_type(GeometricTypeKind::GeometricBox)?)),
@@ -1614,21 +1651,6 @@ impl<'a> Parser<'a> {
16141651 syntax: LambdaSyntax::Arrow,
16151652 }))
16161653 }
1617- Token::Word(_)
1618- if self.peek_nth_token(1).token == Token::Arrow
1619- && self.dialect.supports_lambda_functions() =>
1620- {
1621- let first_param = LambdaFunctionParameter {
1622- name: w.to_ident(self.peek_nth_token_ref(1).span),
1623- data_type: self.maybe_parse(|parser| parser.parse_data_type())?,
1624- };
1625- self.expect_token(&Token::Arrow)?;
1626- Ok(Expr::Lambda(LambdaFunction {
1627- params: OneOrManyWithParens::One(first_param),
1628- body: Box::new(self.parse_expr()?),
1629- syntax: LambdaSyntax::Arrow,
1630- }))
1631- }
16321654 _ => Ok(Expr::Identifier(w.to_ident(w_span))),
16331655 }
16341656 }
@@ -2210,12 +2232,7 @@ impl<'a> Parser<'a> {
22102232 return Ok(None);
22112233 }
22122234 self.maybe_parse(|p| {
2213- let params = p.parse_comma_separated(|p| {
2214- Ok(LambdaFunctionParameter {
2215- name: p.parse_identifier()?,
2216- data_type: None,
2217- })
2218- })?;
2235+ let params = p.parse_comma_separated(|p| p.parse_lambda_function_parameter(false))?;
22192236 p.expect_token(&Token::RParen)?;
22202237 p.expect_token(&Token::Arrow)?;
22212238 let expr = p.parse_expr()?;
@@ -2227,6 +2244,18 @@ impl<'a> Parser<'a> {
22272244 })
22282245 }
22292246
2247+ /// Parses a lambda expression using the arrow syntax with optionally typed arguments.
2248+ fn parse_lambda_expr_with_typed_args(&mut self) -> Result<Expr, ParserError> {
2249+ let params = self.parse_lambda_function_parameters(true)?;
2250+ self.expect_token(&Token::Arrow)?;
2251+ let body = self.parse_expr()?;
2252+ Ok(Expr::Lambda(LambdaFunction {
2253+ params,
2254+ body: Box::new(body),
2255+ syntax: LambdaSyntax::Arrow,
2256+ }))
2257+ }
2258+
22302259 /// Parses a lambda expression using the `LAMBDA` keyword syntax.
22312260 ///
22322261 /// Syntax: `LAMBDA <params> : <expr>`
@@ -2237,40 +2266,55 @@ impl<'a> Parser<'a> {
22372266 ///
22382267 /// See <https://duckdb.org/docs/stable/sql/functions/lambda>
22392268 fn parse_lambda_expr(&mut self) -> Result<Expr, ParserError> {
2269+ // Parse the parameters: either a single identifier or comma-separated identifiers
2270+ let params = self.parse_lambda_function_parameters(false)?;
2271+ // Expect the colon separator
2272+ self.expect_token(&Token::Colon)?;
2273+ // Parse the body expression
2274+ let body = self.parse_expr()?;
2275+ Ok(Expr::Lambda(LambdaFunction {
2276+ params,
2277+ body: Box::new(body),
2278+ syntax: LambdaSyntax::LambdaKeyword,
2279+ }))
2280+ }
2281+
2282+ /// Parses the parameters of a lambda function with optional typing.
2283+ fn parse_lambda_function_parameters(
2284+ &mut self,
2285+ typed: bool,
2286+ ) -> Result<OneOrManyWithParens<LambdaFunctionParameter>, ParserError> {
22402287 // Parse the parameters: either a single identifier or comma-separated identifiers
22412288 let params = if self.consume_token(&Token::LParen) {
22422289 // Parenthesized parameters: (x, y)
2243- let params = self.parse_comma_separated(|p| {
2244- Ok(LambdaFunctionParameter {
2245- name: p.parse_identifier()?,
2246- data_type: None,
2247- })
2248- })?;
2290+ let params =
2291+ self.parse_comma_separated(|p| p.parse_lambda_function_parameter(typed))?;
22492292 self.expect_token(&Token::RParen)?;
22502293 OneOrManyWithParens::Many(params)
22512294 } else {
22522295 // Unparenthesized parameters: x or x, y
2253- let params = self.parse_comma_separated(|p| {
2254- Ok(LambdaFunctionParameter {
2255- name: p.parse_identifier()?,
2256- data_type: None,
2257- })
2258- })?;
2296+ let params =
2297+ self.parse_comma_separated(|p| p.parse_lambda_function_parameter(typed))?;
22592298 if params.len() == 1 {
22602299 OneOrManyWithParens::One(params.into_iter().next().unwrap())
22612300 } else {
22622301 OneOrManyWithParens::Many(params)
22632302 }
22642303 };
2265- // Expect the colon separator
2266- self.expect_token(&Token::Colon)?;
2267- // Parse the body expression
2268- let body = self.parse_expr()?;
2269- Ok(Expr::Lambda(LambdaFunction {
2270- params,
2271- body: Box::new(body),
2272- syntax: LambdaSyntax::LambdaKeyword,
2273- }))
2304+ Ok(params)
2305+ }
2306+
2307+ /// Parses a single parameter of a lambda function, with optional typing.
2308+ fn parse_lambda_function_parameter(
2309+ &mut self,
2310+ typed: bool,
2311+ ) -> Result<LambdaFunctionParameter, ParserError> {
2312+ let name = self.parse_identifier()?;
2313+ let data_type = match self.peek_token().token {
2314+ Token::Word(_) if typed => self.maybe_parse(|p| p.parse_data_type())?,
2315+ _ => None,
2316+ };
2317+ Ok(LambdaFunctionParameter { name, data_type })
22742318 }
22752319
22762320 /// Tries to parse the body of an [ODBC escaping sequence]
0 commit comments