commit ad2faad

uint  ·  2026-10-24 13:45:41 +0000 UTC
parent 87e16ec
Add string escaping
1 files changed,  +36, -2
M expl.c
M expl.c
+36, -2
 1@@ -7,6 +7,8 @@
 2 
 3 #define current_char(p, c) ((p)->src[(p)->pos] == (c))
 4 #define advance(p) ((p)->pos++)
 5+#define pos(p) ((p)->pos)
 6+#define peek(p) ((p)->pos + 1)
 7 
 8 typedef struct {
 9 	const char* src;
10@@ -20,6 +22,7 @@ static expl_node* value(parser* p, expl_type type);
11 
12 static void skipspace(parser* p);
13 static char* _strndup(const char* src, size_t len);
14+static void unescape(char* src);
15 
16 static expl_node* newnode(expl_type type);
17 static void freenode(expl_node* node);
18@@ -128,8 +131,10 @@ value(parser* p, expl_type type)
19 		return NULL;
20 	}
21 
22-	if (type == EXPL_TYPE_STRING)
23+	if (type == EXPL_TYPE_STRING) {
24+		unescape(node->value);
25 		advance(p);
26+	}
27 
28 	return node;
29 }
30@@ -163,6 +168,35 @@ _strndup(const char* src, size_t len)
31 	return str;
32 }
33 
34+static void
35+unescape(char* src)
36+{
37+	char* dst = src;
38+
39+	while (*src) {
40+		if (*src == '\\' && src[1]) {
41+			src++;
42+			switch (*src) {
43+			case 'n':  *dst++ = '\n'; break;
44+			case 't':  *dst++ = '\t'; break;
45+			case 'r':  *dst++ = '\r'; break;
46+			case '\\': *dst++ = '\\'; break;
47+			case '"':  *dst++ = '"';  break;
48+			default:
49+				*dst++ = '\\';
50+				*dst++ = *src;
51+			}
52+		}
53+		else {
54+			*dst++ = *src;
55+		}
56+
57+		src++;
58+	}
59+
60+	*dst = '\0';
61+}
62+
63 static expl_node*
64 newnode(expl_type type)
65 {
66@@ -251,7 +285,7 @@ expl_print(const expl_node* node, int depth)
67 int
68 main(void)
69 {
70-	expl_node* node = expl_parse("(fn (\"hi\" x) (* x x))");
71+	expl_node* node = expl_parse("(fn (\"hi\n\n\n\" x) (* x x))");
72 	expl_print(node, 0);
73 	freenode(node);
74 	return EXIT_SUCCESS;