First commit

This commit is contained in:
mguinhos committed 2026-10-06 22:38:04 +00:00
commit dccc52bd7c
24 files changed
+1702

No files matched your search

+108
View File
@@ -0,0 +1,108 @@
#include "micropascal-tests/testes.h"
#include "micropascal-lexer/lexer.h"
#include <string.h>
static TokenKind tokenDe(const char* fonte)
{
Lexer lexer;
Token token;
lexerInicializar(&lexer, fonte);
token = lexerProximoToken(&lexer);
tokenLiberar(&token);
return token.kind;
}
static int lexemaDe(const char* fonte, const char* esperado)
{
Lexer lexer;
Token token;
int igual;
lexerInicializar(&lexer, fonte);
token = lexerProximoToken(&lexer);
igual = token.lexema != NULL && strcmp(token.lexema, esperado) == 0;
tokenLiberar(&token);
return igual;
}
static int contaTokens(const char* fonte)
{
Lexer lexer;
Token token;
int contador = 0;
lexerInicializar(&lexer, fonte);
while (1) {
token = lexerProximoToken(&lexer);
contador++;
if (token.kind == TOKEN_EOF || token.kind == TOKEN_ERRO) {
tokenLiberar(&token);
break;
}
tokenLiberar(&token);
}
return contador;
}
void runLexerTests(ResultadoTeste* resultado_testes)
{
TESTE_ASSERT(resultado_testes, tokenDe("program") == TOKEN_PROGRAM, "reconhece program");
TESTE_ASSERT(resultado_testes, tokenDe("if") == TOKEN_IF, "reconhece if");
TESTE_ASSERT(resultado_testes, tokenDe("then") == TOKEN_THEN, "reconhece then");
TESTE_ASSERT(resultado_testes, tokenDe("else") == TOKEN_ELSE, "reconhece else");
TESTE_ASSERT(resultado_testes, tokenDe("while") == TOKEN_WHILE, "reconhece while");
TESTE_ASSERT(resultado_testes, tokenDe("do") == TOKEN_DO, "reconhece do");
TESTE_ASSERT(resultado_testes, tokenDe("repeat") == TOKEN_REPEAT, "reconhece repeat");
TESTE_ASSERT(resultado_testes, tokenDe("until") == TOKEN_UNTIL, "reconhece until");
TESTE_ASSERT(resultado_testes, tokenDe("integer") == TOKEN_INTEGER, "reconhece integer");
TESTE_ASSERT(resultado_testes, tokenDe("real") == TOKEN_REAL, "reconhece real");
TESTE_ASSERT(resultado_testes, tokenDe("char") == TOKEN_CHAR, "reconhece char");
TESTE_ASSERT(resultado_testes, tokenDe("begin") == TOKEN_BEGIN, "reconhece begin");
TESTE_ASSERT(resultado_testes, tokenDe("end") == TOKEN_END, "reconhece end");
TESTE_ASSERT(resultado_testes, tokenDe("write") == TOKEN_WRITE, "reconhece write");
TESTE_ASSERT(resultado_testes, tokenDe("var") == TOKEN_VAR, "reconhece var");
TESTE_ASSERT(resultado_testes, tokenDe("div") == TOKEN_DIV, "reconhece div");
TESTE_ASSERT(resultado_testes, tokenDe("and") == TOKEN_AND, "reconhece and");
TESTE_ASSERT(resultado_testes, tokenDe("or") == TOKEN_OR, "reconhece or");
TESTE_ASSERT(resultado_testes, tokenDe("not") == TOKEN_NOT, "reconhece not");
TESTE_ASSERT(resultado_testes, tokenDe("Begin") == TOKEN_IDENTIFICADOR, "Begin nao e palavra reservada");
TESTE_ASSERT(resultado_testes, tokenDe("PROGRAM") == TOKEN_IDENTIFICADOR, "PROGRAM nao e palavra reservada");
TESTE_ASSERT(resultado_testes, tokenDe("_contador") == TOKEN_IDENTIFICADOR, "identificador com underscore");
TESTE_ASSERT(resultado_testes, tokenDe("abc123") == TOKEN_IDENTIFICADOR, "identificador alfanumerico");
TESTE_ASSERT(resultado_testes, lexemaDe("xyz", "xyz"), "lexema do identificador preservado");
TESTE_ASSERT(resultado_testes, tokenDe("123") == TOKEN_INTEIRO_LITERAL, "inteiro literal");
TESTE_ASSERT(resultado_testes, tokenDe("0") == TOKEN_INTEIRO_LITERAL, "inteiro literal zero");
TESTE_ASSERT(resultado_testes, tokenDe("3.14") == TOKEN_REAL_LITERAL, "real literal");
TESTE_ASSERT(resultado_testes, tokenDe("0.5") == TOKEN_REAL_LITERAL, "real literal com zero a esquerda");
TESTE_ASSERT(resultado_testes, tokenDe(".5") == TOKEN_REAL_LITERAL, "real literal sem parte inteira");
TESTE_ASSERT(resultado_testes, tokenDe("7.0") == TOKEN_REAL_LITERAL, "real literal inteiro");
TESTE_ASSERT(resultado_testes, tokenDe("'a'") == TOKEN_CHAR_LITERAL, "char literal letra");
TESTE_ASSERT(resultado_testes, tokenDe("'0'") == TOKEN_CHAR_LITERAL, "char literal digito");
TESTE_ASSERT(resultado_testes, tokenDe("'\\n'") == TOKEN_CHAR_LITERAL, "char literal quebra de linha");
TESTE_ASSERT(resultado_testes, tokenDe("'\\t'") == TOKEN_CHAR_LITERAL, "char literal tabulacao");
TESTE_ASSERT(resultado_testes, tokenDe("<") == TOKEN_MENOR, "menor");
TESTE_ASSERT(resultado_testes, tokenDe(">") == TOKEN_MAIOR, "maior");
TESTE_ASSERT(resultado_testes, tokenDe("<=") == TOKEN_MENOR_IGUAL, "menor ou igual");
TESTE_ASSERT(resultado_testes, tokenDe(">=") == TOKEN_MAIOR_IGUAL, "maior ou igual");
TESTE_ASSERT(resultado_testes, tokenDe("=") == TOKEN_IGUAL, "igual");
TESTE_ASSERT(resultado_testes, tokenDe("<>") == TOKEN_DIFERENTE, "diferente");
TESTE_ASSERT(resultado_testes, tokenDe("+") == TOKEN_MAIS, "mais");
TESTE_ASSERT(resultado_testes, tokenDe("-") == TOKEN_MENOS, "menos");
TESTE_ASSERT(resultado_testes, tokenDe("*") == TOKEN_MULTIPLICACAO, "multiplicacao");
TESTE_ASSERT(resultado_testes, tokenDe("/") == TOKEN_DIVISAO, "divisao de reais");
TESTE_ASSERT(resultado_testes, tokenDe(":=") == TOKEN_ATRIBUICAO, "atribuicao");
TESTE_ASSERT(resultado_testes, tokenDe("(") == TOKEN_ABRE_PARENTESES, "abre parenteses");
TESTE_ASSERT(resultado_testes, tokenDe(")") == TOKEN_FECHA_PARENTESES, "fecha parenteses");
TESTE_ASSERT(resultado_testes, tokenDe(",") == TOKEN_VIRGULA, "virgula");
TESTE_ASSERT(resultado_testes, tokenDe(";") == TOKEN_PONTO_VIRGULA, "ponto e virgula");
TESTE_ASSERT(resultado_testes, tokenDe(".") == TOKEN_PONTO, "ponto");
TESTE_ASSERT(resultado_testes, tokenDe(":") == TOKEN_DOIS_PONTOS, "dois pontos");
TESTE_ASSERT(resultado_testes, contaTokens(" \n\t\r ") == 1, "brancos ignorados resultam em EOF");
TESTE_ASSERT(resultado_testes, contaTokens("a b") == 3, "conta tokens simples");
TESTE_ASSERT(resultado_testes, tokenDe("$") == TOKEN_ERRO, "caractere invalido gera erro");
TESTE_ASSERT(resultado_testes, tokenDe("@") == TOKEN_ERRO, "arroba gera erro");
}
+27
View File
@@ -0,0 +1,27 @@
#include "micropascal-tests/testes.h"
#include <stdio.h>
int main(void)
{
ResultadoTeste resultado_testes;
resultado_testes.total = 0;
resultado_testes.passaram = 0;
resultado_testes.falharam = 0;
printf("Executando testes do lexer\n");
runLexerTests(&resultado_testes);
printf("Executando testes do parser\n");
runParserTests(&resultado_testes);
printf("\nTotal: %d | Passaram: %d | Falharam: %d\n",
resultado_testes.total,
resultado_testes.passaram,
resultado_testes.falharam);
if (resultado_testes.falharam > 0) {
return 1;
}
return 0;
}
+111
View File
@@ -0,0 +1,111 @@
#include "micropascal-tests/testes.h"
#include "micropascal-lexer/lexer.h"
#include "micropascal-parser/parser.h"
#include <string.h>
static int programaValido(const char* fonte)
{
Lexer lexer;
Parser parser;
AstNo* programa;
int valido;
lexerInicializar(&lexer, fonte);
parserInicializar(&parser, &lexer);
parserSilenciarErros(&parser, 1);
programa = parserAnalisarPrograma(&parser);
valido = !parser.houve_erro;
tokenLiberar(&parser.atual);
astLiberar(programa);
return valido;
}
static const char* PROGRAMA_SIMPLES =
"program P;\n"
"var\n"
" x : integer;\n"
"begin\n"
" x := 1;\n"
"end.\n";
static const char* PROGRAMA_PARIDADE =
"program TestaParidade;\n"
"var\n"
" n : integer;\n"
"begin\n"
" n := 2 * 13 + 5;\n"
" if n = (n div 2)*2 then\n"
" write('p')\n"
" ;\n"
" else\n"
" write('i')\n"
" ;\n"
"end.\n";
static const char* PROGRAMA_IMPARES =
"program SomaImpares;\n"
"var\n"
" n : integer;\n"
" i, proximoImpar, soma : integer;\n"
"begin\n"
" n := 4;\n"
" i := 0;\n"
" soma := 0;\n"
" while i < n do\n"
" begin\n"
" proximoImpar := 2*i + 1;\n"
" soma := soma + proximoImpar;\n"
" i := i + 1;\n"
" end;\n"
" write(soma);\n"
" write('\\n');\n"
"end.\n";
static const char* PROGRAMA_REPEAT =
"program Contador;\n"
"var\n"
" i : integer;\n"
"begin\n"
" i := 0;\n"
" repeat\n"
" i := i + 1;\n"
" until i >= 10;\n"
"end.\n";
static const char* PROGRAMA_TIPOS =
"program Tipos;\n"
"var\n"
" a, b : integer;\n"
" c : real;\n"
" d : char;\n"
"begin\n"
" a := 1;\n"
" b := 2;\n"
" c := 1.5 + 2.5;\n"
" d := 'x';\n"
"end.\n";
void runParserTests(ResultadoTeste* resultado_testes)
{
TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_SIMPLES), "programa simples valido");
TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_PARIDADE), "programa TestaParidade valido");
TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_IMPARES), "programa SomaImpares valido");
TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_REPEAT), "programa com repeat until valido");
TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_TIPOS), "programa com varios tipos valido");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := 1 + 2 * 3;\nend.\n"), "precedencia multiplicacao sobre soma");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := (1 + 2) * 3;\nend.\n"), "parenteses");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := not a and b or c;\nend.\n"), "operadores not and or");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a = b;\nend.\n"), "igualdade");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a <> b;\nend.\n"), "diferente");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a <= b;\nend.\n"), "menor ou igual");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n if a then b := 1;\nend.\n"), "decisao sem else");
TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n while a do b := 1;\nend.\n"), "iteracao while");
TESTE_ASSERT(resultado_testes, !programaValido("program P\nbegin end.\n"), "falta ponto e virgula apos nome");
TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := ;\nend.\n"), "expressao ausente");
TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := 1 +\nend.\n"), "operando ausente");
TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n if a then\nend.\n"), "comando ausente apos then");
TESTE_ASSERT(resultado_testes, !programaValido("program P;\nvar x integer;\nbegin end.\n"), "falta dois pontos na declaracao");
TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := 1\nend.\n"), "falta ponto e virgula no comando");
}