// Pruebas del analizador léxico. Si algo falla, assert dice en qué línea.
#include <assert.h>
#include <string.h>

#include "lexer.h"

// Comprueba que el texto produzca esos tipos de token, y luego TOKEN_END.
static void check_kinds(const char *source, const TokenKind *wanted, int count) {
    Lexer *lexer = lexer_new(source);
    assert(lexer != NULL);
    for (int i = 0; i < count; i++) {
        assert(lexer_next(lexer).kind == wanted[i]);
    }
    assert(lexer_next(lexer).kind == TOKEN_END);
    lexer_free(lexer);
}

static void test_symbols_and_names(void) {
    const TokenKind wanted[] = {TOKEN_LET, TOKEN_NAME, TOKEN_ASSIGN, TOKEN_NUMBER, TOKEN_STAR, TOKEN_LPAREN,
                                TOKEN_NAME, TOKEN_PLUS, TOKEN_NUMBER, TOKEN_RPAREN};
    check_kinds("let x1 = 3*(y+2)", wanted, 10);
}

static void test_a_keyword_needs_the_whole_word(void) {
    const TokenKind wanted[] = {TOKEN_NAME, TOKEN_NAME, TOKEN_IF};
    check_kinds("lets _if if", wanted, 3);
}

static void test_number_value_and_text(void) {
    Lexer *lexer = lexer_new("3.25");
    assert(lexer != NULL);
    Token token = lexer_next(lexer);
    assert(token.kind == TOKEN_NUMBER);
    assert(token.number == 3.25);
    assert(strcmp(token.text, "3.25") == 0);
    lexer_free(lexer);
}

static void test_positions(void) {
    Lexer *lexer = lexer_new("x\n  +");
    assert(lexer != NULL);
    Token first = lexer_next(lexer);
    assert(first.line == 1 && first.column == 1);
    Token second = lexer_next(lexer);
    assert(second.line == 2 && second.column == 3);
    lexer_free(lexer);
}

static void test_unknown_character(void) {
    Lexer *lexer = lexer_new("@ 1");
    assert(lexer != NULL);
    assert(lexer_next(lexer).kind == TOKEN_ERROR);
    assert(lexer_next(lexer).kind == TOKEN_NUMBER);
    lexer_free(lexer);
}

// Parte 1: agreguen aquí sus pruebas de los comparadores y de los comentarios,
// y llámenlas desde main.

int main(void) {
    test_symbols_and_names();
    test_a_keyword_needs_the_whole_word();
    test_number_value_and_text();
    test_positions();
    test_unknown_character();
    return 0;
}
