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