Begin data_desc
This commit is contained in:
184
src/text_editor/data_desc.cpp
Normal file
184
src/text_editor/data_desc.cpp
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
namespace DataDesc {
|
||||||
|
struct Lexer {
|
||||||
|
Allocator allocator;
|
||||||
|
char *at;
|
||||||
|
char *start;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
char *file;
|
||||||
|
int line, column;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TokenKind {
|
||||||
|
TokenKind_EOF,
|
||||||
|
TokenKind_String,
|
||||||
|
TokenKind_Colon,
|
||||||
|
TokenKind_Comma,
|
||||||
|
TokenKind_OpenBrace,
|
||||||
|
TokenKind_CloseBrace,
|
||||||
|
TokenKind_Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Token {
|
||||||
|
TokenKind kind;
|
||||||
|
union {
|
||||||
|
struct {char *data; Int len;};
|
||||||
|
String string;
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char At(Lexer *lex) {
|
||||||
|
if (lex->at < lex->end) {
|
||||||
|
return lex->at[0];
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LexString(Lexer *lex, Token *t) {
|
||||||
|
t->kind = TokenKind_String;
|
||||||
|
char end_char = t->data[0];
|
||||||
|
t->data += 1;
|
||||||
|
for (;;) {
|
||||||
|
char c = At(lex);
|
||||||
|
if (c == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == end_char) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == '\\') {
|
||||||
|
Advance(lex);
|
||||||
|
}
|
||||||
|
Advance(lex);
|
||||||
|
}
|
||||||
|
Advance(lex);
|
||||||
|
t->len = (Int)(lex->at - t->data) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOkForIdent(char cc) {
|
||||||
|
bool result = IsAlphanumeric(cc) || cc == '_' || cc == '/' || cc == '-' || cc == '.' || cc == '@';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token Next(Lexer *lex) {
|
||||||
|
EatWhitespace(lex);
|
||||||
|
Token t = {};
|
||||||
|
t.data = lex->at;
|
||||||
|
t.len = 1;
|
||||||
|
t.line = lex->line;
|
||||||
|
t.column = lex->column;
|
||||||
|
t.file = lex->file;
|
||||||
|
char c = At(lex);
|
||||||
|
Advance(lex);
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
t.kind = TokenKind_EOF;
|
||||||
|
} else if (c == '{') {
|
||||||
|
t.kind = TokenKind_OpenBrace;
|
||||||
|
} else if (c == '}') {
|
||||||
|
t.kind = TokenKind_CloseBrace;
|
||||||
|
} else if (c == ':') {
|
||||||
|
t.kind = TokenKind_Colon;
|
||||||
|
} else if (c == ',') {
|
||||||
|
t.kind = TokenKind_Comma;
|
||||||
|
} else if (c == '"') {
|
||||||
|
LexString(lex, &t);
|
||||||
|
} else if (c == '`') {
|
||||||
|
LexString(lex, &t);
|
||||||
|
} else if (IsOkForIdent(c)) {
|
||||||
|
t.kind = TokenKind_String;
|
||||||
|
for (;;) {
|
||||||
|
char cc = At(lex);
|
||||||
|
bool ok = IsOkForIdent(cc);
|
||||||
|
if (!ok) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Advance(lex);
|
||||||
|
}
|
||||||
|
t.len = (Int)(lex->at - t.data);
|
||||||
|
} else {
|
||||||
|
t.kind = TokenKind_Error;
|
||||||
|
t.string = Format(lex->allocator, "Got invalid character when parsing: '%c'", c);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunDataDescriptionTest() {
|
||||||
|
Scratch scratch;
|
||||||
|
String s = "{/usr/bin/python3, `Hidden`, Input:Clipboard}";
|
||||||
|
Lexer lexer = MakeLexer(scratch, s, "test");
|
||||||
|
{
|
||||||
|
Token tok = {};
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_OpenBrace);
|
||||||
|
Assert(tok.len == 1);
|
||||||
|
Assert(tok.data[0] == '{');
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_String);
|
||||||
|
Assert(tok.string == "/usr/bin/python3");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_Comma);
|
||||||
|
Assert(tok.string == ",");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_String);
|
||||||
|
Assert(tok.string == "Hidden");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_Comma);
|
||||||
|
Assert(tok.string == ",");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_String);
|
||||||
|
Assert(tok.string == "Input");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_Colon);
|
||||||
|
Assert(tok.string == ":");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_String);
|
||||||
|
Assert(tok.string == "Clipboard");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_CloseBrace);
|
||||||
|
Assert(tok.string == "}");
|
||||||
|
|
||||||
|
tok = Next(&lexer);
|
||||||
|
Assert(tok.kind == TokenKind_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} RegisterFunction(&TestFunctions, RunDataDescriptionTest);
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
#include "text_editor.h"
|
#include "text_editor.h"
|
||||||
#include "globals.cpp"
|
#include "globals.cpp"
|
||||||
#include "coroutines.cpp"
|
#include "coroutines.cpp"
|
||||||
|
#include "data_desc.cpp"
|
||||||
#include "buffer.cpp"
|
#include "buffer.cpp"
|
||||||
#include "view.cpp"
|
#include "view.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
|
|||||||
Reference in New Issue
Block a user