private Simbolo PreencheAtributos(Simbolo s, int cod_erro) { if (cod_erro >= 0) //Caso ocorra um erro, as seguintes informações são solicitadas { string _descricaoERRO = ""; TiposErros.TryGetValue(cod_erro, out _descricaoERRO); s.DescricaoERRO = _descricaoERRO; s.Coluna = _coluna; s.Linha = _linha; return(s); } switch (s.Token) { case "num": if (s.Lexema.Contains(".")) { s.Tipo = "double"; } else { s.Tipo = "int"; } break; case "lit": s.Tipo = "literal"; break; case "opm": s.Tipo = s.Lexema; break; case "rcb": s.Tipo = "="; break; case "opr": s.Tipo = s.Lexema; break; } s.Coluna = _coluna; s.Linha = _linha; return(s); }
public Simbolo AssociaRegraSemantica(int numProducao, List <Simbolo> tabDeSimbolos, out bool _houveErro) { Simbolo s = new Simbolo(); Simbolo simboloNaoterminal = new Simbolo(); StreamWriter x = File.AppendText(_caminhoNome); Simbolo tipo; Simbolo arg; Simbolo oprd; Simbolo ld; _houveErro = false; var tabelaDeSimbolos = tabDeSimbolos; switch (numProducao) { case 5: int i = 0; while (i++ < 3) { x.WriteLine(""); } break; case 6: _pilhaSemantica.Pop(); s.Tipo = _pilhaSemantica.Pop().Tipo; Simbolo simboloTopo = _pilhaSemantica.Peek(); simboloTopo.Tipo = s.Tipo; x.WriteLine($"{simboloTopo.Tipo} {simboloTopo.Lexema};"); break; case 7: s = _pilhaSemantica.Pop(); tipo = new Simbolo("TIPO", "TIPO", s.Tipo); _pilhaSemantica.Push(tipo); break; case 8: s = _pilhaSemantica.Pop(); tipo = new Simbolo("TIPO", "TIPO", s.Tipo); _pilhaSemantica.Push(tipo); break; case 9: s = _pilhaSemantica.Pop(); tipo = new Simbolo("TIPO", "TIPO", s.Tipo); _pilhaSemantica.Push(tipo); break; case 11: _pilhaSemantica.Pop(); s = _pilhaSemantica.Peek(); if (s.Tipo != null) { switch (s.Tipo) { case "literal": x.WriteLine($"scanf(\"%s\",{s.Lexema});"); break; case "int": x.WriteLine($"scanf(\"%d\",&{s.Lexema});"); break; case "double": x.WriteLine($"scanf(\"%lf\",&{s.Lexema});"); break; } } else { _houveErro = true; s.DescricaoERRO = "Variável não declarada."; } break; case 12: _pilhaSemantica.Pop(); arg = _pilhaSemantica.Peek(); switch (arg.Token) { case "literal": x.WriteLine($"printf({arg.Lexema});"); break; case "id": switch (arg.Tipo) { case "int": x.WriteLine($"printf(\"%d\",{arg.Lexema});"); break; case "literal": x.WriteLine($"printf(\"%s\",{arg.Lexema});"); break; case "double": x.WriteLine($"printf(\"%lf\",{arg.Lexema});"); break; } break; } break; case 13: s = _pilhaSemantica.Pop(); arg = s.CopiaAtributos(); _pilhaSemantica.Push(arg); break; case 14: s = _pilhaSemantica.Pop(); arg = s.CopiaAtributos(); _pilhaSemantica.Push(arg); break; case 15: s = _pilhaSemantica.Peek(); if (s.Tipo != null) { arg = s.CopiaAtributos(); _pilhaSemantica.Push(arg); } else { _houveErro = true; s.DescricaoERRO = "Variável não declarada."; } break; case 17: _pilhaSemantica.Pop(); Simbolo num = _pilhaSemantica.Pop(); Simbolo rcb = _pilhaSemantica.Pop(); Simbolo id = _pilhaSemantica.Pop(); if (id.Tipo != null) { if (num.Tipo == id.Tipo) { x.WriteLine($"{id.Lexema} {rcb.Tipo} {num.Lexema};"); } else { _houveErro = true; s = id.CopiaAtributos(); s.DescricaoERRO = "Tipos diferentes para atribuição."; } } else { _houveErro = true; s = id.CopiaAtributos(); s.DescricaoERRO = "Variável não declarada."; } break; case 18: Simbolo oprd1 = _pilhaSemantica.Pop(); Simbolo opm = _pilhaSemantica.Pop(); Simbolo oprd2 = _pilhaSemantica.Pop(); if (oprd1.Tipo == oprd2.Tipo) { var temp = new VariavelTemporaria($"T{countTemp}", oprd1.Tipo.ToString()); _listaTemporarios.Add(temp); Simbolo LD = new Simbolo($"T{countTemp++}", "LD", oprd1.Tipo); _pilhaSemantica.Push(LD); x.WriteLine($"{LD.Lexema} = {oprd2.Lexema} {opm.Tipo} {oprd1.Lexema};"); } else { _houveErro = true; s = oprd1.CopiaAtributos(); s.DescricaoERRO = "Operandos com tipos incompatíveis."; } break; case 19: s = _pilhaSemantica.Pop(); ld = s.CopiaAtributos(); _pilhaSemantica.Push(ld); break; case 20: s = _pilhaSemantica.Peek(); if (s.Tipo != null) { s = _pilhaSemantica.Pop(); oprd = s.CopiaAtributos(); _pilhaSemantica.Push(oprd); } else { _houveErro = true; s.DescricaoERRO = "Variável não declarada."; } break; case 21: s = _pilhaSemantica.Pop(); oprd = s.CopiaAtributos(); _pilhaSemantica.Push(oprd); break; case 23: x.WriteLine("}"); break; case 24: _pilhaSemantica.Pop(); _pilhaSemantica.Pop(); s = _pilhaSemantica.Pop(); x.WriteLine($"if({s.Lexema}){{"); break; case 25: Simbolo oprnd1 = _pilhaSemantica.Pop(); Simbolo opr = _pilhaSemantica.Pop(); Simbolo oprnd2 = _pilhaSemantica.Pop(); if (oprnd1.Tipo == oprnd2.Tipo) { var temp = new VariavelTemporaria($"T{countTemp}", oprnd1.Tipo.ToString()); _listaTemporarios.Add(temp); Simbolo exp_r = new Simbolo($"T{countTemp++}", "tx", "tx"); x.WriteLine($"{exp_r.Lexema} = {oprnd2.Lexema} {opr.Tipo} {oprnd1.Lexema};"); _pilhaSemantica.Push(exp_r); } else { _houveErro = true; s = oprnd1.CopiaAtributos(); s.DescricaoERRO = "Operandos com tipos incompatíveis."; } break; } x.Close(); return(s); }
public void AnaliseSintatica() { AnalisadorLexico analisadorLexico = new AnalisadorLexico(_codigoFonte); //aqui é onde ele inicializa o analisador léxico AnalisadorSemantico analisadorSemantico = new AnalisadorSemantico(); _pilha.Push(0); // Empilha o estado inicial na pilha int estado = 0; string acao = ""; string guardaToken = ""; Simbolo simbolo = analisadorLexico.RetornaToken(); Stack <Simbolo> pilhaDeSimbolos = new Stack <Simbolo>(); List <Simbolo> TabelaDeSimbolos = analisadorLexico.GetTabelaDeSimbolos(); while (true) // Início do procedimento de Shift - Reduce { //enquanto ele não aceitar ou dar erro ele não para a execução if (simbolo.Token != "ERRO") //CASO NÃO SEJA RETORNADO UM ERRO DO ANALISADOR LÉXICO { acao = _tabelaShiftReduce.Rows[estado][$"{simbolo.Token}"].ToString(); //captura a ação da tabela shift-reduce de acordo com o estado e com o simbolo if (acao.Contains("S")) //EMPILHA { estado = Convert.ToInt32(acao.Substring(1)); _pilha.Push(estado); analisadorSemantico._pilhaSemantica.Push(simbolo); if (pilhaDeSimbolos.Count == 0) { simbolo = analisadorLexico.RetornaToken(); //atualiza o simbolo com o token retornado do léxico } else { simbolo.Token = guardaToken; //atualiza o token após o tratamento do erro simbolo = pilhaDeSimbolos.Pop(); //atualiza com o simbolo da pilha } } else { if (acao.Contains("R")) // REDUZ { int numProducao = Convert.ToInt32(acao.Substring(1)); //captura o numero da produção se for S32 PEGA SO O 32; var producao = new string[2]; _producoes.TryGetValue(numProducao, out producao); //Atualiza a produção De acordo com o número da ação; var Simbolos = producao[1].Split(' '); int numSimbolos = Simbolos.Count(); //DESEMPILHA QUANTIDADE DE SÍMBOLOS LADO DIREITO for (int i = 0; i < numSimbolos; i++) { _pilha.Pop(); } //EMPILHAR O VALOR DE [t,A] na pilha estado = Convert.ToInt32(_tabelaShiftReduce.Rows[Convert.ToInt32(_pilha.Peek())][producao[0].ToString()]); //pula para o estado seguinte _pilha.Push(estado); Console.WriteLine($"{producao[0]} -> {producao[1]}"); if (_houveErro == false) { TabelaDeSimbolos = analisadorLexico.GetTabelaDeSimbolos(); var simboloComErro = analisadorSemantico.AssociaRegraSemantica(numProducao, TabelaDeSimbolos, out _houveErro); if (_houveErro) { PrintErro(simboloComErro.DescricaoERRO, simboloComErro); } } else { analisadorSemantico.DeletaArquivoObj(); } } else { if (acao.Contains("ACC")) // ACEITA { Console.WriteLine("P' -> P"); if (_houveErro == false) { analisadorSemantico.FinalizaArquivoObj(); } Console.ReadLine(); break; } else //EM CASO DE ERRO SINTÁTICO { if (Convert.ToInt32(acao.Substring(1)) < 16) //CASO O ERRO SEJA TRATÁVEL { Simbolo s = CopiaSimbolo(simbolo); pilhaDeSimbolos.Push(s); //cria uma nova pilha para guardar os tokens já lidos var tipoDeErro = Erro(acao, s); guardaToken = simbolo.Token; //guarda o token do simbolo atual para atualizar depois do tratamento de erro simbolo.Token = tipoDeErro[1].ToString(); //Rotina de erro } else //SE O ERRO NÃO FOR TRATÁVEL A COMPILAÇÃO É PAUSADA { Erro(acao, simbolo); Console.ReadLine(); break; } } } } } else//EM CASO DE ERRO LÉXICO { PrintErro(simbolo.DescricaoERRO, simbolo); //Escreve o erro na tela simbolo = analisadorLexico.RetornaToken(); //Busca o próximo token } } }
public Simbolo AnaliseLexica(string codigoFonte) // Percorre ocodigo fonte do Mgol { _proxEstado = "q0"; // a cada inicialização ele deve começar do estado incial _estadoAnterior = "q0"; _lexema = ""; // lexema vazio _linhaDoEstado = 0; _colunaDaEntrada = 0; _tipo_de_erro = -1; while (_ponteiro != codigoFonte.Length) // percorre o ponteiro enquanto ele não chegar no final do codigo fonte { //_ponteiro -> do codigo fonte _caracterAtual = codigoFonte[_ponteiro]; ModificaLinhaColuna(); // Contador que atualiza o valor da linha e da coluna if (!SimbolosValidos.ContainsKey(_caracterAtual.ToString())) //verifica se o caractere atual é valido { // se não for caractere válido retorna o erro _tipo_de_erro = 0; _proxEstado = "ERRO"; } _estadoAnterior = _proxEstado; //armazena o estado anterior para o proximo estado ser modificado TodosEstados.TryGetValue(_proxEstado, out _linhaDoEstado); SimbolosValidos.TryGetValue(_caracterAtual.ToString(), out _colunaDaEntrada); //Modifica o valor da coluna de acordo com o caractere if (_estadoAnterior == "num" && (_caracterAtual == 'E' || _caracterAtual == 'e')) { _colunaDaEntrada = 9; } _proxEstado = Convert.ToString(TabelaDeTransicao[_linhaDoEstado][_colunaDaEntrada]); if (EstadosFinais.ContainsKey(_estadoAnterior) && _proxEstado == "") { if (_estadoAnterior == "qG") { _estadoAnterior = "opr"; } //VERIFICA SE TEM ESSE LEXEMA NA LISTA DE SIMBOLOS Simbolo s = TabelaDeSimbolos.Find(o => o.Lexema == _lexema); if (s == null) // s-> simbolo do codigo fonte { s = new Simbolo() { Lexema = _lexema, Token = _estadoAnterior, Tipo = null }; if (_estadoAnterior.Equals("id")) { TabelaDeSimbolos.Add(s); // lista de identificadores } s = PreencheAtributos(s, _tipo_de_erro); //Verifica se ocorreu algum erro de caracter inválido durante a leitura return(s); } else { s = PreencheAtributos(s, _tipo_de_erro);//Verifica se ocorreu algum erro de caracter inválido durante a leitura return(s); } } if (!char.IsWhiteSpace(_caracterAtual) || _proxEstado == "qA") // Verifica se o caractere atual é espaço em branco ou se o proximo estado é qA { if (_caracterAtual == '\r') //Converte o \r para ' ' { _caracterAtual = ' '; } _lexema += _caracterAtual; } _ponteiro++; continue; // Continua o laço de análise } Simbolo simb = TabelaDeSimbolos.Find(o => o.Lexema == _lexema); // verifica se o lexema formado está na tabela de simbolo if (simb == null) // verifica se chegou no final da leitura do arquivo { simb = new Simbolo { Token = "$" }; _linha++; PreencheAtributos(simb, _tipo_de_erro); } return(simb); }
private static Dictionary <string, Simbolo> Palavras_Chave() { Dictionary <string, Simbolo> TabelaDeSimbolos = new Dictionary <string, Simbolo>(); //palavras chave da linguagem MGOL var inicio = new Simbolo() { Lexema = "inicio", Token = "inicio", Tipo = null }; var varinicio = new Simbolo() { Lexema = "varinicio", Token = "varinicio", Tipo = null }; var varfim = new Simbolo() { Lexema = "varfim", Token = "varfim", Tipo = null }; var escreva = new Simbolo() { Lexema = "escreva", Token = "escreva", Tipo = null }; var leia = new Simbolo() { Lexema = "leia", Token = "leia", Tipo = null }; var se = new Simbolo() { Lexema = "se", Token = "se", Tipo = null }; var entao = new Simbolo() { Lexema = "entao", Token = "entao", Tipo = null }; var fimse = new Simbolo() { Lexema = "fimse", Token = "fimse", Tipo = null }; var fim = new Simbolo() { Lexema = "fim", Token = "fim", Tipo = null }; var inteiro = new Simbolo() { Lexema = "inteiro", Token = "inteiro", Tipo = "int" }; var lit = new Simbolo() { Lexema = "lit", Token = "lit", Tipo = "literal" }; var real = new Simbolo() { Lexema = "real", Token = "real", Tipo = "double" }; TabelaDeSimbolos.Add(inicio.Lexema, inicio); TabelaDeSimbolos.Add(varinicio.Lexema, varinicio); TabelaDeSimbolos.Add(varfim.Lexema, varfim); TabelaDeSimbolos.Add(escreva.Lexema, escreva); TabelaDeSimbolos.Add(leia.Lexema, leia); TabelaDeSimbolos.Add(se.Lexema, se); TabelaDeSimbolos.Add(entao.Lexema, entao); TabelaDeSimbolos.Add(fimse.Lexema, fimse); TabelaDeSimbolos.Add(fim.Lexema, fim); TabelaDeSimbolos.Add(inteiro.Lexema, inteiro); TabelaDeSimbolos.Add(lit.Lexema, lit); TabelaDeSimbolos.Add(real.Lexema, real); return(TabelaDeSimbolos); }