@@ -92,10 +92,12 @@ ASTNode *root = NULL;
9292%type <node> assignment
9393%type <node> literal identifier sizeof_expression
9494%type <expr_list> array_init initializer_list
95+ %type <expr_list> row_list row
9596%type <node> function_def
9697%type <node> function_def_list
9798%type <param> param_list params
9899%type <array_dims> dimensions
100+ %type <array_dims> dimensions_or_unsized
99101%type <array> multi_dimension_access
100102
101103%start program
@@ -260,11 +262,42 @@ declaration:
260262 SAFE_FREE (var);
261263 free_expression_list ($6 );
262264 }
265+ | optional_modifiers type IDENTIFIER dimensions_or_unsized EQUALS array_init
266+ {
267+ Variable *var = variable_new($3 );
268+ add_variable_to_scope ($3 , var);
269+ ArrayDimensions dims = $4 ;
270+ if (dims.num_dimensions == 0 ) {
271+ size_t n = count_expression_list($6 );
272+ if (n <= 0 || n > MAX_DIMENSIONS ? 0 : 0 ) { /* keep structure, no-op */ }
273+ dims.dimensions[0 ] = (int )n;
274+ dims.num_dimensions = 1 ;
275+ } else if (dims.dimensions[0 ] == 0 && dims.num_dimensions >= 2 ) {
276+ /* Partially unsized: infer first dimension by dividing total inits by product of trailing dims */
277+ size_t total_inits = count_expression_list($6 );
278+ size_t trailing = 1 ;
279+ for (int i = 1 ; i < dims.num_dimensions; i++) trailing *= (size_t )dims.dimensions[i];
280+ if (trailing == 0 ) { yyerror (" Invalid array dimensions" ); YYABORT ; }
281+ if (total_inits % trailing != 0 ) { yyerror (" Initializer count does not match array dimensions" ); YYABORT ; }
282+ size_t first = total_inits / trailing;
283+ dims.dimensions[0 ] = (int )first;
284+ }
285+ int tmp_dims[MAX_DIMENSIONS];
286+ for (int i = 0 ; i < dims.num_dimensions; i++) tmp_dims[i] = dims.dimensions[i];
287+ set_multi_array_variable ($3 , tmp_dims, dims.num_dimensions, get_current_modifiers(), $2);
288+ populate_multi_array_variable ($3 , $6 , tmp_dims, dims.num_dimensions);
289+ $$ = create_multi_array_declaration_node($3 , tmp_dims, dims.num_dimensions, $2 );
290+ SAFE_FREE ($3 );
291+ SAFE_FREE (var);
292+ free_expression_list ($6 );
293+ }
263294 ;
264295
265296array_init :
266297 LBRACE initializer_list RBRACE
267298 { $$ = $2 ; }
299+ | LBRACE row_list RBRACE
300+ { $$ = $2 ; }
268301 ;
269302
270303dimensions :
@@ -284,13 +317,56 @@ dimensions:
284317 }
285318 ;
286319
320+ dimensions_or_unsized :
321+ LBRACKET RBRACKET
322+ {
323+ $$ .num_dimensions = 0 ; /* marker for unsized 1D array to infer */
324+ }
325+ | LBRACKET RBRACKET dimensions
326+ {
327+ /* Partially unsized: infer first dimension later */
328+ $$ .dimensions[0 ] = 0 ;
329+ for (int i = 0 ; i < $3 .num_dimensions; i++) {
330+ $$ .dimensions[i + 1 ] = $3 .dimensions[i];
331+ }
332+ $$ .num_dimensions = $3 .num_dimensions + 1 ;
333+ }
334+ | dimensions
335+ { $$ = $1 ; }
336+ ;
337+
287338initializer_list :
288339 expression
289340 { $$ = create_expression_list($1 ); }
290341 | initializer_list COMMA expression
291342 { $$ = append_expression_list($1 , $3 ); }
292343 ;
293344
345+ row_list :
346+ row
347+ { $$ = $1 ; }
348+ | row_list COMMA row
349+ {
350+ ExpressionList *acc = $1 ;
351+ ExpressionList *start = $3 ;
352+ if (start) {
353+ ExpressionList *cur = start;
354+ do {
355+ acc = append_expression_list(acc, cur->expr);
356+ cur = cur->next;
357+ } while (cur != start);
358+ /* Free the temporary 'start' list nodes now that we've copied exprs */
359+ free_expression_list (start);
360+ }
361+ $$ = acc;
362+ }
363+ ;
364+
365+ row :
366+ LBRACE initializer_list RBRACE
367+ { $$ = $2 ; }
368+ ;
369+
294370optional_modifiers :
295371 /* empty */
296372 { /* No action needed */ }
0 commit comments