-
Notifications
You must be signed in to change notification settings - Fork 6
/
scanner.cc
128 lines (113 loc) · 3.32 KB
/
scanner.cc
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
#include <tree_sitter/parser.h>
#include <vector>
enum TokenType {
NESTING_BLOCK_COMMENT,
DELIMITED_STRING,
};
// This is only an approximation of the exact definition.
static bool is_identifier_char(int32_t c) {
return
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_';
}
extern "C" {
void *tree_sitter_d_external_scanner_create() {
return NULL;
}
bool tree_sitter_d_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
if (lexer->lookahead == '/' && valid_symbols[NESTING_BLOCK_COMMENT]) {
lexer->advance(lexer, false);
if (lexer->lookahead != '+') {
return false;
}
lexer->advance(lexer, false);
size_t depth = 1;
int32_t last = 0;
while (depth > 0) {
last = lexer->lookahead;
lexer->advance(lexer, false);
if (last == '/' && lexer->lookahead == '+') {
depth++;
last = 0;
lexer->advance(lexer, false);
} else if (last == '+' && lexer->lookahead == '/') {
depth--;
last = 0;
lexer->advance(lexer, false);
} else if (lexer->lookahead == 0) {
return false; // EOF
}
}
lexer->result_symbol = NESTING_BLOCK_COMMENT;
return true;
}
if (lexer->lookahead == 'q' && valid_symbols[DELIMITED_STRING]) {
lexer->advance(lexer, false);
if (lexer->lookahead != '"') {
return false;
}
lexer->advance(lexer, false);
lexer->result_symbol = DELIMITED_STRING;
int32_t opener = lexer->lookahead, closer;
switch (opener) {
case '(': closer = ')'; break;
case '[': closer = ']'; break;
case '{': closer = '}'; break;
case '<': closer = '>'; break;
default:
{
// Handle the identifier case
std::vector<int32_t> delimiter;
delimiter.push_back('\n');
while (lexer->lookahead != '\n') {
if (!is_identifier_char(lexer->lookahead))
return false; // bad syntax or EOF
delimiter.push_back(lexer->lookahead);
lexer->advance(lexer, false);
}
delimiter.push_back('"');
size_t delimiter_pos = 0;
while (true) {
if (lexer->lookahead == 0)
return false; // EOF
if (delimiter_pos == delimiter.size())
return true;
if (lexer->lookahead == delimiter.at(delimiter_pos))
delimiter_pos++;
else
delimiter_pos = lexer->lookahead == delimiter.at(0) ? 1 : 0;
lexer->advance(lexer, false);
}
}
}
// Handle the punctuation case
size_t depth = 1;
while (depth > 0) {
lexer->advance(lexer, false);
if (lexer->lookahead == opener) {
depth++;
} else if (lexer->lookahead == closer) {
depth--;
} else if (lexer->lookahead == 0) {
return false; // EOF
}
}
lexer->advance(lexer, false); // last closer
if (lexer->lookahead != '"')
return false;
lexer->advance(lexer, false); // "
return true;
}
return false;
}
unsigned tree_sitter_d_external_scanner_serialize(void *payload, char *buffer) {
return 0;
}
void tree_sitter_d_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
}
void tree_sitter_d_external_scanner_destroy(void *payload) {
}
}