#include "lexer.h" #include #include #include 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; }