diff --git a/build.sh b/build.sh index 2c961d43..ff6f278a 100755 --- a/build.sh +++ b/build.sh @@ -12,4 +12,4 @@ if [ `uname` = "Darwin" ]; then CFLAGS+=" -framework OpenGL" fi -$CC $CFLAGS `pkg-config --cflags $PKGS` -o ded $SRC $LIBS `pkg-config --libs $PKGS` +$CC $CFLAGS `pkg-config --cflags $PKGS` -g -o ded $SRC $LIBS `pkg-config --libs $PKGS` diff --git a/src/editor.c b/src/editor.c index 1aaeee76..8175ab5f 100644 --- a/src/editor.c +++ b/src/editor.c @@ -218,7 +218,7 @@ void editor_retokenize(Editor *e) // Syntax Highlighting { e->tokens.count = 0; - Lexer l = lexer_new(e->atlas, e->data.items, e->data.count); + Lexer l = lexer_new(e->atlas, e->data.items, e->data.count, e->file_path); Token t = lexer_next(&l); while (t.kind != TOKEN_END) { da_append(&e->tokens, t); diff --git a/src/lexer.c b/src/lexer.c index cfd9022c..a5c185dc 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "common.h" #include "lexer.h" @@ -19,7 +20,27 @@ Literal_Token literal_tokens[] = { }; #define literal_tokens_count (sizeof(literal_tokens)/sizeof(literal_tokens[0])) -const char *keywords[] = { +const char *jKeywords[] = { + "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", + "const", "continue", "default", "do", "double", "else", "enum", "extends", "final", + "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", + "interface", "long", "native", "new", "package", "private", "protected", "public", + "return", "short", "static", "super", "switch", "synchronized", "this", "throw", + "throws", "transient", "try", "void", "volatile", "while", "non-sealed", "open", + "opens", "permits", "provides", "record", "sealed", "to", "transitive", "uses", "var", + "with", "yield", "true", "false", "null", "const", "goto", "strictfp", +}; +#define jKeywords_count (sizeof(jKeywords)/sizeof(jKeywords[0])) + +const char *ktKeywords[] = { + "abstract", "break", "catch", "class", "const", "continue", "else", "enum", "is", "as", + "when", "val", "var", "for", "if", "import", "interface", "data", "external", "inner", + "package", "private", "protected", "return", "super", "when", "this", "throw", + "try", "while", "sealed", "open", "true", "false", "null", "fun", "typealias", +}; +#define ktKeywords_count (sizeof(ktKeywords)/sizeof(ktKeywords[0])) + +const char *cKeywords[] = { "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", @@ -34,7 +55,15 @@ const char *keywords[] = { "template", "this", "thread_local", "throw", "true", "try", "typeid", "typename", "using", "virtual", "wchar_t", "xor", "xor_eq", }; -#define keywords_count (sizeof(keywords)/sizeof(keywords[0])) +#define cKeywords_count (sizeof(cKeywords)/sizeof(cKeywords[0])) + +const char *pyKeywords[] = { + "False", "None", "True", "and", "as", "assert", "async", "await", "break", "class", + "continue", "def", "del", "elif", "else", "except", "finally", "for", "from", "global", + "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "raise", + "return", "try", "while", "with", "yield", +}; +#define pyKeywords_count (sizeof(pyKeywords)/sizeof(pyKeywords[0])) const char *token_kind_name(Token_Kind kind) { @@ -65,12 +94,38 @@ const char *token_kind_name(Token_Kind kind) return NULL; } -Lexer lexer_new(Free_Glyph_Atlas *atlas, const char *content, size_t content_len) +Lexer lexer_new(Free_Glyph_Atlas *atlas, const char *content, size_t content_len, String_Builder file_path) { Lexer l = {0}; l.atlas = atlas; l.content = content; l.content_len = content_len; + if (file_path.items != NULL) { + l.file_path.items = (char*) malloc(sizeof(char*) * (strlen(file_path.items) + 1)); + strcpy(l.file_path.items, file_path.items); + + File_Extension file_ext; + const char *filename = l.file_path.items; + const char *dot = strrchr(filename, '.'); + if (!dot || dot == filename) { + file_ext = FEXT_CPP; + } else { + const char *file_ext_str = dot + 1; + + if (strcmp(file_ext_str, "kt") == 0 || strcmp(file_ext_str, "kts") == 0) { + file_ext = FEXT_KOTLIN; + } else if (strcmp(file_ext_str, "py") == 0) { + file_ext = FEXT_PYTHON; + } else if (strcmp(file_ext_str, "java") == 0) { + file_ext = FEXT_JAVA; + } else { + file_ext = FEXT_CPP; + } + } + + l.file_ext = file_ext; + } + return l; } @@ -202,6 +257,30 @@ Token lexer_next(Lexer *l) lexer_chop_char(l, 1); token.text_len += 1; } + + const char **keywords; + size_t keywords_count; + switch (l->file_ext) { + case FEXT_JAVA: + keywords = jKeywords; + keywords_count = jKeywords_count; + break; + + case FEXT_KOTLIN: + keywords = ktKeywords; + keywords_count = ktKeywords_count; + break; + + case FEXT_PYTHON: + keywords = pyKeywords; + keywords_count = pyKeywords_count; + break; + + default: + keywords = cKeywords; + keywords_count = cKeywords_count; + } + for (size_t i = 0; i < keywords_count; ++i) { size_t keyword_len = strlen(keywords[i]); @@ -210,7 +289,7 @@ Token lexer_next(Lexer *l) break; } } - + return token; } diff --git a/src/lexer.h b/src/lexer.h index 6ee721ed..3801a358 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -4,6 +4,14 @@ #include #include "./la.h" #include "./free_glyph.h" +#include "./common.h" + +typedef enum { + FEXT_KOTLIN, + FEXT_JAVA, + FEXT_CPP, + FEXT_PYTHON, +} File_Extension; typedef enum { TOKEN_END = 0, @@ -37,9 +45,11 @@ typedef struct { size_t line; size_t bol; float x; + String_Builder file_path; + File_Extension file_ext; } Lexer; -Lexer lexer_new(Free_Glyph_Atlas *atlas, const char *content, size_t content_len); +Lexer lexer_new(Free_Glyph_Atlas *atlas, const char *content, size_t content_len, String_Builder file_path); Token lexer_next(Lexer *l); #endif // LEXER_H_