scripting: Added string literals
authorLukas Krickl <lukas@krickl.dev>
Fri, 20 Mar 2026 08:19:25 +0000 (09:19 +0100)
committerLukas Krickl <lukas@krickl.dev>
Fri, 20 Mar 2026 08:19:25 +0000 (09:19 +0100)
src/l_lsl.c
src/tests/lsl/strliteral.lsl [new file with mode: 0644]
src/tests/t_lsl.c
src/u_string.c
src/u_string.h

index d9837f84ef872716a17be05c3de7f0837eb3e207..7bf8286a8157dfeb484ce23a81cf07933da6b95f 100644 (file)
@@ -197,11 +197,23 @@ struct l_lsl_token l_lsl_next_token(struct l_lsl_vm *v, struct l_lsl_lex *lex) {
        } else if (c == '\'' || c == '\"') {
                /* string literal */
                /* consume initial term */
-               c = l_lsl_lex_advance(v, lex);
+               t.type = L_LSL_TOK_STRING;
                string_term = c;
+               c = l_lsl_lex_advance(v, lex);
+
                while (c && c != string_term) {
+                       /* TODO: allow escaping */
+                       l_lsl_lex_write_token(v, lex, &t, c);
                        c = l_lsl_lex_advance(v, lex);
                }
+               
+               if (c != string_term) {
+                       l_lsl_lex_err(v, lex, L_LSL_ERR_LEX, "unterminated string\n");
+                       goto fail;
+               }
+
+               /* consume final term */
+               l_lsl_lex_advance(v, lex);
        } else {
                        l_lsl_lex_err(v, lex, L_LSL_ERR_LEX, "unknown char: %c\n", c);
                        t.type = L_LSL_TOK_NONE;
@@ -215,7 +227,10 @@ struct l_lsl_token l_lsl_next_token(struct l_lsl_vm *v, struct l_lsl_lex *lex) {
                l_lsl_lex_err(v, lex, L_LSL_ERR_LEX, "unexpected end of token\n", c);
                t.type = L_LSL_TOK_NONE;
        }
-
+       
+       return t;
+fail:
+       t.type = L_LSL_TOK_NONE;
        return t;
 }
 
@@ -235,6 +250,10 @@ void l_lsl_value_free(struct l_lsl_vm *v,
        lrts_assert(v);
        lrts_assert(val);
 
+       if (val->type == L_LSL_TYPE_STRING) {
+               v->free(val->data.str_val);
+       }
+
        v->free(val);
 }
 
@@ -260,6 +279,12 @@ struct l_lsl_value* l_lsl_compile(struct l_lsl_vm *v,
                        val->type = L_LSL_TYPE_INT;
                        val->data.int_val = u_strtol(tok.val, LRTS_NULL, tok.base);
                        break;
+               case L_LSL_TOK_STRING:
+                       val = l_lsl_value_alloc(v);
+                       val->type = L_LSL_TYPE_STRING;
+                       val->data.str_val = v->malloc(tok.len+1);
+                       u_memcpy(val->data.str_val, tok.val, tok.len+1);
+                       break;
                default:
                        v->err = L_LSL_ERR_LEX;
        }
diff --git a/src/tests/lsl/strliteral.lsl b/src/tests/lsl/strliteral.lsl
new file mode 100644 (file)
index 0000000..cd4bc1a
--- /dev/null
@@ -0,0 +1 @@
+"hello world"
index 89f947542554fd93cda7c0432ddc737ae247193a..905682b3bf26a0f9271b9947540f2a0c04973039 100644 (file)
@@ -12,6 +12,15 @@ int t_lsl_vlue_assert_int(struct l_lsl_value *expected,
        return 0;
 }
 
+int t_lsl_vlue_assert_str(struct l_lsl_value *expected, 
+               struct l_lsl_value *actual) {
+       T_ASSERT(u_strncmp(expected->data.str_val, actual->data.str_val, 256) == 0, 
+                       ("Unexpected int value. Expected %s got %s\n", expected->data.str_val,
+                        actual->data.str_val));
+
+       return 0;
+}
+
 #define T_LSL_ASSERT(expected_value, expected_err, src_file, value_assert) \
        if (t_lsl_assert(expected_value, expected_err, src_file, value_assert)) { \
                return 1; \
@@ -27,7 +36,7 @@ int t_lsl_assert(struct l_lsl_value expect_value, enum l_lsl_error expect_err,
 
        l_lsl_vm_free(&v);
        
-       T_ASSERT(res != LRTS_NULL, ("Invalid result value"))
+       T_ASSERT(res != LRTS_NULL, ("Invalid result value\n"))
        T_ASSERT(err == expect_err, ("Unexpected error code %d\n", err));
        T_ASSERT(res->type == expect_value.type, ("Unexpected return value\n"));
 
@@ -66,5 +75,11 @@ int t_test_lsl() {
        v.data.int_val = 0123;
        T_LSL_ASSERT(v, L_LSL_ERR_OK, "./src/tests/lsl/octliteral.lsl", 
                        t_lsl_vlue_assert_int);
+
+       /* simple str value */
+       v.type = L_LSL_TYPE_STRING;
+       v.data.str_val = "hello world";
+       T_LSL_ASSERT(v, L_LSL_ERR_OK, "./src/tests/lsl/strliteral.lsl", 
+                       t_lsl_vlue_assert_str);
        return 0;
 }
index e0735ebee5602792bef5dad8fc4b0a6a44ece72f..e38b738fee6789a7bd762dfbb677fc6f9d3f3456 100644 (file)
@@ -7,3 +7,4 @@ int u_strnlen(const char *s, u32 n) {
        }
        return i;
 }
+
index 28b48b3f8a1a48ae5b39a34a1cee1d2341c056bb..b405338eb7767a240e8a18f15b953c24910d9f6c 100644 (file)
@@ -10,4 +10,6 @@ int u_strncmp(const char *s1, const char *s2, u32 n);
 
 int u_strnlen(const char *s, u32 n);
 
+int u_strncmp(const char *l, const char *r, u32 n);
+
 #endif