@@ -1559,6 +1559,43 @@ impl<'a> Parser<'a> {
15591559 Keyword::LAMBDA if self.dialect.supports_lambda_functions() => {
15601560 Ok(Some(self.parse_lambda_expr()?))
15611561 }
1562+ Keyword::FILTER
1563+ | Keyword::TRANSFORM
1564+ | Keyword::REDUCE if self.dialect.supports_lambda_functions() => {
1565+ self.expect_token(&Token::LParen)?;
1566+ let array = self.parse_expr()?;
1567+ self.expect_token(&Token::Comma)?;
1568+ let initial_value = if w.keyword == Keyword::REDUCE {
1569+ let initial_value = self.parse_expr()?;
1570+ self.expect_token(&Token::Comma)?;
1571+ Some(initial_value)
1572+ } else {
1573+ None
1574+ };
1575+ let lambda = self.parse_lambda_expr_with_typed_args()?;
1576+ let mut args = vec![
1577+ FunctionArg::Unnamed(FunctionArgExpr::Expr(array)),
1578+ FunctionArg::Unnamed(FunctionArgExpr::Expr(lambda)),
1579+ ];
1580+ if let Some(initial_value) = initial_value {
1581+ args.insert(1, FunctionArg::Unnamed(FunctionArgExpr::Expr(initial_value)));
1582+ }
1583+ self.expect_token(&Token::RParen)?;
1584+ Ok(Some(Expr::Function(Function {
1585+ name: ObjectName::from(vec![w.to_ident(w_span)]),
1586+ uses_odbc_syntax: false,
1587+ parameters: FunctionArguments::None,
1588+ args: FunctionArguments::List(FunctionArgumentList {
1589+ duplicate_treatment: None,
1590+ clauses: vec![],
1591+ args,
1592+ }),
1593+ filter: None,
1594+ null_treatment: None,
1595+ over: None,
1596+ within_group: vec![],
1597+ })))
1598+ }
15621599 _ if self.dialect.supports_geometric_types() => match w.keyword {
15631600 Keyword::CIRCLE => Ok(Some(self.parse_geometric_type(GeometricTypeKind::Circle)?)),
15641601 Keyword::BOX => Ok(Some(self.parse_geometric_type(GeometricTypeKind::GeometricBox)?)),
@@ -1617,21 +1654,6 @@ impl<'a> Parser<'a> {
16171654 syntax: LambdaSyntax::Arrow,
16181655 }))
16191656 }
1620- Token::Word(_)
1621- if self.peek_nth_token(1).token == Token::Arrow
1622- && self.dialect.supports_lambda_functions() =>
1623- {
1624- let first_param = LambdaFunctionParameter {
1625- name: w.to_ident(self.peek_nth_token_ref(1).span),
1626- data_type: self.maybe_parse(|parser| parser.parse_data_type())?,
1627- };
1628- self.expect_token(&Token::Arrow)?;
1629- Ok(Expr::Lambda(LambdaFunction {
1630- params: OneOrManyWithParens::One(first_param),
1631- body: Box::new(self.parse_expr()?),
1632- syntax: LambdaSyntax::Arrow,
1633- }))
1634- }
16351657 _ => Ok(Expr::Identifier(w.to_ident(w_span))),
16361658 }
16371659 }
@@ -2213,12 +2235,7 @@ impl<'a> Parser<'a> {
22132235 return Ok(None);
22142236 }
22152237 self.maybe_parse(|p| {
2216- let params = p.parse_comma_separated(|p| {
2217- Ok(LambdaFunctionParameter {
2218- name: p.parse_identifier()?,
2219- data_type: None,
2220- })
2221- })?;
2238+ let params = p.parse_comma_separated(|p| p.parse_lambda_function_parameter(false))?;
22222239 p.expect_token(&Token::RParen)?;
22232240 p.expect_token(&Token::Arrow)?;
22242241 let expr = p.parse_expr()?;
@@ -2230,6 +2247,18 @@ impl<'a> Parser<'a> {
22302247 })
22312248 }
22322249
2250+ /// Parses a lambda expression using the arrow syntax with optionally typed arguments.
2251+ fn parse_lambda_expr_with_typed_args(&mut self) -> Result<Expr, ParserError> {
2252+ let params = self.parse_lambda_function_parameters(true)?;
2253+ self.expect_token(&Token::Arrow)?;
2254+ let body = self.parse_expr()?;
2255+ Ok(Expr::Lambda(LambdaFunction {
2256+ params,
2257+ body: Box::new(body),
2258+ syntax: LambdaSyntax::Arrow,
2259+ }))
2260+ }
2261+
22332262 /// Parses a lambda expression using the `LAMBDA` keyword syntax.
22342263 ///
22352264 /// Syntax: `LAMBDA <params> : <expr>`
@@ -2240,40 +2269,55 @@ impl<'a> Parser<'a> {
22402269 ///
22412270 /// See <https://duckdb.org/docs/stable/sql/functions/lambda>
22422271 fn parse_lambda_expr(&mut self) -> Result<Expr, ParserError> {
2272+ // Parse the parameters: either a single identifier or comma-separated identifiers
2273+ let params = self.parse_lambda_function_parameters(false)?;
2274+ // Expect the colon separator
2275+ self.expect_token(&Token::Colon)?;
2276+ // Parse the body expression
2277+ let body = self.parse_expr()?;
2278+ Ok(Expr::Lambda(LambdaFunction {
2279+ params,
2280+ body: Box::new(body),
2281+ syntax: LambdaSyntax::LambdaKeyword,
2282+ }))
2283+ }
2284+
2285+ /// Parses the parameters of a lambda function with optional typing.
2286+ fn parse_lambda_function_parameters(
2287+ &mut self,
2288+ typed: bool,
2289+ ) -> Result<OneOrManyWithParens<LambdaFunctionParameter>, ParserError> {
22432290 // Parse the parameters: either a single identifier or comma-separated identifiers
22442291 let params = if self.consume_token(&Token::LParen) {
22452292 // Parenthesized parameters: (x, y)
2246- let params = self.parse_comma_separated(|p| {
2247- Ok(LambdaFunctionParameter {
2248- name: p.parse_identifier()?,
2249- data_type: None,
2250- })
2251- })?;
2293+ let params =
2294+ self.parse_comma_separated(|p| p.parse_lambda_function_parameter(typed))?;
22522295 self.expect_token(&Token::RParen)?;
22532296 OneOrManyWithParens::Many(params)
22542297 } else {
22552298 // Unparenthesized parameters: x or x, y
2256- let params = self.parse_comma_separated(|p| {
2257- Ok(LambdaFunctionParameter {
2258- name: p.parse_identifier()?,
2259- data_type: None,
2260- })
2261- })?;
2299+ let params =
2300+ self.parse_comma_separated(|p| p.parse_lambda_function_parameter(typed))?;
22622301 if params.len() == 1 {
22632302 OneOrManyWithParens::One(params.into_iter().next().unwrap())
22642303 } else {
22652304 OneOrManyWithParens::Many(params)
22662305 }
22672306 };
2268- // Expect the colon separator
2269- self.expect_token(&Token::Colon)?;
2270- // Parse the body expression
2271- let body = self.parse_expr()?;
2272- Ok(Expr::Lambda(LambdaFunction {
2273- params,
2274- body: Box::new(body),
2275- syntax: LambdaSyntax::LambdaKeyword,
2276- }))
2307+ Ok(params)
2308+ }
2309+
2310+ /// Parses a single parameter of a lambda function, with optional typing.
2311+ fn parse_lambda_function_parameter(
2312+ &mut self,
2313+ typed: bool,
2314+ ) -> Result<LambdaFunctionParameter, ParserError> {
2315+ let name = self.parse_identifier()?;
2316+ let data_type = match self.peek_token().token {
2317+ Token::Word(_) if typed => self.maybe_parse(|p| p.parse_data_type())?,
2318+ _ => None,
2319+ };
2320+ Ok(LambdaFunctionParameter { name, data_type })
22772321 }
22782322
22792323 /// Tries to parse the body of an [ODBC escaping sequence]
0 commit comments