@@ -203,8 +203,30 @@ static Expr* parse_primary(Parser* parser) {
203203 Stmt * body = parse_block (parser );
204204 return expr_lambda (params , ret , body , lambda_tok .line , lambda_tok .column );
205205 }
206- if (match (parser , TOKEN_IDENT )) {
207- return expr_ident (token .literal , token .line , token .column );
206+ if (parser -> current_token .type == TOKEN_IDENT ) {
207+ Token idtok = parser -> current_token ;
208+ // Build possibly-dotted identifier by concatenating IDENT (DOT IDENT)*
209+ size_t len0 = idtok .literal ? strlen (idtok .literal ) : 0 ;
210+ char * name = malloc (len0 + 1 );
211+ if (!name ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
212+ if (len0 ) memcpy (name , idtok .literal , len0 + 1 ); else name [0 ] = '\0' ;
213+ advance (parser ); // consume first IDENT
214+ while (parser -> current_token .type == TOKEN_DOT && parser -> next_token .type == TOKEN_IDENT ) {
215+ advance (parser ); // consume DOT
216+ // append '.' + next ident
217+ const char * part = parser -> current_token .literal ? parser -> current_token .literal : "" ;
218+ size_t part_len = strlen (part );
219+ size_t cur_len = strlen (name );
220+ size_t newlen = cur_len + 1 + part_len + 1 ;
221+ char * tmp = realloc (name , newlen );
222+ if (!tmp ) { free (name ); fprintf (stderr , "Out of memory\n" ); exit (1 ); }
223+ name = tmp ;
224+ name [cur_len ] = '.' ;
225+ if (part_len ) memcpy (name + cur_len + 1 , part , part_len );
226+ name [cur_len + 1 + part_len ] = '\0' ;
227+ advance (parser ); // consume IDENT
228+ }
229+ return expr_ident (name , idtok .line , idtok .column );
208230 }
209231 if (match (parser , TOKEN_LPAREN )) {
210232 Expr * expr = parse_expression (parser );
0 commit comments