]> git.lizzy.rs Git - nothing.git/blob - src/ebisp/tokenizer.c
(#603) Fix bad GC memory reallocation
[nothing.git] / src / ebisp / tokenizer.c
1 #include <stdio.h>
2 #include <stdbool.h>
3 #include "system/stacktrace.h"
4 #include <ctype.h>
5 #include <stdlib.h>
6
7 #include "./tokenizer.h"
8
9 static struct Token token(const char *begin, const char *end)
10 {
11     struct Token token = {
12         .begin = begin,
13         .end = end
14     };
15
16     return token;
17 }
18
19 static bool is_symbol_char(char x)
20 {
21     static const char forbidden_symbol_chars[] = {
22         '(', ')', '"', '\'', ';', '.', '`', ','
23     };
24     static const size_t n = sizeof(forbidden_symbol_chars) / sizeof(char);
25
26     for (size_t i = 0; i < n; ++i) {
27         if (x == forbidden_symbol_chars[i] || isspace(x)) {
28             return false;
29         }
30     }
31
32     return true;
33 }
34
35 static const char *skip_whitespace(const char *str)
36 {
37     trace_assert(str);
38
39     while(*str != 0 && isspace(*str)) {
40         str++;
41     }
42
43     return str;
44 }
45
46 static const char *next_quote(const char *str)
47 {
48     trace_assert(str);
49
50     while(*str != 0 && *str != '"') {
51         str++;
52     }
53
54     return str;
55 }
56
57 static const char *skip_until_newline(const char *str)
58 {
59     trace_assert(str);
60
61     while(*str != 0 && *str != '\n') {
62         str++;
63     }
64
65     return str;
66 }
67
68 static const char *next_non_symbol(const char *str)
69 {
70     trace_assert(str);
71
72     while(*str != 0 && is_symbol_char(*str)) {
73         str++;
74     }
75
76     return str;
77 }
78
79 struct Token next_token(const char *str)
80 {
81     trace_assert(str);
82
83     str = skip_whitespace(str);
84     if (*str == 0) {
85         return token(str, str);
86     }
87
88     while (*str != 0 && *str == ';') {
89         str = skip_until_newline(str + 1);
90         str = skip_whitespace(str);
91     }
92
93     switch (*str) {
94     case '(':
95     case ')':
96     case '.':
97     case '\'':
98     case '`':
99     case ',':
100         return token(str, str + 1);
101
102     case '"': {
103         const char *str_end = next_quote(str + 1);
104         return token(str, *str_end == 0 ? str_end : str_end + 1);
105     }
106
107     default:
108         return token(str, next_non_symbol(str + 1));
109     }
110 }