-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple-lexer.h
162 lines (134 loc) · 5.8 KB
/
simple-lexer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef SIMPLE_LEXER_H_
#define SIMPLE_LEXER_H_
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#define SIMPLELEXER_ARRAY_LEN(xs) (sizeof(xs) / sizeof((xs)[0]))
#define simplelexer_return_defer(value) do { result = (value); goto defer; } while(0)
typedef struct {
char *items;
size_t count;
size_t capacity;
} SimpleLexer_StringBuilder;
#ifndef SIMPLELEXER_ASSERT
#define SIMPLELEXER_ASSERT assert
#endif
#ifndef SIMPLELEXER_REALLOC
#define SIMPLELEXER_REALLOC realloc
#endif
#ifndef SIMPLELEXER_FREE
#define SIMPLELEXER_FREE free
#endif
#ifndef SIMPLELEXER_DA_INIT_CAP
#define SIMPLELEXER_DA_INIT_CAP 256
#endif
#define simplelexer_da_append_many(da, new_items, new_items_count) \
do { \
if ((da)->count + (new_items_count) > (da)->capacity) { \
if ((da)->capacity == 0) { \
(da)->capacity = SIMPLELEXER_DA_INIT_CAP; \
} \
while ((da)->count + (new_items_count) > (da)->capacity) { \
(da)->capacity *= 2; \
} \
(da)->items = SIMPLELEXER_REALLOC((da)->items, (da)->capacity * sizeof(*(da)->items));\
SIMPLELEXER_ASSERT((da)->items != NULL && "Memory allocation failed"); \
} \
memcpy((da)->items + (da)->count, (new_items), (new_items_count) * sizeof(*(da)->items));\
(da)->count += (new_items_count); \
} while (0)
#define simplelexer_sb_append_cstr(sb, cstr) \
do { \
const char *s = (cstr); \
size_t n = strlen(s); \
simplelexer_da_append_many(sb, s, n); \
} while (0)
#define simplelexer_sb_append_null(sb) simplelexer_da_append_many(sb, "", 1)
typedef struct {
const char *file_path;
size_t row;
size_t col;
} SimpleLexer_Loc;
#define SimpleLexer_Loc_Fmt "%s:%zu:%zu"
#define SimpleLexer_Loc_Arg(loc) (loc).file_path, (loc).row, (loc).col
#define SIMPLELEXER_LOW32(x) (((uint64_t)(x)) & 0xFFFFFFFF)
#define SIMPLELEXER_ID(kind, index) ((SIMPLELEXER_LOW32(index) << 32) | (SIMPLELEXER_LOW32(kind)))
#define SIMPLELEXER_KIND(id) SIMPLELEXER_LOW32(id)
#define SIMPLELEXER_INDEX(id) SIMPLELEXER_LOW32((id) >> 32)
typedef enum {
SIMPLELEXER_INVALID,
SIMPLELEXER_END,
SIMPLELEXER_INT,
SIMPLELEXER_SYMBOL,
SIMPLELEXER_KEYWORD,
SIMPLELEXER_PUNCT,
SIMPLELEXER_STRING,
SIMPLELEXER_COUNT_KINDS,
} SimpleLexer_Kind;
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(SIMPLELEXER_COUNT_KINDS == 7, "Token kinds count mismatch");
#else
typedef char static_assertion_SIMPLELEXER_COUNT_KINDS[(SIMPLELEXER_COUNT_KINDS == 7) ? 1 : -1];
#endif
extern const char *simplelexer_kind_names[SIMPLELEXER_COUNT_KINDS];
#define simplelexer_kind_name(kind) (SIMPLELEXER_ASSERT((uint64_t)kind < SIMPLELEXER_COUNT_KINDS), simplelexer_kind_names[(uint64_t)kind])
typedef struct {
uint64_t id;
SimpleLexer_Loc loc;
const char *begin;
const char *end;
long int_value;
} SimpleLexer_Token;
bool simplelexer_token_text_equal(SimpleLexer_Token a, SimpleLexer_Token b);
bool simplelexer_token_text_equal_cstr(SimpleLexer_Token a, const char *b);
#define SimpleLexer_Token_Fmt "%.*s"
#define SimpleLexer_Token_Arg(t) (int)((t).end - (t).begin), (t).begin
typedef struct {
const char *opening;
const char *closing;
} SimpleLexer_MLComments;
typedef struct {
size_t cur;
size_t bol;
size_t row;
} SimpleLexer_State;
typedef struct {
const char *file_path;
const char *content;
size_t size;
size_t cur;
size_t bol;
size_t row;
const char **puncts;
size_t puncts_count;
const char **keywords;
size_t keywords_count;
const char **sl_comments;
size_t sl_comments_count;
SimpleLexer_MLComments *ml_comments;
size_t ml_comments_count;
bool (*is_symbol_start)(char x);
bool (*is_symbol)(char x);
void (*diagf)(SimpleLexer_Loc loc, const char *level, const char *fmt, ...);
} SimpleLexer;
SimpleLexer simplelexer_create(const char *file_path, const char *content, size_t size);
bool simplelexer_get_token(SimpleLexer *l, SimpleLexer_Token *t);
SimpleLexer_State simplelexer_save(SimpleLexer *l);
void simplelexer_rewind(SimpleLexer *l, SimpleLexer_State s);
bool simplelexer_chop_char(SimpleLexer *l);
void simplelexer_chop_chars(SimpleLexer *l, size_t n);
void simplelexer_trim_left_ws(SimpleLexer *l);
void simplelexer_drop_until_endline(SimpleLexer *l);
SimpleLexer_Loc simplelexer_loc(SimpleLexer *l);
bool simplelexer_default_is_symbol(char x);
bool simplelexer_default_is_symbol_start(char x);
void simplelexer_default_diagf(SimpleLexer_Loc loc, const char *level, const char *fmt, ...);
void simplelexer_ignore_diagf(SimpleLexer_Loc loc, const char *level, const char *fmt, ...);
bool simplelexer_expect_id(SimpleLexer *l, SimpleLexer_Token t, uint64_t id);
bool simplelexer_expect_one_of_ids(SimpleLexer *l, SimpleLexer_Token t, uint64_t *ids, size_t ids_count);
#endif /* SIMPLE_LEXER_H_ */