@@ -21,6 +21,7 @@ use gitql_ast::types::any::AnyType;
2121use gitql_ast:: types:: array:: ArrayType ;
2222use gitql_ast:: types:: boolean:: BoolType ;
2323use gitql_ast:: types:: composite:: CompositeType ;
24+ use gitql_ast:: types:: row:: RowType ;
2425use gitql_ast:: types:: undefined:: UndefType ;
2526use gitql_ast:: types:: DataType ;
2627use gitql_core:: environment:: Environment ;
@@ -3396,7 +3397,7 @@ pub(crate) fn parse_member_access_expression(
33963397
33973398 // The syntax for member access is (composite).member
33983399 // The composite expr must be in group, that make it different from table access table.name
3399- if expr. kind ( ) != ExprKind :: Grouping {
3400+ if expr. kind ( ) != ExprKind :: Column {
34003401 return Err (
34013402 Diagnostic :: error ( "Dot token expect composite value between `(` and `)`" )
34023403 . add_note ( "The syntax for accessing composite element is (composite).member" )
@@ -3474,7 +3475,7 @@ fn parse_primary_expression(
34743475 TokenKind :: Symbol ( _) => parse_symbol_expression ( context, env, tokens, position) ,
34753476 TokenKind :: Array => parse_array_value_expression ( context, env, tokens, position) ,
34763477 TokenKind :: LeftBracket => parse_array_value_expression ( context, env, tokens, position) ,
3477- TokenKind :: LeftParen => parse_group_expression ( context, env, tokens, position) ,
3478+ TokenKind :: LeftParen => parse_column_or_row_expression ( context, env, tokens, position) ,
34783479 TokenKind :: Case => parse_case_expression ( context, env, tokens, position) ,
34793480 TokenKind :: Cast => parse_cast_call_expression ( context, env, tokens, position) ,
34803481 TokenKind :: Benchmark => parse_benchmark_call_expression ( context, env, tokens, position) ,
@@ -3721,27 +3722,57 @@ fn parse_array_value_expression(
37213722 } ) )
37223723}
37233724
3724- fn parse_group_expression (
3725+ fn parse_column_or_row_expression (
37253726 context : & mut ParserContext ,
37263727 env : & mut Environment ,
37273728 tokens : & [ Token ] ,
37283729 position : & mut usize ,
37293730) -> Result < Box < dyn Expr > , Box < Diagnostic > > {
37303731 // Consume '(' token
3731- * position += 1 ;
3732+ consume_token_or_error (
3733+ tokens,
3734+ position,
3735+ TokenKind :: LeftParen ,
3736+ "Expect `(` at the start of column or row expression" ,
3737+ ) ?;
37323738
3733- let expression = parse_expression ( context, env, tokens, position) ?;
3734- if tokens[ * position] . kind != TokenKind :: RightParen {
3735- return Err ( Diagnostic :: error ( "Expect `)` to end group expression" )
3739+ let mut exprs = vec ! [ ] ;
3740+ while !is_current_token ( tokens, position, TokenKind :: RightParen ) {
3741+ exprs. push ( parse_expression ( context, env, tokens, position) ?) ;
3742+
3743+ if !is_current_token ( tokens, position, TokenKind :: Comma ) {
3744+ break ;
3745+ }
3746+
3747+ // Consume `,`
3748+ * position += 1 ;
3749+ }
3750+
3751+ if exprs. is_empty ( ) {
3752+ return Err ( Diagnostic :: error ( "Column or Row expression can't be empty" )
37363753 . with_location ( calculate_safe_location ( tokens, * position) )
3737- . add_help ( "Try to add ')' at the end of group expression" )
37383754 . as_boxed ( ) ) ;
37393755 }
37403756
37413757 // Consume ')' token
3742- * position += 1 ;
3758+ consume_token_or_error (
3759+ tokens,
3760+ position,
3761+ TokenKind :: RightParen ,
3762+ "Expect `(` at the end of column or row expression" ,
3763+ ) ?;
37433764
3744- Ok ( Box :: new ( GroupExpr { expr : expression } ) )
3765+ if exprs. len ( ) == 1 {
3766+ let expr = exprs[ 0 ] . clone ( ) ;
3767+ Ok ( Box :: new ( ColumnExpr { expr } ) )
3768+ } else {
3769+ let mut column_types = Vec :: with_capacity ( exprs. len ( ) ) ;
3770+ for expr in exprs. iter ( ) {
3771+ column_types. push ( expr. expr_type ( ) ) ;
3772+ }
3773+ let row_type = RowType :: new ( column_types) ;
3774+ Ok ( Box :: new ( RowExpr { exprs, row_type } ) )
3775+ }
37453776}
37463777
37473778fn parse_case_expression (
0 commit comments