summaryrefslogtreecommitdiff
path: root/vendor/tree-sitter-odin/src/scanner.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tree-sitter-odin/src/scanner.c')
-rw-r--r--vendor/tree-sitter-odin/src/scanner.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/vendor/tree-sitter-odin/src/scanner.c b/vendor/tree-sitter-odin/src/scanner.c
new file mode 100644
index 0000000..ee0f651
--- /dev/null
+++ b/vendor/tree-sitter-odin/src/scanner.c
@@ -0,0 +1,285 @@
+#include "tree_sitter/parser.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <wctype.h>
+
+enum {
+ NEWLINE,
+ BACKSLASH,
+ NL_COMMA,
+ FLOAT,
+ BLOCK_COMMENT,
+ BRACKET,
+ QUOTE,
+};
+
+static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
+
+static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
+
+void *tree_sitter_odin_external_scanner_create() { return NULL; }
+
+unsigned tree_sitter_odin_external_scanner_serialize(void *payload, char *buffer) { return 0; }
+
+void tree_sitter_odin_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {}
+
+bool tree_sitter_odin_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
+ if (valid_symbols[FLOAT]) {
+ while (iswspace(lexer->lookahead) && lexer->lookahead != '\n') {
+ skip(lexer);
+ }
+
+ if (!valid_symbols[NEWLINE]) { // skip newlines too
+ while (iswspace(lexer->lookahead)) {
+ skip(lexer);
+ }
+ }
+
+ // basically, -? [0-9]+ \. [0-9]*, BUT a second . after isnt allowed
+ // cuz it could be ..< operator,
+ // it can have an i at the end for imaginary numbers
+ // and exponents, [eE][+-]?[0-9]+, imaginary comes after
+
+ // needs ONE of these two to be float
+ bool found_decimal = false;
+ bool found_exponent = false;
+ bool found_number_before_decimal = false;
+ bool found_number_after_decimal = false;
+ bool found_number_after_expontent = false;
+ for (int i = 0;; i++) {
+ switch (lexer->lookahead) {
+ case '.':
+ if ((found_decimal || found_exponent) &&
+ (found_number_after_decimal || found_number_before_decimal)) {
+ lexer->result_symbol = FLOAT;
+ lexer->mark_end(lexer);
+ return true;
+ } else {
+ lexer->mark_end(lexer);
+ found_decimal = true;
+ advance(lexer);
+ if (lexer->lookahead == '.') {
+ advance(lexer);
+ goto newline;
+ }
+ lexer->mark_end(lexer);
+ if (!isdigit(lexer->lookahead) && (found_number_after_decimal || found_number_before_decimal)) {
+ lexer->result_symbol = FLOAT;
+ return true;
+ }
+ }
+ break;
+ case 'i':
+ case 'j':
+ case 'k':
+ if (!found_number_after_decimal) {
+ goto newline;
+ }
+ if ((found_decimal || found_exponent) &&
+ (found_number_after_decimal || found_number_before_decimal)) {
+ advance(lexer);
+ lexer->result_symbol = FLOAT;
+ lexer->mark_end(lexer);
+ return true;
+ }
+ goto newline;
+ case 'e':
+ case 'E':
+ if ((found_exponent) && (found_number_after_decimal || found_number_before_decimal)) {
+ lexer->result_symbol = FLOAT;
+ lexer->mark_end(lexer);
+ return true;
+ } else if (found_number_before_decimal || found_number_after_decimal) {
+ found_exponent = true;
+ advance(lexer);
+ } else {
+ goto newline;
+ }
+ break;
+ case '+':
+ case '-':
+ if (i == 0 || (found_exponent && !found_number_after_expontent)) {
+ advance(lexer);
+ } else {
+ goto newline;
+ }
+ break;
+ default:
+ if (lexer->lookahead <= 255 && isdigit(lexer->lookahead)) {
+ advance(lexer);
+ if (found_decimal) {
+ found_number_after_decimal = true;
+ } else {
+ found_number_before_decimal = true;
+ }
+ if (found_exponent && !found_number_after_expontent) {
+ found_number_after_expontent = true;
+ }
+ } else {
+ if ((found_decimal || found_exponent) &&
+ (found_number_after_decimal || found_number_before_decimal)) {
+ lexer->result_symbol = FLOAT;
+ lexer->mark_end(lexer);
+ return true;
+ }
+ if (found_number_before_decimal) {
+ return false; // number needs to match
+ }
+ goto newline;
+ }
+ }
+ }
+ }
+
+ if (valid_symbols[NL_COMMA]) {
+ while (iswspace(lexer->lookahead) && lexer->lookahead != '\n') {
+ skip(lexer);
+ }
+
+ if (lexer->lookahead == ',') {
+ advance(lexer);
+ lexer->result_symbol = NL_COMMA;
+ lexer->mark_end(lexer);
+ while (iswspace(lexer->lookahead) && lexer->lookahead != '\n') {
+ advance(lexer);
+ }
+
+ if (lexer->lookahead == '\n') {
+ while (iswspace(lexer->lookahead)) {
+ advance(lexer);
+ }
+ return lexer->lookahead != '}';
+ }
+ }
+ }
+
+newline:
+ if (valid_symbols[NEWLINE]) {
+ while (iswspace(lexer->lookahead) && lexer->lookahead != '\n') {
+ skip(lexer);
+ }
+
+ if (lexer->lookahead == '\n') {
+ advance(lexer);
+ lexer->result_symbol = NEWLINE;
+ lexer->mark_end(lexer);
+
+ uint32_t nl_count = 0;
+
+ while (iswspace(lexer->lookahead)) {
+ if (lexer->lookahead == '\n') {
+ nl_count++;
+ }
+ skip(lexer);
+ }
+
+ const char *where = "where";
+ const char *_else = "else";
+ const char *bracket = "{";
+
+ char next_word[6] = {0};
+
+ // check for where and _else
+
+ for (int i = 0; i < 5; i++) {
+ if (iswspace(lexer->lookahead)) {
+ break;
+ }
+ next_word[i] = (char)lexer->lookahead;
+ advance(lexer);
+ }
+
+ if (strcmp(next_word, where) == 0 || strcmp(next_word, _else) == 0) {
+ if (!iswspace(lexer->lookahead)) {
+ return true;
+ }
+ goto backslash;
+ }
+
+ if (strcmp(next_word, bracket) == 0 && nl_count == 0 && valid_symbols[BRACKET]) {
+ return false;
+ }
+
+ return true;
+ }
+ // if (lexer->lookahead == ';') {
+ // advance(lexer);
+ // lexer->result_symbol = SEPARATOR;
+ // lexer->mark_end(lexer);
+ // while (iswspace(lexer->lookahead)) {
+ // advance(lexer);
+ // }
+ // return true;
+ // }
+ }
+
+backslash:
+ if (valid_symbols[BACKSLASH] && lexer->lookahead == '\\') {
+ advance(lexer);
+ if (lexer->lookahead == '\n') {
+ advance(lexer);
+ while (iswspace(lexer->lookahead)) {
+ advance(lexer);
+ }
+ lexer->result_symbol = BACKSLASH;
+ return true;
+ }
+ }
+
+ while (iswspace(lexer->lookahead)) {
+ skip(lexer);
+ }
+
+ if (valid_symbols[BLOCK_COMMENT] && lexer->lookahead == '/') {
+ advance(lexer);
+ if (lexer->lookahead != '*') {
+ return false;
+ }
+ advance(lexer);
+
+ if (lexer->lookahead == '"') {
+ return false;
+ }
+
+ bool after_star = false;
+ unsigned nesting_depth = 1;
+ for (;;) {
+ switch (lexer->lookahead) {
+ case '\0':
+ return false;
+ case '*':
+ advance(lexer);
+ after_star = true;
+ break;
+ case '/':
+ if (after_star) {
+ advance(lexer);
+ after_star = false;
+ nesting_depth--;
+ if (nesting_depth == 0) {
+ lexer->result_symbol = BLOCK_COMMENT;
+ return true;
+ }
+ } else {
+ advance(lexer);
+ after_star = false;
+ if (lexer->lookahead == '*') {
+ nesting_depth++;
+ advance(lexer);
+ }
+ }
+ break;
+ default:
+ advance(lexer);
+ after_star = false;
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+void tree_sitter_odin_external_scanner_destroy(void *payload) {}