2022-06-02 16:13:55 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <tree_sitter/parser.h>
|
|
|
|
|
|
|
|
enum TokenType {
|
|
|
|
COMMENT,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int32_t advance(TSLexer *lexer) {
|
|
|
|
int32_t last = lexer->lookahead;
|
|
|
|
lexer->advance(lexer, false);
|
|
|
|
return last;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool expect(TSLexer *lexer, int32_t expected) {
|
|
|
|
if (lexer->eof(lexer) || lexer->lookahead != expected) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
advance(lexer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void skip_whitespace(TSLexer *lexer) {
|
|
|
|
while (!lexer->eof(lexer)) {
|
|
|
|
switch (lexer->lookahead) {
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
lexer->advance(lexer, true);
|
2022-06-02 22:27:00 +02:00
|
|
|
break;
|
2022-06-02 16:13:55 +02:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comments start with "/*", end with "*/", and can be nested like OCaml
|
|
|
|
static bool scan_comment(TSLexer *lexer) {
|
|
|
|
// '/' already consumed outside of the function
|
|
|
|
if (!expect(lexer, '*')) {
|
|
|
|
return false; // Division etc...
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long level = 1;
|
|
|
|
|
|
|
|
while (level > 0 && !lexer->eof(lexer)) {
|
|
|
|
switch (advance(lexer)) {
|
|
|
|
case '/':
|
|
|
|
if (expect(lexer, '*')) {
|
|
|
|
++level;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
if (expect(lexer, '/')) {
|
|
|
|
--level;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return level == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *tree_sitter_tiger_external_scanner_create() {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tree_sitter_tiger_external_scanner_destroy(void *payload) {}
|
|
|
|
|
|
|
|
unsigned tree_sitter_tiger_external_scanner_serialize(void *payload,
|
|
|
|
char *buffer) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tree_sitter_tiger_external_scanner_deserialize(void *payload,
|
|
|
|
char const *buffer,
|
|
|
|
unsigned length) {}
|
|
|
|
|
|
|
|
bool tree_sitter_tiger_external_scanner_scan(void *payload,
|
|
|
|
TSLexer *lexer,
|
|
|
|
bool const *valid_symbols) {
|
|
|
|
// Only try to scan when appropriate
|
|
|
|
if (!valid_symbols[COMMENT]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apparently it is expected of us to skip all whitespace by ourselves...
|
|
|
|
skip_whitespace(lexer);
|
|
|
|
|
|
|
|
// Comments start with "/*", scan_comment expects '/' to have been consumed
|
|
|
|
if (expect(lexer, '/')) {
|
|
|
|
lexer->result_symbol = COMMENT;
|
|
|
|
return scan_comment(lexer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|