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