]> git.lizzy.rs Git - nothing.git/blob - src/script/tokenizer.c
(#299) Simplify parser with tokenizer
[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     assert(str);
71
72     str = skip_whitespace(str);
73     if (*str == 0) {
74         return token(str, str);
75     }
76
77     while (*str != 0 && *str == ';') {
78         str = skip_until_newline(str + 1);
79         str = skip_whitespace(str);
80     }
81
82     switch (*str) {
83     case '(':
84     case ')':
85     case '.':
86         return token(str, str + 1);
87
88     case '"': {
89         const char *str_end = next_quote(str + 1);
90         return token(str, *str_end == 0 ? str_end : str_end + 1);
91     }
92
93     default:
94         return token(str, next_non_symbol(str + 1));
95     }
96 }