L2_TOK_CLOSE_BRACKET, | L2_TOK_CLOSE_BRACKET, | ||||
L2_TOK_COMMA, | L2_TOK_COMMA, | ||||
L2_TOK_PERIOD, | L2_TOK_PERIOD, | ||||
L2_TOK_NUMBER, | |||||
L2_TOK_EOF, | L2_TOK_EOF, | ||||
L2_TOK_NUMBER, | |||||
L2_TOK_STRING, | L2_TOK_STRING, | ||||
L2_TOK_ERROR, | L2_TOK_ERROR, | ||||
}; | }; | ||||
const char *l2_token_kind_name(enum l2_token_kind kind); | |||||
struct l2_token { | struct l2_token { | ||||
enum l2_token_kind kind; | enum l2_token_kind kind; | ||||
int line; | int line; | ||||
void l2_token_free(struct l2_token *tok); | void l2_token_free(struct l2_token *tok); | ||||
struct l2_token l2_token_move(struct l2_token *tok); | struct l2_token l2_token_move(struct l2_token *tok); | ||||
void l2_token_print(struct l2_token *tok, struct l2_io_writer *w); | |||||
struct l2_lexer { | struct l2_lexer { | ||||
struct l2_token currtok; | struct l2_token currtok; |
#include "io.h" | #include "io.h" | ||||
#include "parse/lex.h" | |||||
int main() { | int main() { | ||||
struct l2_io_mem_reader r = { l2_io_mem_read }; | struct l2_io_mem_reader r = { l2_io_mem_read }; | ||||
r.mem = "Hello World"; | |||||
r.mem = " \"Hello\", [], {}."; | |||||
r.len = strlen(r.mem); | r.len = strlen(r.mem); | ||||
struct l2_bufio_reader rb; | |||||
l2_bufio_reader_init(&rb, &r.r); | |||||
struct l2_lexer lexer; | |||||
l2_lexer_init(&lexer, &r.r); | |||||
while (1) { | while (1) { | ||||
int ch = l2_bufio_get(&rb); | |||||
if (ch == EOF) break; | |||||
printf("%c", (char)ch); | |||||
struct l2_token *tok = l2_lexer_get(&lexer); | |||||
printf("%s\n", l2_token_kind_name(tok->kind)); | |||||
if (tok->kind == L2_TOK_EOF) { | |||||
break; | |||||
} | |||||
} | } | ||||
printf("\n"); | |||||
} | } |
#include <stdlib.h> | #include <stdlib.h> | ||||
const char *l2_token_kind_name(enum l2_token_kind kind) { | |||||
switch (kind) { | |||||
case L2_TOK_OPEN_PAREN: | |||||
return "open-paren"; | |||||
case L2_TOK_CLOSE_PAREN: | |||||
return "close-paren"; | |||||
case L2_TOK_OPEN_BRACE: | |||||
return "open-brace"; | |||||
case L2_TOK_CLOSE_BRACE: | |||||
return "close-brace"; | |||||
case L2_TOK_OPEN_BRACKET: | |||||
return "open-bracket"; | |||||
case L2_TOK_CLOSE_BRACKET: | |||||
return "close-bracket"; | |||||
case L2_TOK_COMMA: | |||||
return "comma"; | |||||
case L2_TOK_PERIOD: | |||||
return "period"; | |||||
case L2_TOK_EOF: | |||||
return "end-of-file"; | |||||
case L2_TOK_NUMBER: | |||||
return "number"; | |||||
case L2_TOK_STRING: | |||||
return "string"; | |||||
case L2_TOK_ERROR: | |||||
return "error"; | |||||
} | |||||
} | |||||
void l2_token_free(struct l2_token *tok) { | void l2_token_free(struct l2_token *tok) { | ||||
if (tok->kind == L2_TOK_STRING) { | if (tok->kind == L2_TOK_STRING) { | ||||
free(tok->v.str); | free(tok->v.str); |