diff options
Diffstat (limited to '21sh/ll-expr/src/lexer/lexer.c')
| -rw-r--r-- | 21sh/ll-expr/src/lexer/lexer.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/21sh/ll-expr/src/lexer/lexer.c b/21sh/ll-expr/src/lexer/lexer.c new file mode 100644 index 0000000..3b3d29f --- /dev/null +++ b/21sh/ll-expr/src/lexer/lexer.c @@ -0,0 +1,104 @@ +#include "lexer.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct lexer *lexer_new(const char *input) +{ + struct lexer *new = malloc(sizeof(struct lexer)); + new->input = input; + new->pos = 0; + return new; +} + +void lexer_free(struct lexer *lexer) +{ + free(lexer); +} + +struct template +{ + char value; + enum token_type type; +}; + +struct template templates[] = { + { '+', TOKEN_PLUS }, { '-', TOKEN_MINUS }, { '*', TOKEN_MUL }, + { '/', TOKEN_DIV }, { '(', TOKEN_LEFT_PAR }, { ')', TOKEN_RIGHT_PAR }, + { '\0', TOKEN_EOF }, { 0, TOKEN_ERROR } +}; + +static ssize_t parse_number(struct lexer *l) +{ + union + { + const char *cc; + char *c; + } cast; + cast.cc = l->input + l->pos; + char *in = cast.c; + size_t t = 0; + while (in[t] && in[t] >= '0' && in[t] <= '9') + t++; + char tmp = in[t]; + in[t] = '\0'; + ssize_t res = atoi(in); + in[t] = tmp; + return res; +} + +struct token lexer_next_token(struct lexer *lexer) +{ + for (; lexer->input[lexer->pos] && lexer->input[lexer->pos] == ' '; + lexer->pos++) + continue; + for (int i = 0; i < 7; i++) + { + if (lexer->input[lexer->pos] == templates[i].value) + { + lexer->current_tok.type = templates[i].type; + return lexer->current_tok; + } + } + if (lexer->input[lexer->pos] > '9' || lexer->input[lexer->pos] < '0') + { + lexer->current_tok.type = TOKEN_ERROR; + fprintf(stderr, "lexer: invalid token %c\n", lexer->input[lexer->pos]); + return lexer->current_tok; + } + else + { + lexer->current_tok.type = TOKEN_NUMBER; + lexer->current_tok.value = parse_number(lexer); + return lexer->current_tok; + } +} + +struct token lexer_peek(struct lexer *lexer) +{ + return lexer_next_token(lexer); +} + +static size_t count_numbers(ssize_t value) +{ + if (value == 0) + return 1; + size_t size = 0; + while (value) + { + size++; + value /= 10; + } + return size; +} + +struct token lexer_pop(struct lexer *lexer) +{ + struct token res = lexer_next_token(lexer); + if (res.type == TOKEN_NUMBER) + lexer->pos += count_numbers(res.value); + else + lexer->pos++; + return res; +} |
