forked from marcoroth/herb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtoken.c
More file actions
149 lines (123 loc) · 4.29 KB
/
token.c
File metadata and controls
149 lines (123 loc) · 4.29 KB
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
#include "include/token.h"
#include "include/lexer.h"
#include "include/position.h"
#include "include/range.h"
#include "include/token_struct.h"
#include "include/util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
token_T* token_init(const char* value, const token_type_T type, lexer_T* lexer) {
token_T* token = calloc(1, sizeof(token_T));
if (type == TOKEN_NEWLINE) {
lexer->current_line++;
lexer->current_column = 0;
}
if (value) {
token->value = herb_strdup(value);
} else {
token->value = NULL;
}
token->type = type;
token->range = (range_T) { .from = lexer->previous_position, .to = lexer->current_position };
location_from(
&token->location,
lexer->previous_line,
lexer->previous_column,
lexer->current_line,
lexer->current_column
);
lexer->previous_line = lexer->current_line;
lexer->previous_column = lexer->current_column;
lexer->previous_position = lexer->current_position;
return token;
}
const char* token_type_to_string(const token_type_T type) {
switch (type) {
case TOKEN_WHITESPACE: return "TOKEN_WHITESPACE";
case TOKEN_NBSP: return "TOKEN_NBSP";
case TOKEN_NEWLINE: return "TOKEN_NEWLINE";
case TOKEN_IDENTIFIER: return "TOKEN_IDENTIFIER";
case TOKEN_HTML_DOCTYPE: return "TOKEN_HTML_DOCTYPE";
case TOKEN_XML_DECLARATION: return "TOKEN_XML_DECLARATION";
case TOKEN_XML_DECLARATION_END: return "TOKEN_XML_DECLARATION_END";
case TOKEN_CDATA_START: return "TOKEN_CDATA_START";
case TOKEN_CDATA_END: return "TOKEN_CDATA_END";
case TOKEN_HTML_TAG_START: return "TOKEN_HTML_TAG_START";
case TOKEN_HTML_TAG_END: return "TOKEN_HTML_TAG_END";
case TOKEN_HTML_TAG_START_CLOSE: return "TOKEN_HTML_TAG_START_CLOSE";
case TOKEN_HTML_TAG_SELF_CLOSE: return "TOKEN_HTML_TAG_SELF_CLOSE";
case TOKEN_HTML_COMMENT_START: return "TOKEN_HTML_COMMENT_START";
case TOKEN_HTML_COMMENT_END: return "TOKEN_HTML_COMMENT_END";
case TOKEN_EQUALS: return "TOKEN_EQUALS";
case TOKEN_QUOTE: return "TOKEN_QUOTE";
case TOKEN_BACKTICK: return "TOKEN_BACKTICK";
case TOKEN_BACKSLASH: return "TOKEN_BACKSLASH";
case TOKEN_DASH: return "TOKEN_DASH";
case TOKEN_UNDERSCORE: return "TOKEN_UNDERSCORE";
case TOKEN_EXCLAMATION: return "TOKEN_EXCLAMATION";
case TOKEN_SLASH: return "TOKEN_SLASH";
case TOKEN_SEMICOLON: return "TOKEN_SEMICOLON";
case TOKEN_COLON: return "TOKEN_COLON";
case TOKEN_AT: return "TOKEN_AT";
case TOKEN_LT: return "TOKEN_LT";
case TOKEN_PERCENT: return "TOKEN_PERCENT";
case TOKEN_AMPERSAND: return "TOKEN_AMPERSAND";
case TOKEN_ERB_START: return "TOKEN_ERB_START";
case TOKEN_ERB_CONTENT: return "TOKEN_ERB_CONTENT";
case TOKEN_ERB_END: return "TOKEN_ERB_END";
case TOKEN_CHARACTER: return "TOKEN_CHARACTER";
case TOKEN_ERROR: return "TOKEN_ERROR";
case TOKEN_EOF: return "TOKEN_EOF";
}
return "Unknown token_type_T";
}
char* token_to_string(const token_T* token) {
const char* type_string = token_type_to_string(token->type);
const char* template = "#<Herb::Token type=\"%s\" value=\"%.*s\" range=[%u, %u] start=(%u:%u) end=(%u:%u)>";
char* string = calloc(strlen(type_string) + strlen(template) + strlen(token->value) + 16, sizeof(char));
hb_string_T escaped;
if (token->type == TOKEN_EOF) {
escaped = hb_string(herb_strdup("<EOF>"));
} else {
escaped = escape_newlines(hb_string(token->value));
}
sprintf(
string,
template,
type_string,
escaped.length,
escaped.data,
token->range.from,
token->range.to,
token->location.start.line,
token->location.start.column,
token->location.end.line,
token->location.end.column
);
free(escaped.data);
return string;
}
token_T* token_copy(token_T* token) {
if (!token) { return NULL; }
token_T* new_token = calloc(1, sizeof(token_T));
if (!new_token) { return NULL; }
if (token->value) {
new_token->value = herb_strdup(token->value);
if (!new_token->value) {
free(new_token);
return NULL;
}
} else {
new_token->value = NULL;
}
new_token->type = token->type;
new_token->range = token->range;
new_token->location = token->location;
return new_token;
}
void token_free(token_T* token) {
if (!token) { return; }
if (token->value != NULL) { free(token->value); }
free(token);
}