// Análisis léxico del lenguaje Mini: parte un texto en tokens, uno por llamada.
//
// Owner: quien llama a lexer_new libera con lexer_free. El lexer no copia el texto:
// source debe seguir vivo mientras se use el lexer.
#ifndef LEXER_H
#define LEXER_H

typedef enum {
    TOKEN_NUMBER, TOKEN_NAME,
    TOKEN_LET, TOKEN_PRINT, TOKEN_DEF, TOKEN_IF, TOKEN_THEN, TOKEN_ELSE,
    TOKEN_PLUS, TOKEN_MINUS, TOKEN_STAR, TOKEN_SLASH,
    TOKEN_LPAREN, TOKEN_RPAREN, TOKEN_COMMA, TOKEN_ASSIGN,
    TOKEN_LESS, TOKEN_LESS_EQUAL, TOKEN_GREATER, TOKEN_GREATER_EQUAL, TOKEN_EQUAL, TOKEN_NOT_EQUAL,
    TOKEN_END, TOKEN_ERROR
} TokenKind;

// line y column empiezan en 1 y dicen dónde empieza el token. column cuenta bytes.
// text es el texto del token. En un TOKEN_ERROR, text es el mensaje de error.
// number solo tiene sentido en un TOKEN_NUMBER.
typedef struct {
    TokenKind kind;
    double number;
    char text[64];
    int line;
    int column;
} Token;

typedef struct lexer Lexer;

// Devuelve NULL si no hay memoria.
Lexer *lexer_new(const char *source);

// Acepta NULL.
void lexer_free(Lexer *lexer);

// Devuelve el token siguiente. Al llegar al final devuelve TOKEN_END, y lo sigue
// devolviendo si se le vuelve a llamar. Después de un TOKEN_ERROR se puede seguir.
Token lexer_next(Lexer *lexer);

#endif
