#include "micropascal-parser/parser.h" #include #include #include static AstNo* parserCriarNo(AstKind kind, const char* valor) { AstNo* no = (AstNo*)malloc(sizeof(AstNo)); no->kind = kind; if (valor != NULL) { no->valor = (char*)malloc(strlen(valor) + 1); strcpy(no->valor, valor); } else { no->valor = NULL; } no->esquerda = NULL; no->direita = NULL; no->terceiro = NULL; no->proximo = NULL; return no; } static void parserAvancar(Parser* parser) { tokenLiberar(&parser->atual); parser->atual = lexerProximoToken(parser->lexer); } void parserInicializar(Parser* parser, Lexer* lexer) { parser->lexer = lexer; parser->atual.kind = TOKEN_EOF; parser->atual.lexema = NULL; parser->atual.linha = 0; parser->atual.coluna = 0; parser->houve_erro = 0; parser->total_erros = 0; parser->silencioso = 0; parserAvancar(parser); } void parserSilenciarErros(Parser* parser, int silenciar) { parser->silencioso = silenciar; } static void parserErro(Parser* parser) { const char* lexema = parser->atual.lexema; if (lexema == NULL) { lexema = ""; } parser->houve_erro = 1; parser->total_erros++; if (!parser->silencioso) { printf("Erro de sintaxe no token [%s]\n", lexema); } } static int parserVerificar(Parser* parser, TokenKind kind) { return parser->atual.kind == kind; } static int parserConsumir(Parser* parser, TokenKind kind) { if (parserVerificar(parser, kind)) { parserAvancar(parser); return 1; } return 0; } static int parserEsperar(Parser* parser, TokenKind kind) { if (parserConsumir(parser, kind)) { return 1; } parserErro(parser); return 0; } static int parserEmInicioDeComando(Parser* parser) { switch (parser->atual.kind) { case TOKEN_BEGIN: case TOKEN_IDENTIFICADOR: case TOKEN_WHILE: case TOKEN_REPEAT: case TOKEN_IF: case TOKEN_WRITE: return 1; default: return 0; } } static AstNo* parserAnalisarBloco(Parser* parser); static AstNo* parserAnalisarComando(Parser* parser); static AstNo* parserAnalisarExpressao(Parser* parser); static AstNo* parserAnalisarTipo(Parser* parser) { switch (parser->atual.kind) { case TOKEN_INTEGER: parserAvancar(parser); return parserCriarNo(AST_TIPO, "integer"); case TOKEN_REAL: parserAvancar(parser); return parserCriarNo(AST_TIPO, "real"); case TOKEN_CHAR: parserAvancar(parser); return parserCriarNo(AST_TIPO, "char"); default: parserErro(parser); return NULL; } } static AstNo* parserAnalisarDeclVar(Parser* parser) { AstNo* decl = parserCriarNo(AST_DECL_VAR, NULL); AstNo* ultimo = NULL; AstNo* identificador; AstNo* tipo; if (!parserEsperar(parser, TOKEN_IDENTIFICADOR)) { astLiberar(decl); return NULL; } identificador = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, NULL); decl->esquerda = identificador; ultimo = identificador; while (parserVerificar(parser, TOKEN_VIRGULA)) { parserAvancar(parser); if (!parserEsperar(parser, TOKEN_IDENTIFICADOR)) { return decl; } ultimo->proximo = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, NULL); ultimo = ultimo->proximo; } if (!parserEsperar(parser, TOKEN_DOIS_PONTOS)) { return decl; } tipo = parserAnalisarTipo(parser); decl->direita = tipo; if (!parserEsperar(parser, TOKEN_PONTO_VIRGULA)) { return decl; } return decl; } static AstNo* parserAnalisarSecaoVar(Parser* parser) { AstNo* secao = parserCriarNo(AST_SECAO_VAR, NULL); AstNo* ultimo = NULL; if (!parserEsperar(parser, TOKEN_VAR)) { astLiberar(secao); return NULL; } while (parserVerificar(parser, TOKEN_IDENTIFICADOR)) { AstNo* decl = parserAnalisarDeclVar(parser); if (decl == NULL) { break; } if (ultimo == NULL) { secao->esquerda = decl; } else { ultimo->proximo = decl; } ultimo = decl; } return secao; } static AstNo* parserAnalisarExprBasica(Parser* parser) { AstNo* no; switch (parser->atual.kind) { case TOKEN_ABRE_PARENTESES: parserAvancar(parser); no = parserCriarNo(AST_EXPRESSAO_PARENTESES, NULL); no->esquerda = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_FECHA_PARENTESES); return no; case TOKEN_NOT: parserAvancar(parser); no = parserCriarNo(AST_EXPRESSAO_UNARIA, "not"); no->esquerda = parserAnalisarExprBasica(parser); return no; case TOKEN_INTEIRO_LITERAL: no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); parserAvancar(parser); return no; case TOKEN_REAL_LITERAL: no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); parserAvancar(parser); return no; case TOKEN_CHAR_LITERAL: no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); parserAvancar(parser); return no; case TOKEN_IDENTIFICADOR: no = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, parser->atual.lexema); parserAvancar(parser); return no; default: parserErro(parser); return NULL; } } static AstNo* parserAnalisarExpMul(Parser* parser) { AstNo* esquerda = parserAnalisarExprBasica(parser); while (parser->atual.kind == TOKEN_MULTIPLICACAO || parser->atual.kind == TOKEN_DIVISAO || parser->atual.kind == TOKEN_DIV) { char operador[8]; AstNo* direita; AstNo* novo; strcpy(operador, parser->atual.lexema); parserAvancar(parser); direita = parserAnalisarExprBasica(parser); novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); novo->esquerda = esquerda; novo->direita = direita; esquerda = novo; } return esquerda; } static AstNo* parserAnalisarExpAd(Parser* parser) { AstNo* esquerda = parserAnalisarExpMul(parser); while (parser->atual.kind == TOKEN_MAIS || parser->atual.kind == TOKEN_MENOS) { char operador[8]; AstNo* direita; AstNo* novo; strcpy(operador, parser->atual.lexema); parserAvancar(parser); direita = parserAnalisarExpMul(parser); novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); novo->esquerda = esquerda; novo->direita = direita; esquerda = novo; } return esquerda; } static AstNo* parserAnalisarExpRel(Parser* parser) { AstNo* esquerda = parserAnalisarExpAd(parser); while (parser->atual.kind == TOKEN_IGUAL || parser->atual.kind == TOKEN_DIFERENTE || parser->atual.kind == TOKEN_MENOR || parser->atual.kind == TOKEN_MAIOR || parser->atual.kind == TOKEN_MENOR_IGUAL || parser->atual.kind == TOKEN_MAIOR_IGUAL) { char operador[8]; AstNo* direita; AstNo* novo; strcpy(operador, parser->atual.lexema); parserAvancar(parser); direita = parserAnalisarExpAd(parser); novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); novo->esquerda = esquerda; novo->direita = direita; esquerda = novo; } return esquerda; } static AstNo* parserAnalisarExpOrAnd(Parser* parser) { AstNo* esquerda = parserAnalisarExpRel(parser); while (parser->atual.kind == TOKEN_OR || parser->atual.kind == TOKEN_AND) { char operador[8]; AstNo* direita; AstNo* novo; strcpy(operador, parser->atual.lexema); parserAvancar(parser); direita = parserAnalisarExpRel(parser); novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); novo->esquerda = esquerda; novo->direita = direita; esquerda = novo; } return esquerda; } static AstNo* parserAnalisarExpressao(Parser* parser) { return parserAnalisarExpOrAnd(parser); } static AstNo* parserAnalisarAtribuicao(Parser* parser) { AstNo* no = parserCriarNo(AST_ATRIBUICAO, parser->atual.lexema); parserAvancar(parser); if (!parserEsperar(parser, TOKEN_ATRIBUICAO)) { return no; } no->esquerda = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_PONTO_VIRGULA); return no; } static AstNo* parserAnalisarIteracao(Parser* parser) { AstNo* no; if (parser->atual.kind == TOKEN_WHILE) { parserAvancar(parser); no = parserCriarNo(AST_ITERACAO, "while"); no->esquerda = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_DO); no->direita = parserAnalisarComando(parser); return no; } parserAvancar(parser); no = parserCriarNo(AST_ITERACAO, "repeat"); no->esquerda = parserAnalisarComando(parser); parserEsperar(parser, TOKEN_UNTIL); no->direita = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_PONTO_VIRGULA); return no; } static AstNo* parserAnalisarDecisao(Parser* parser) { AstNo* no; parserAvancar(parser); no = parserCriarNo(AST_DECISAO, NULL); no->esquerda = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_THEN); no->direita = parserAnalisarComando(parser); if (parserVerificar(parser, TOKEN_ELSE)) { parserAvancar(parser); no->terceiro = parserAnalisarComando(parser); } return no; } static AstNo* parserAnalisarEscrita(Parser* parser) { AstNo* no; parserAvancar(parser); no = parserCriarNo(AST_ESCRITA, NULL); parserEsperar(parser, TOKEN_ABRE_PARENTESES); no->esquerda = parserAnalisarExpressao(parser); parserEsperar(parser, TOKEN_FECHA_PARENTESES); parserEsperar(parser, TOKEN_PONTO_VIRGULA); return no; } static AstNo* parserAnalisarComando(Parser* parser) { switch (parser->atual.kind) { case TOKEN_BEGIN: { AstNo* bloco = parserAnalisarBloco(parser); parserEsperar(parser, TOKEN_PONTO_VIRGULA); return bloco; } case TOKEN_IDENTIFICADOR: return parserAnalisarAtribuicao(parser); case TOKEN_WHILE: case TOKEN_REPEAT: return parserAnalisarIteracao(parser); case TOKEN_IF: return parserAnalisarDecisao(parser); case TOKEN_WRITE: return parserAnalisarEscrita(parser); default: parserErro(parser); return NULL; } } static AstNo* parserAnalisarBloco(Parser* parser) { AstNo* bloco = parserCriarNo(AST_BLOCO, NULL); AstNo* lista = parserCriarNo(AST_LISTA_COMANDOS, NULL); AstNo* ultimo = NULL; if (!parserEsperar(parser, TOKEN_BEGIN)) { astLiberar(bloco); astLiberar(lista); return NULL; } while (parserEmInicioDeComando(parser)) { AstNo* comando = parserAnalisarComando(parser); if (comando == NULL) { break; } if (ultimo == NULL) { lista->esquerda = comando; } else { ultimo->proximo = comando; } ultimo = comando; } parserEsperar(parser, TOKEN_END); bloco->esquerda = lista; return bloco; } AstNo* parserAnalisarPrograma(Parser* parser) { AstNo* programa = parserCriarNo(AST_PROGRAMA, NULL); if (!parserEsperar(parser, TOKEN_PROGRAM)) { astLiberar(programa); return NULL; } if (parserVerificar(parser, TOKEN_IDENTIFICADOR)) { free(programa->valor); programa->valor = (char*)malloc(strlen(parser->atual.lexema) + 1); strcpy(programa->valor, parser->atual.lexema); parserAvancar(parser); } else { parserErro(parser); } parserEsperar(parser, TOKEN_PONTO_VIRGULA); if (parserVerificar(parser, TOKEN_VAR)) { programa->esquerda = parserAnalisarSecaoVar(parser); } programa->direita = parserAnalisarBloco(parser); parserEsperar(parser, TOKEN_PONTO); if (!parserVerificar(parser, TOKEN_EOF)) { parserErro(parser); } return programa; }