feat: started project and lexer
This commit is contained in:
commit
a6c17eff5f
8 changed files with 344 additions and 0 deletions
40
src/_include/mrk/lexer_internal.h
Normal file
40
src/_include/mrk/lexer_internal.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef MRK_LEXER_INTERNAL
|
||||
#define MRK_LEXER_INTERNAL
|
||||
|
||||
#include "mrk/lexer.h"
|
||||
|
||||
struct mrk_lexer {
|
||||
struct {
|
||||
const char *s;
|
||||
size_t len;
|
||||
} buf;
|
||||
struct {
|
||||
size_t line;
|
||||
size_t line_index;
|
||||
size_t buf_index;
|
||||
} pos;
|
||||
struct {
|
||||
size_t start;
|
||||
size_t end;
|
||||
} token;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the next character that would be consumed by a call to advance. At the
|
||||
* end of the buffer, this value is nul.
|
||||
*/
|
||||
char mrk_lexer_peek(mrk_lexer *lexer);
|
||||
|
||||
/**
|
||||
* Advance the current position by one character, adding the new character to
|
||||
* the curent token's context and returning it.
|
||||
*/
|
||||
char mrk_lexer_advance(mrk_lexer *lexer);
|
||||
|
||||
/**
|
||||
* Output the currently matched token to the token struct with the given type,
|
||||
* and reset the lexer's tracked token.
|
||||
*/
|
||||
void mrk_lexer_emit(mrk_token *out, mrk_lexer *lexer, mrk_token_type type);
|
||||
|
||||
#endif
|
||||
73
src/lexer/lexer.c
Normal file
73
src/lexer/lexer.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "mrk/lexer_internal.h"
|
||||
|
||||
mrk_err mrk_lexer_init(mrk_lexer **out) {
|
||||
MRK_CALLOC(out, 1, sizeof(mrk_lexer));
|
||||
|
||||
return mrk_err_ok;
|
||||
}
|
||||
|
||||
void mrk_lexer_open(mrk_lexer *lexer, const char *buf, size_t len) {
|
||||
lexer->buf.s = buf;
|
||||
lexer->buf.len = len;
|
||||
lexer->pos.line = 0;
|
||||
lexer->pos.buf_index = 0;
|
||||
lexer->token.start = 0;
|
||||
lexer->token.end = 0;
|
||||
}
|
||||
|
||||
bool mrk_lexer_at_end(const mrk_lexer *lexer) {
|
||||
return (lexer->buf.len > 0 && lexer->pos.buf_index == lexer->buf.len) ||
|
||||
(lexer->buf.s[lexer->pos.buf_index] == '\0');
|
||||
}
|
||||
|
||||
char mrk_lexer_advance(mrk_lexer *lexer) {
|
||||
if (mrk_lexer_at_end(lexer)) {
|
||||
return '\0';
|
||||
}
|
||||
|
||||
char c = lexer->buf.s[lexer->pos.buf_index];
|
||||
|
||||
// A newline is still part of the previous line, so if the last character was
|
||||
// a newline, we now go to the next line
|
||||
if (lexer->buf.s[lexer->pos.buf_index] == '\0') {
|
||||
lexer->pos.line++;
|
||||
lexer->pos.line_index = 0;
|
||||
} else {
|
||||
lexer->pos.line_index++;
|
||||
}
|
||||
|
||||
lexer->pos.buf_index++;
|
||||
lexer->token.end++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
char mrk_lexer_peek(mrk_lexer *lexer) {
|
||||
if (mrk_lexer_at_end(lexer)) {
|
||||
return '\0';
|
||||
}
|
||||
|
||||
return lexer->buf.s[lexer->pos.buf_index];
|
||||
}
|
||||
|
||||
void mrk_lexer_emit(mrk_token *out, mrk_lexer *lexer, mrk_token_type type) {
|
||||
out->type = type;
|
||||
out->start = lexer->token.start;
|
||||
out->start = lexer->token.end;
|
||||
|
||||
lexer->token.start = lexer->token.end;
|
||||
}
|
||||
|
||||
mrk_lexer_err mrk_lexer_next(mrk_token *out, mrk_lexer *lexer) {
|
||||
if (mrk_lexer_at_end(lexer)) {
|
||||
return mrk_lexer_err_done;
|
||||
}
|
||||
|
||||
switch (mrk_lexer_advance(lexer)) {
|
||||
case '#':
|
||||
mrk_lexer_emit(out, lexer, mrk_token_type_pound);
|
||||
break;
|
||||
}
|
||||
|
||||
return mrk_lexer_err_ok;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue