Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/compiler/gravity_token.c
1214 views
1
//
2
// gravity_token.c
3
// gravity
4
//
5
// Created by Marco Bambini on 31/08/14.
6
// Copyright (c) 2014 CreoLabs. All rights reserved.
7
//
8
9
#include "gravity_token.h"
10
#include "gravity_utils.h"
11
12
const char *token_string (gtoken_s token, uint32_t *len) {
13
if (len) *len = token.bytes;
14
return token.value;
15
}
16
17
const char *token_name (gtoken_t token) {
18
switch (token) {
19
case TOK_EOF: return "EOF";
20
case TOK_ERROR: return "ERROR";
21
case TOK_COMMENT: return "COMMENT";
22
case TOK_STRING: return "STRING";
23
case TOK_NUMBER: return "NUMBER";
24
case TOK_IDENTIFIER: return "IDENTIFIER";
25
case TOK_SPECIAL: return "SPECIAL";
26
case TOK_MACRO: return "MACRO";
27
28
// keywords
29
case TOK_KEY_FILE: return "file";
30
case TOK_KEY_FUNC: return "func";
31
case TOK_KEY_SUPER: return "super";
32
case TOK_KEY_DEFAULT: return "default";
33
case TOK_KEY_TRUE: return "true";
34
case TOK_KEY_FALSE: return "false";
35
case TOK_KEY_IF: return "if";
36
case TOK_KEY_ELSE: return "else";
37
case TOK_KEY_SWITCH: return "switch";
38
case TOK_KEY_BREAK: return "break";
39
case TOK_KEY_CONTINUE: return "continue";
40
case TOK_KEY_RETURN: return "return";
41
case TOK_KEY_WHILE: return "while";
42
case TOK_KEY_REPEAT: return "repeat";
43
case TOK_KEY_FOR: return "for";
44
case TOK_KEY_IN: return "in";
45
case TOK_KEY_ENUM: return "enum";
46
case TOK_KEY_CLASS: return "class";
47
case TOK_KEY_STRUCT: return "struct";
48
case TOK_KEY_PRIVATE: return "private";
49
case TOK_KEY_INTERNAL: return "internal";
50
case TOK_KEY_PUBLIC: return "public";
51
case TOK_KEY_STATIC: return "static";
52
case TOK_KEY_EXTERN: return "extern";
53
case TOK_KEY_LAZY: return "lazy";
54
case TOK_KEY_CONST: return "const";
55
case TOK_KEY_VAR: return "var";
56
case TOK_KEY_MODULE: return "module";
57
case TOK_KEY_IMPORT: return "import";
58
case TOK_KEY_CASE: return "case";
59
case TOK_KEY_EVENT: return "event";
60
case TOK_KEY_NULL: return "null";
61
case TOK_KEY_UNDEFINED: return "undefined";
62
case TOK_KEY_ISA: return "isa";
63
case TOK_KEY_CURRARGS: return "_args";
64
case TOK_KEY_CURRFUNC: return "_func";
65
66
// operators
67
case TOK_OP_ADD: return "+";
68
case TOK_OP_SUB: return "-";
69
case TOK_OP_DIV: return "/";
70
case TOK_OP_MUL: return "*";
71
case TOK_OP_REM: return "%";
72
case TOK_OP_ASSIGN: return "=";
73
case TOK_OP_LESS: return "<";
74
case TOK_OP_GREATER: return ">";
75
case TOK_OP_LESS_EQUAL: return "<=";
76
case TOK_OP_GREATER_EQUAL: return ">=";
77
case TOK_OP_ADD_ASSIGN: return "+=";
78
case TOK_OP_SUB_ASSIGN: return "-=";
79
case TOK_OP_DIV_ASSIGN: return "/=";
80
case TOK_OP_MUL_ASSIGN: return "*=";
81
case TOK_OP_REM_ASSIGN: return "%=";
82
case TOK_OP_NOT: return "!";
83
case TOK_OP_AND: return "&&";
84
case TOK_OP_OR: return "||";
85
case TOK_OP_ISEQUAL: return "==";
86
case TOK_OP_ISNOTEQUAL: return "!=";
87
case TOK_OP_RANGE_INCLUDED: return "...";
88
case TOK_OP_RANGE_EXCLUDED: return "..<";
89
case TOK_OP_TERNARY: return "?";
90
case TOK_OP_SHIFT_LEFT: return "<<";
91
case TOK_OP_SHIFT_RIGHT: return ">>";
92
case TOK_OP_BIT_AND: return "&";
93
case TOK_OP_BIT_OR: return "|";
94
case TOK_OP_BIT_XOR: return "^";
95
case TOK_OP_BIT_NOT: return "~";
96
case TOK_OP_ISIDENTICAL: return "===";
97
case TOK_OP_ISNOTIDENTICAL: return "!==";
98
case TOK_OP_PATTERN_MATCH: return "~=";
99
case TOK_OP_SHIFT_LEFT_ASSIGN: return "<<=";
100
case TOK_OP_SHIFT_RIGHT_ASSIGN: return ">>=";
101
case TOK_OP_BIT_AND_ASSIGN: return "&=";
102
case TOK_OP_BIT_OR_ASSIGN: return "|=";
103
case TOK_OP_BIT_XOR_ASSIGN: return "^=";
104
105
case TOK_OP_OPEN_PARENTHESIS: return "(";
106
case TOK_OP_CLOSED_PARENTHESIS: return ")";
107
case TOK_OP_OPEN_SQUAREBRACKET: return "[";
108
case TOK_OP_CLOSED_SQUAREBRACKET: return "]";
109
case TOK_OP_OPEN_CURLYBRACE: return "{";
110
case TOK_OP_CLOSED_CURLYBRACE: return "}";
111
case TOK_OP_SEMICOLON: return ";";
112
case TOK_OP_COLON: return ":";
113
case TOK_OP_COMMA: return ",";
114
case TOK_OP_DOT: return ".";
115
116
case TOK_END: return "";
117
}
118
119
// should never reach this point
120
return "UNRECOGNIZED TOKEN";
121
}
122
123
void token_keywords_indexes (uint32_t *idx_start, uint32_t *idx_end) {
124
*idx_start = (uint32_t)TOK_KEY_FUNC;
125
*idx_end = (uint32_t)TOK_KEY_CURRARGS;
126
};
127
128
gtoken_t token_keyword (const char *buffer, int32_t len) {
129
switch (len) {
130
case 2:
131
if (string_casencmp(buffer, "if", len) == 0) return TOK_KEY_IF;
132
if (string_casencmp(buffer, "in", len) == 0) return TOK_KEY_IN;
133
if (string_casencmp(buffer, "or", len) == 0) return TOK_OP_OR;
134
break;
135
136
case 3:
137
if (string_casencmp(buffer, "isa", len) == 0) return TOK_KEY_ISA;
138
if (string_casencmp(buffer, "for", len) == 0) return TOK_KEY_FOR;
139
if (string_casencmp(buffer, "var", len) == 0) return TOK_KEY_VAR;
140
if (string_casencmp(buffer, "and", len) == 0) return TOK_OP_AND;
141
if (string_casencmp(buffer, "not", len) == 0) return TOK_OP_NOT;
142
break;
143
144
case 4:
145
if (string_casencmp(buffer, "func", len) == 0) return TOK_KEY_FUNC;
146
if (string_casencmp(buffer, "else", len) == 0) return TOK_KEY_ELSE;
147
if (string_casencmp(buffer, "true", len) == 0) return TOK_KEY_TRUE;
148
if (string_casencmp(buffer, "enum", len) == 0) return TOK_KEY_ENUM;
149
if (string_casencmp(buffer, "case", len) == 0) return TOK_KEY_CASE;
150
if (string_casencmp(buffer, "null", len) == 0) return TOK_KEY_NULL;
151
if (string_casencmp(buffer, "file", len) == 0) return TOK_KEY_FILE;
152
if (string_casencmp(buffer, "lazy", len) == 0) return TOK_KEY_LAZY;
153
break;
154
155
case 5:
156
if (string_casencmp(buffer, "super", len) == 0) return TOK_KEY_SUPER;
157
if (string_casencmp(buffer, "false", len) == 0) return TOK_KEY_FALSE;
158
if (string_casencmp(buffer, "break", len) == 0) return TOK_KEY_BREAK;
159
if (string_casencmp(buffer, "while", len) == 0) return TOK_KEY_WHILE;
160
if (string_casencmp(buffer, "class", len) == 0) return TOK_KEY_CLASS;
161
if (string_casencmp(buffer, "const", len) == 0) return TOK_KEY_CONST;
162
if (string_casencmp(buffer, "event", len) == 0) return TOK_KEY_EVENT;
163
if (string_casencmp(buffer, "_func", len) == 0) return TOK_KEY_CURRFUNC;
164
if (string_casencmp(buffer, "_args", len) == 0) return TOK_KEY_CURRARGS;
165
break;
166
167
case 6:
168
if (string_casencmp(buffer, "struct", len) == 0) return TOK_KEY_STRUCT;
169
if (string_casencmp(buffer, "repeat", len) == 0) return TOK_KEY_REPEAT;
170
if (string_casencmp(buffer, "switch", len) == 0) return TOK_KEY_SWITCH;
171
if (string_casencmp(buffer, "return", len) == 0) return TOK_KEY_RETURN;
172
if (string_casencmp(buffer, "public", len) == 0) return TOK_KEY_PUBLIC;
173
if (string_casencmp(buffer, "static", len) == 0) return TOK_KEY_STATIC;
174
if (string_casencmp(buffer, "extern", len) == 0) return TOK_KEY_EXTERN;
175
if (string_casencmp(buffer, "import", len) == 0) return TOK_KEY_IMPORT;
176
if (string_casencmp(buffer, "module", len) == 0) return TOK_KEY_MODULE;
177
break;
178
179
case 7:
180
if (string_casencmp(buffer, "default", len) == 0) return TOK_KEY_DEFAULT;
181
if (string_casencmp(buffer, "private", len) == 0) return TOK_KEY_PRIVATE;
182
break;
183
184
case 8:
185
if (string_casencmp(buffer, "continue", len) == 0) return TOK_KEY_CONTINUE;
186
if (string_casencmp(buffer, "internal", len) == 0) return TOK_KEY_INTERNAL;
187
break;
188
189
case 9:
190
if (string_casencmp(buffer, "undefined", len) == 0) return TOK_KEY_UNDEFINED;
191
break;
192
}
193
194
return TOK_IDENTIFIER;
195
}
196
197
const char *token_literal_name (gliteral_t value) {
198
if (value == LITERAL_STRING) return "STRING";
199
else if (value == LITERAL_FLOAT) return "FLOAT";
200
else if (value == LITERAL_INT) return "INTEGER";
201
else if (value == LITERAL_BOOL) return "BOOLEAN";
202
return "N/A";
203
}
204
205
// MARK: -
206
207
bool token_isidentifier (gtoken_t token) {
208
return (token == TOK_IDENTIFIER);
209
}
210
211
bool token_isvariable_declaration (gtoken_t token) {
212
return ((token == TOK_KEY_CONST) || (token == TOK_KEY_VAR));
213
}
214
215
bool token_isstatement (gtoken_t token) {
216
// label_statement (case, default)
217
// expression_statement ('+' | '-' | '!' | 'not' | new | raise | file | isPrimaryExpression)
218
// flow_statement (if, select)
219
// loop_statement (while, loop, for)
220
// jump_statement (break, continue, return)
221
// compound_statement ({)
222
// declaration_statement (isDeclarationStatement)
223
// empty_statement (;)
224
// import_statement (import)
225
226
return (token_islabel_statement(token) || token_isexpression_statement(token) || token_isflow_statement(token) ||
227
token_isloop_statement(token) || token_isjump_statement(token) || token_iscompound_statement(token) ||
228
token_isdeclaration_statement(token) || token_isempty_statement(token) || token_isimport_statement(token));
229
}
230
231
bool token_isassignment (gtoken_t token) {
232
return ((token == TOK_OP_ASSIGN) || (token == TOK_OP_MUL_ASSIGN) || (token == TOK_OP_DIV_ASSIGN) ||
233
(token == TOK_OP_REM_ASSIGN) || (token == TOK_OP_ADD_ASSIGN) || (token == TOK_OP_SUB_ASSIGN) ||
234
(token == TOK_OP_SHIFT_LEFT_ASSIGN) || (token == TOK_OP_SHIFT_RIGHT_ASSIGN) ||
235
(token == TOK_OP_BIT_AND_ASSIGN) || (token == TOK_OP_BIT_OR_ASSIGN) || (token == TOK_OP_BIT_XOR_ASSIGN));
236
}
237
238
bool token_isvariable_assignment (gtoken_t token) {
239
return (token == TOK_OP_ASSIGN);
240
}
241
242
bool token_isaccess_specifier (gtoken_t token) {
243
return ((token == TOK_KEY_PRIVATE) || (token == TOK_KEY_INTERNAL) || (token == TOK_KEY_PUBLIC));
244
}
245
246
bool token_isstorage_specifier (gtoken_t token) {
247
return ((token == TOK_KEY_STATIC) || (token == TOK_KEY_EXTERN) || (token == TOK_KEY_LAZY));
248
}
249
250
bool token_isprimary_expression (gtoken_t token) {
251
// literal (number, string)
252
// true, false
253
// IDENTIFIER
254
// 'nil'
255
// 'super'
256
// 'func'
257
// 'undefined'
258
// 'file'
259
// '(' expression ')'
260
// function_expression
261
// list_expression
262
// map_expression
263
264
return ((token == TOK_NUMBER) || (token == TOK_STRING) || (token == TOK_KEY_TRUE) ||
265
(token == TOK_KEY_FALSE) || (token == TOK_IDENTIFIER) || (token == TOK_KEY_NULL) ||
266
(token == TOK_KEY_SUPER) || (token == TOK_KEY_FUNC) || (token == TOK_KEY_UNDEFINED) ||
267
(token == TOK_OP_OPEN_PARENTHESIS) || (token == TOK_OP_OPEN_SQUAREBRACKET) ||
268
(token == TOK_OP_OPEN_CURLYBRACE) || (token == TOK_KEY_FILE));
269
270
}
271
272
bool token_isexpression_statement (gtoken_t token) {
273
// reduced to check for unary_expression
274
// postfix_expression: primary_expression | 'module' (was file)
275
// unary_operator: '+' | '-' | '!' | 'not'
276
// raise_expression: 'raise'
277
278
return (token_isprimary_expression(token) || (token == TOK_OP_ADD) || (token == TOK_OP_SUB) || (token == TOK_OP_NOT));
279
}
280
281
bool token_islabel_statement (gtoken_t token) {
282
return ((token == TOK_KEY_CASE) || (token == TOK_KEY_DEFAULT));
283
}
284
285
bool token_isflow_statement (gtoken_t token) {
286
return ((token == TOK_KEY_IF) || (token == TOK_KEY_SWITCH));
287
}
288
289
bool token_isloop_statement (gtoken_t token) {
290
return ((token == TOK_KEY_WHILE) || (token == TOK_KEY_REPEAT) || (token == TOK_KEY_FOR));
291
}
292
293
bool token_isjump_statement (gtoken_t token) {
294
return ((token == TOK_KEY_BREAK) || (token == TOK_KEY_CONTINUE) || (token == TOK_KEY_RETURN));
295
}
296
297
bool token_iscompound_statement (gtoken_t token) {
298
return (token == TOK_OP_OPEN_CURLYBRACE);
299
}
300
301
bool token_isdeclaration_statement (gtoken_t token) {
302
// variable_declaration_statement (CONST, VAR)
303
// function_declaration (FUNC)
304
// class_declaration (CLASS | STRUCT)
305
// enum_declaration (ENUM)
306
// module_declaration (MODULE)
307
// event_declaration_statement (EVENT)
308
// empty_declaration (;)
309
310
return ((token_isaccess_specifier(token) || token_isstorage_specifier(token) || token_isvariable_declaration(token) ||
311
(token == TOK_KEY_FUNC) || (token == TOK_KEY_CLASS) || (token == TOK_KEY_STRUCT) || (token == TOK_KEY_ENUM) ||
312
(token == TOK_KEY_MODULE) || (token == TOK_KEY_EVENT) || (token == TOK_OP_SEMICOLON)));
313
}
314
315
bool token_isempty_statement (gtoken_t token) {
316
return (token == TOK_OP_SEMICOLON);
317
}
318
319
bool token_isimport_statement (gtoken_t token) {
320
return (token == TOK_KEY_IMPORT);
321
}
322
323
bool token_isspecial_statement (gtoken_t token) {
324
return (token == TOK_SPECIAL);
325
}
326
327
bool token_isoperator (gtoken_t token) {
328
return ((token >= TOK_OP_SHIFT_LEFT) && (token <= TOK_OP_NOT));
329
}
330
331
bool token_ismacro (gtoken_t token) {
332
return (token == TOK_MACRO);
333
}
334
335
bool token_iserror (gtoken_t token) {
336
return (token == TOK_ERROR);
337
}
338
339
bool token_iseof (gtoken_t token) {
340
return (token == TOK_EOF);
341
}
342
343
bool token_identical (gtoken_s *t1, gtoken_s *t2) {
344
// we can't use memcmp to compare structs for equality due to potential random padding characters between field in structs
345
return ((t1->type == t2->type) && (t1->lineno == t2->lineno) && (t1->colno == t2->colno) && (t1->position == t2->position) &&
346
(t1->bytes == t2->bytes) && (t1->length == t2->length) && (t1->fileid == t2->fileid) && (t1->escaped == t2->escaped) &&
347
(memcmp(t1->value, t2->value, t1->bytes) == 0));
348
}
349
350