summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-13 04:25:19 +0200
committerkdx <kikoodx@paranoici.org>2023-06-13 04:25:19 +0200
commitdea6dce494e9c403f1f9e2178cd8c7d0aad79738 (patch)
tree41611f96256ec2525ec19513b796166faed6a3cd
parentbef68b681f0af54061858a6689057850b390d79c (diff)
downloadgolem-dea6dce494e9c403f1f9e2178cd8c7d0aad79738.tar.gz
escape sequences
-rw-r--r--samples/helloworld.golem3
-rw-r--r--src/main.c56
-rwxr-xr-xtesting.sh1
3 files changed, 44 insertions, 16 deletions
diff --git a/samples/helloworld.golem b/samples/helloworld.golem
index 37698c0..57333b5 100644
--- a/samples/helloworld.golem
+++ b/samples/helloworld.golem
@@ -5,8 +5,7 @@ define iterations = 9;
main() {
local i;
- strcpy(str, "Hello, World!");
- strappend(str, '\n');
+ strcpy(str, "Hello, World!\n");
i = 0;
loop {
diff --git a/src/main.c b/src/main.c
index 01ade54..a76d098 100644
--- a/src/main.c
+++ b/src/main.c
@@ -96,6 +96,33 @@ is_punct(const char *p)
return (strchr("+-/*()<>,;{}[]=&^|", p[0]) != NULL);
}
+static int
+escaped_char(char *s, char **skipped)
+{
+ if (*s == '\\') {
+ int rv = -1;
+ switch (s[1]) {
+ case 'a': rv = '\a'; break;
+ case 'b': rv = '\b'; break;
+ case 'f': rv = '\f'; break;
+ case 'n': rv = '\n'; break;
+ case 'r': rv = '\r'; break;
+ case 't': rv = '\t'; break;
+ case 'v': rv = '\v'; break;
+ case '\\':rv = '\\'; break;
+ case '\'':rv = '\''; break;
+ case '"': rv = '"'; break;
+ default: break;
+ }
+ if (rv >= 0) {
+ *skipped = s + 2;
+ return rv;
+ }
+ }
+ *skipped = s + 1;
+ return *s;
+}
+
static Token *
tokenize(char *p)
{
@@ -139,17 +166,14 @@ tokenize(char *p)
continue;
}
- if (*p == '\'' && p[1] != '\0' && p[2] == '\'') {
- cur = cur->next = new_token(TOK_NUM, p, p + 3);
- cur->val = (unsigned char)p[1];
- p += 3;
- continue;
- }
-
- if (strncmp(p, "'\\n'", 4) == 0) {
- cur = cur->next = new_token(TOK_NUM, p, p + 4);
- cur->val = '\n';
- p += 4;
+ if (*p == '\'' && p[1] != '\'') {
+ char *q = p;
+ const int c = escaped_char(p + 1, &p);
+ if (*p != '\'')
+ error("unclosed single quotes", 0);
+ p += 1;
+ cur = cur->next = new_token(TOK_NUM, q, p);
+ cur->val = (unsigned char)c;
continue;
}
@@ -1141,8 +1165,14 @@ codegen(Node *node)
for (int i = 0; i < strings_size; i++) {
printf("@__str_%x\n", strings_size - i - 1);
- for (int k = 1; k < strings->lhs->len - 1; k++)
- printf("\t%04x\n", (unsigned)strings->lhs->loc[k]);
+ for (int k = 1; k < strings->lhs->len - 1;) {
+ char *q = strings->lhs->loc + k;
+ const int c = escaped_char(q, &q);
+ if (c == '"') /* TODO: handle this */
+ error("can't escape double quotes", 0);
+ printf("\t%04x\n", (unsigned)c);
+ k = q - strings->lhs->loc;
+ }
printf("\t0000\n");
strings = strings->next;
}
diff --git a/testing.sh b/testing.sh
index 3539b20..7d35ec0 100755
--- a/testing.sh
+++ b/testing.sh
@@ -55,5 +55,4 @@ test "$1" "main() return;"
test "$1" "main() { local a; a = 5; dbg a; a++; dbg a; }"
test "$1" "main() { local a; a = 5; dbg a; a--; dbg a; }"
test "$1" "main() { wrt [\"(\"]; wrt '\n'; }"
-exit
rm -f build/tmp.*