summaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-18 15:57:40 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-18 15:57:40 +0000
commit43c4f78eb3d2af7778bab6e51d77588bec62930d (patch)
treef8614e429ef913467420af7d08d104030ec6d434 /src/parser
parenta7eceb21faf04762379f2ce4d23d21bbc8c11929 (diff)
Update docs + add '..<' + add typed embed.
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/parser.h2
-rw-r--r--src/parser/parser_expr.c6
-rw-r--r--src/parser/parser_stmt.c22
-rw-r--r--src/parser/parser_type.c110
4 files changed, 120 insertions, 20 deletions
diff --git a/src/parser/parser.h b/src/parser/parser.h
index f54bae0..cfe486d 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -394,7 +394,7 @@ ASTNode *parse_lambda(ParserContext *ctx, Lexer *l);
char *parse_condition_raw(ParserContext *ctx, Lexer *l);
char *parse_array_literal(ParserContext *ctx, Lexer *l, const char *st);
char *parse_tuple_literal(ParserContext *ctx, Lexer *l, const char *tn);
-char *parse_embed(ParserContext *ctx, Lexer *l);
+ASTNode *parse_embed(ParserContext *ctx, Lexer *l);
ASTNode *parse_macro_call(ParserContext *ctx, Lexer *l, char *name);
ASTNode *parse_statement(ParserContext *ctx, Lexer *l);
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 99ce7d1..b9f022a 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -3075,10 +3075,10 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
}
// Case: [..] or [..end]
- if (lexer_peek(l).type == TOK_DOTDOT)
+ if (lexer_peek(l).type == TOK_DOTDOT || lexer_peek(l).type == TOK_DOTDOT_LT)
{
is_slice = 1;
- lexer_next(l); // consume ..
+ lexer_next(l); // consume .. or ..<
if (lexer_peek(l).type != TOK_RBRACKET)
{
end = parse_expression(ctx, l);
@@ -3088,7 +3088,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
{
// Case: [start] or [start..] or [start..end]
start = parse_expression(ctx, l);
- if (lexer_peek(l).type == TOK_DOTDOT)
+ if (lexer_peek(l).type == TOK_DOTDOT || lexer_peek(l).type == TOK_DOTDOT_LT)
{
is_slice = 1;
lexer_next(l); // consume ..
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index 6a0f50d..5307768 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -242,11 +242,12 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l)
p_str = tmp;
}
- // Check for range pattern: value..end or value..=end
- if (lexer_peek(l).type == TOK_DOTDOT || lexer_peek(l).type == TOK_DOTDOT_EQ)
+ // Check for range pattern: value..end, value..<end or value..=end
+ if (lexer_peek(l).type == TOK_DOTDOT || lexer_peek(l).type == TOK_DOTDOT_EQ ||
+ lexer_peek(l).type == TOK_DOTDOT_LT)
{
int is_inclusive = (lexer_peek(l).type == TOK_DOTDOT_EQ);
- lexer_next(l); // eat .. or ..=
+ lexer_next(l); // eat operator
Token end_tok = lexer_next(l);
char *end_str = token_strdup(end_tok);
@@ -1071,9 +1072,12 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l)
Token next = lexer_peek(l);
if (next.type == TOK_IDENT && strncmp(next.start, "embed", 5) == 0)
{
- char *e = parse_embed(ctx, l);
- init = ast_create(NODE_RAW_STMT);
- init->raw_stmt.content = e;
+ init = parse_embed(ctx, l);
+
+ if (!type && init->type_info)
+ {
+ type = type_to_string(init->type_info);
+ }
if (!type)
{
register_slice(ctx, "char");
@@ -1583,9 +1587,9 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
{
ASTNode *start_expr = parse_expression(ctx, l);
int is_inclusive = 0;
- if (lexer_peek(l).type == TOK_DOTDOT)
+ if (lexer_peek(l).type == TOK_DOTDOT || lexer_peek(l).type == TOK_DOTDOT_LT)
{
- lexer_next(l); // consume ..
+ lexer_next(l); // consume .. or ..<
}
else if (lexer_peek(l).type == TOK_DOTDOT_EQ)
@@ -3327,7 +3331,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
continue;
}
- // --- HANDLE 'use' (Struct Embedding) ---
+ // Handle 'use' (Struct Embedding)
if (t.type == TOK_USE)
{
lexer_next(l); // eat use
diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c
index 27328fe..3d5bff8 100644
--- a/src/parser/parser_type.c
+++ b/src/parser/parser_type.c
@@ -874,7 +874,7 @@ char *parse_tuple_literal(ParserContext *ctx, Lexer *l, const char *tn)
free(c);
return o;
}
-char *parse_embed(ParserContext *ctx, Lexer *l)
+ASTNode *parse_embed(ParserContext *ctx, Lexer *l)
{
lexer_next(l);
Token t = lexer_next(l);
@@ -886,6 +886,15 @@ char *parse_embed(ParserContext *ctx, Lexer *l)
strncpy(fn, t.start + 1, t.len - 2);
fn[t.len - 2] = 0;
+ // Check for optional "as Type"
+ Type *target_type = NULL;
+ if (lexer_peek(l).type == TOK_IDENT && lexer_peek(l).len == 2 &&
+ strncmp(lexer_peek(l).start, "as", 2) == 0)
+ {
+ lexer_next(l); // consume 'as'
+ target_type = parse_type_formal(ctx, l);
+ }
+
FILE *f = fopen(fn, "rb");
if (!f)
{
@@ -898,16 +907,103 @@ char *parse_embed(ParserContext *ctx, Lexer *l)
fread(b, 1, len, f);
fclose(f);
- register_slice(ctx, "char");
- size_t oc = len * 6 + 128;
+ size_t oc = len * 6 + 256;
char *o = xmalloc(oc);
- sprintf(o, "(Slice_char){.data=(char[]){");
+
+ // Default Type if none
+ if (!target_type)
+ {
+ // Default: Slice_char
+ register_slice(ctx, "char");
+
+ Type *slice_type = type_new(TYPE_STRUCT);
+ slice_type->name = xstrdup("Slice_char");
+ target_type = slice_type;
+
+ sprintf(o, "(Slice_char){.data=(char[]){");
+ }
+ else
+ {
+ // Handle specific type
+ char *ts = type_to_string(target_type);
+
+ if (target_type->kind == TYPE_ARRAY)
+ {
+ char *inner_ts = type_to_string(target_type->inner);
+ if (target_type->array_size > 0)
+ {
+ Type *ptr_type = type_new_ptr(target_type->inner); // Reuse inner
+ target_type = ptr_type;
+ sprintf(o, "(%s[]){", inner_ts);
+ }
+ else
+ {
+ // Slice -> Slice_T struct
+ register_slice(ctx, inner_ts);
+ char slice_name[256];
+ sprintf(slice_name, "Slice_%s", inner_ts);
+ Type *slice_t = type_new(TYPE_STRUCT);
+ slice_t->name = xstrdup(slice_name);
+ target_type = slice_t;
+ sprintf(o, "(%s){.data=(%s[]){", slice_name, inner_ts);
+ }
+ free(inner_ts);
+ }
+ else
+ {
+ if (strcmp(ts, "string") == 0 || strcmp(ts, "char*") == 0)
+ {
+ sprintf(o, "(char*)\"");
+ }
+ else
+ {
+ sprintf(o, "(%s){", ts);
+ }
+ }
+ free(ts);
+ }
+
char *p = o + strlen(o);
+
+ // Check if string mode
+ int is_string = (target_type && (strcmp(type_to_string(target_type), "string") == 0 ||
+ strcmp(type_to_string(target_type), "char*") == 0));
+
for (int i = 0; i < len; i++)
{
- p += sprintf(p, "0x%02X,", b[i]);
+ if (is_string)
+ {
+ // Hex escape for string
+ p += sprintf(p, "\\x%02X", b[i]);
+ }
+ else
+ {
+ p += sprintf(p, "0x%02X,", b[i]);
+ }
+ }
+
+ if (is_string)
+ {
+ sprintf(p, "\"");
}
- sprintf(p, "},.len=%ld,.cap=%ld}", len, len);
+ else
+ {
+ int is_slice = (strncmp(o, "(Slice_", 7) == 0);
+
+ if (is_slice)
+ {
+ sprintf(p, "},.len=%ld,.cap=%ld}", len, len);
+ }
+ else
+ {
+ sprintf(p, "}");
+ }
+ }
+
free(b);
- return o;
+
+ ASTNode *n = ast_create(NODE_RAW_STMT);
+ n->raw_stmt.content = o;
+ n->type_info = target_type;
+ return n;
}