Skip to content

Commit 1ebb84e

Browse files
gh-51: Ban . from identifiers.
1 parent 01bc9ce commit 1ebb84e

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

src/lexer.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ Token lexer_next_token(Lexer* lexer) {
242242
if (c == ':') { advance(lexer); return make_token(lexer, TOKEN_COLON, ":", 1); }
243243
if (c == '@') { advance(lexer); return make_token(lexer, TOKEN_AT, "@", 1); }
244244
if (c == '*') { advance(lexer); return make_token(lexer, TOKEN_STAR, "*", 1); }
245+
if (c == '.') { advance(lexer); return make_token(lexer, TOKEN_DOT, ".", 1); }
245246

246247
if (c == '"' || c == '\'') {
247248
return string_token(lexer, c);
@@ -457,7 +458,7 @@ static Token identifier_token(Lexer* lexer) {
457458

458459
while (!is_at_end(lexer)) {
459460
char c = peek(lexer);
460-
if (strchr("abcdefghijklmnopqrstuvwxyz1234567890./ABCDEFGHIJKLMNOPQRSTUVWXYZ$%&~_+|?", c)) {
461+
if (strchr("abcdefghijklmnopqrstuvwxyz1234567890/ABCDEFGHIJKLMNOPQRSTUVWXYZ$%&~_+|?", c)) {
461462
advance(lexer);
462463
if (len_val + 1 >= capacity) { capacity *= 2; value = safe_realloc(value, capacity); }
463464
value[len_val++] = c;

src/parser.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

src/token.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const char* token_type_to_string(PTokenType type) {
2222
case TOKEN_COLON: return "COLON";
2323
case TOKEN_AT: return "AT";
2424
case TOKEN_STAR: return "STAR";
25+
case TOKEN_DOT: return "DOT";
2526
case TOKEN_DASH: return "DASH";
2627
case TOKEN_TRY: return "TRY";
2728
case TOKEN_CATCH: return "CATCH";

src/token.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef enum {
2929
TOKEN_COLON, // :
3030
TOKEN_AT, // @
3131
TOKEN_STAR, // *
32+
TOKEN_DOT, // .
3233
TOKEN_DASH, // - (when used as slice range separator)
3334

3435
// Keywords

0 commit comments

Comments
 (0)