Pause on lexing stuff

This commit is contained in:
Krzosa Karol
2026-02-03 23:23:49 +01:00
parent 51f1fd1b4f
commit 7a73a982d2
6 changed files with 110 additions and 113 deletions

View File

@@ -1,12 +1,3 @@
struct Lexer {
Allocator allocator;
char *at;
char *start;
char *end;
char *name;
Int line, column;
};
enum TriggerKind {
TriggerKind_Error,
TriggerKind_Key,
@@ -34,40 +25,7 @@ struct CachedTrigger {
};
Array<CachedTrigger> CachedTriggers;
Lexer MakeLexer(Allocator allocator, String string, char *file, Int line, Int column) {
Lexer lexer = {allocator, string.data, string.data, string.data + string.len, file, line, column};
return lexer;
}
void Advance(Lexer *lex) {
if (lex->at < lex->end) {
if (lex->at[0] == '\n') {
lex->line += 1;
lex->column = 0;
} else {
lex->column += 1;
}
lex->at += 1;
}
}
void Advance(Lexer *lex, int n) {
for (int i = 0; i < n; i += 1) Advance(lex);
}
char At(Lexer *lex) {
if (lex->at < lex->end) {
return lex->at[0];
}
return 0;
}
String AsString(Lexer *lex) {
String result = {lex->at, lex->end - lex->at};
return result;
}
void EatWhitespace(Lexer *lex) {
void EatWhitespaceEx(Lexer *lex) {
while (At(lex) != '\n' && IsWhitespace(At(lex))) {
Advance(lex);
}
@@ -85,7 +43,7 @@ Trigger *TriggerBinary(Lexer *lex, Trigger *left, Trigger *right, int key) {
Trigger *ParseKeyAtom(Lexer *lex) {
Trigger *result = AllocType(lex->allocator, Trigger);
result->kind = TriggerKind_Key;
EatWhitespace(lex);
EatWhitespaceEx(lex);
for (;;) {
String lex_string = AsString(lex);
if (StartsWith(lex_string, "ctrl")) {
@@ -123,12 +81,12 @@ Trigger *ParseKeyAtom(Lexer *lex) {
if (!found) {
result->kind = TriggerKind_Error;
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected identifier: '%d'", lex->name, lex->line, lex->column, result->key);
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected identifier: '%d'", lex->file, lex->line, lex->column, result->key);
return result;
}
} else {
result->kind = TriggerKind_Error;
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected character: '%c'", lex->name, lex->line, lex->column, At(lex));
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected character: '%c'", lex->file, lex->line, lex->column, At(lex));
return result;
}
@@ -143,21 +101,21 @@ Trigger *ParseKeyAtom(Lexer *lex) {
Trigger *ParseKeyChord(Lexer *lex) {
Trigger *left = ParseKeyAtom(lex);
EatWhitespace(lex);
EatWhitespaceEx(lex);
while (IsAlphanumeric(At(lex))) {
left = TriggerBinary(lex, left, ParseKeyChord(lex), ' ');
EatWhitespace(lex);
EatWhitespaceEx(lex);
}
return left;
}
Trigger *ParseKeyOr(Lexer *lex) {
Trigger *left = ParseKeyChord(lex);
EatWhitespace(lex);
EatWhitespaceEx(lex);
while (At(lex) == '|') {
Advance(lex);
left = TriggerBinary(lex, left, ParseKeyOr(lex), '|');
EatWhitespace(lex);
EatWhitespaceEx(lex);
}
return left;
}

View File

@@ -1,22 +1,25 @@
namespace DataDesc {
struct Lexer {
Allocator allocator;
char *at;
char *start;
char *end;
typedef U32 TokenKind;
enum {
TokenKind_EOF = 0,
TokenKind_Ident = (1<<0),
TokenKind_String = (1<<1),
TokenKind_Numeric = (1<<2),
TokenKind_Comment = (1<<3),
TokenKind_Error = (1<<4),
char *file;
int line, column;
TokenKind_OpenBrace = (1<<5),
TokenKind_CloseBrace = (1<<6),
TokenKind_Colon = (1<<7),
TokenKind_Comma = (1<<8),
TokenKind_Minus = (1<<9),
TokenKind_Tag = (1<<10),
TokenKind_Or = (1<<11),
};
enum TokenKind {
TokenKind_EOF,
TokenKind_String,
TokenKind_Colon,
TokenKind_Comma,
TokenKind_OpenBrace,
TokenKind_CloseBrace,
TokenKind_Error,
typedef U32 TokenGroup;
enum {
TokenGroup_String = (TokenKind_Numeric|TokenKind_String|TokenKind_Ident),
TokenGroup_Symbol = (TokenKind_OpenBrace|TokenKind_CloseBrace|TokenKind_Colon|TokenKind_Comma|TokenKind_Minus|TokenKind_Tag|TokenKind_Or),
};
struct Token {
@@ -25,14 +28,42 @@ struct Token {
struct {char *data; Int len;};
String string;
};
int line, column;
Float f;
Int line, column;
char *file;
};
Lexer MakeLexer(Allocator allocator, String string, char *file) {
Assert(string.data != NULL && string.data != 0);
Lexer result = {allocator, string.data, string.data, string.data + string.len};
result.file = file;
struct Lexer {
Allocator allocator;
char *at;
char *start;
char *end;
char *file;
Int line, column;
};
Lexer MakeLexer(Allocator allocator, String string, char *file, Int line, Int column) {
Lexer lexer = {allocator, string.data, string.data, string.data + string.len, file, line, column};
return lexer;
}
void Advance(Lexer *lex) {
if (lex->at < lex->end) {
if (lex->at[0] == '\n') {
lex->line += 1;
lex->column = 0;
}
lex->column += 1;
lex->at += 1;
}
}
void Advance(Lexer *lex, int n) {
for (int i = 0; i < n; i += 1) Advance(lex);
}
String AsString(Lexer *lex) {
String result = {lex->at, lex->end - lex->at};
return result;
}
@@ -43,18 +74,6 @@ char At(Lexer *lex) {
return 0;
}
void Advance(Lexer *lex) {
if (lex->at >= lex->end) {
return;
}
if (lex->at[0] == '\n') {
lex->line += 1;
lex->column = 0;
}
lex->column += 1;
lex->at += 1;
}
void EatWhitespace(Lexer *lex) {
while (IsWhitespace(At(lex))) {
Advance(lex);
@@ -82,8 +101,24 @@ void LexString(Lexer *lex, Token *t) {
t->len = (Int)(lex->at - t->data) - 1;
}
bool IsOkForIdent(char cc) {
bool result = IsAlphanumeric(cc) || cc == '_' || cc == '/' || cc == '-' || cc == '.' || cc == '@';
void LexDigit(Lexer *lex, Token *t) {
t->kind = TokenKind_Numeric;
for (;;) {
char c = At(lex);
if (c == 0) {
break;
}
if (!IsDigit(c)) {
break;
}
Advance(lex);
}
t->len = (Int)(lex->at - t->data);
t->f = (Float)strtoll(t->data, NULL, 10);
}
bool IsOkForIdent(Lexer *lex, char c) {
bool result = IsAlphanumeric(c) || c == '_' || c == '/';
return result;
}
@@ -99,7 +134,7 @@ Token Next(Lexer *lex) {
Advance(lex);
if (c == 0) {
t.kind = TokenKind_EOF;
return t;
} else if (c == '{') {
t.kind = TokenKind_OpenBrace;
} else if (c == '}') {
@@ -108,15 +143,17 @@ Token Next(Lexer *lex) {
t.kind = TokenKind_Colon;
} else if (c == ',') {
t.kind = TokenKind_Comma;
} else if (IsDigit(c)) {
LexDigit(lex, &t);
} else if (c == '"') {
LexString(lex, &t);
} else if (c == '`') {
LexString(lex, &t);
} else if (IsOkForIdent(c)) {
} else if (IsOkForIdent(lex, c)) {
t.kind = TokenKind_String;
for (;;) {
char cc = At(lex);
bool ok = IsOkForIdent(cc);
bool ok = IsOkForIdent(lex, cc);
if (!ok) {
break;
}
@@ -132,10 +169,10 @@ Token Next(Lexer *lex) {
return t;
}
void RunDataDescriptionTest() {
void TestDataDesc() {
Scratch scratch;
String s = "{/usr/bin/python3, `Hidden`, Input:Clipboard}";
Lexer lexer = MakeLexer(scratch, s, "test");
Lexer lexer = MakeLexer(scratch, s, "test", 0, 0);
{
Token tok = {};
tok = Next(&lexer);
@@ -179,6 +216,4 @@ void RunDataDescriptionTest() {
Assert(tok.kind == TokenKind_EOF);
}
} RegisterFunction(&TestFunctions, RunDataDescriptionTest);
}
} RegisterFunction(&TestFunctions, TestDataDesc);

View File

@@ -12,7 +12,6 @@ bool BreakOnError = false;
Int ErrorCount;
Allocator SysAllocator = {SystemAllocatorProc};
String ConfigDir;
float DPIScale = 1.0f;
// @WARNING: be careful about using this, should only be used for debugging
@@ -175,7 +174,8 @@ RegisterVariable(String, InternetBrowser, "firefox");
RegisterVariable(String, OpenCodePatterns, ".c .h .cpp .hpp .cc .cxx .rs .go .zig .py .lua .js .ts .jsx .tsx .java .kt .swift .cs .rb .php .html .css .scss .bat .sh .bash .zsh .sql .asm .s .cmake .make .json .yaml .toml .ini .txt .md .rst .Makefile .Dockerfile .gitignore .bashrc .zshrc");
RegisterVariable(String, OpenCodeExcludePatterns, "");
RegisterVariable(Int, TrimTrailingWhitespace, 1);
RegisterVariable(String, HomeFolder, "");
RegisterVariable(String, ConfigFolder, "");
// PROJECT_MANAGEMENT
// Set at the beginning of the program to current directory

View File

@@ -861,7 +861,21 @@ int main(int argc, char **argv)
#endif
InitScratch();
InitOS(ReportErrorf);
ProjectFolder = GetWorkingDir(Perm);
HomeFolder = SDL_GetUserFolder(SDL_FOLDER_HOME);
{
String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor");
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') {
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
}
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') {
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
}
ConfigFolder = NormalizePath(Perm, sdl_config_path);
SDL_free(sdl_config_path.data);
}
#if OS_WINDOWS
{
wchar_t *p = GetEnvironmentStringsW();
@@ -889,18 +903,6 @@ int main(int argc, char **argv)
// return 0;
}
{
String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor");
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') {
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
}
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') {
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
}
ConfigDir = NormalizePath(Perm, sdl_config_path);
SDL_free(sdl_config_path.data);
}
if (!SDL_Init(SDL_INIT_VIDEO)) {
ReportErrorf("Couldn't initialize SDL! %s", SDL_GetError());
return 1;
@@ -1027,7 +1029,7 @@ int main(int argc, char **argv)
#if PLUGIN_CONFIG
{
Scratch scratch;
GlobalConfigBufferID = LoadConfig(Format(scratch, "%S/config.te", ConfigDir));
GlobalConfigBufferID = LoadConfig(Format(scratch, "%S/config.te", ConfigFolder));
}
#endif
for (int i = 1; i < argc; i += 1) {

View File

@@ -325,15 +325,17 @@ Otherwise it does filepath parsing:
./thing(10)
TODO: need to add '~', but where?
USECASE: Wouldn't it be cool to just select a part of codebase pipe that into a script
and get a result in a clipboard or capture the output and change the selection.
TODO: Data desc language
and get a result in a clipboard or capture the output and change the selection?
PREV IDEA:
!{bash,Out:Sel} SCRIPT
!{bash,Out:Clip} SCRIPT
Use variables for injecting selection: @Sel
TODO: I would pause the data desc language, seems a bit cumbersome... think of more concrete, constrained ideas
TODO: Unify lexers (Set and Trigger)
*/
ResolvedOpen ResolveOpen(Allocator alo, Window *window, String path, ResolveOpenMeta meta) {
ResolvedOpen result = {};