diff --git a/src/main/scala/Tudo.scala b/src/main/scala/Tudo.scala new file mode 100644 index 0000000000000000000000000000000000000000..77e804dc1e87ef00fd7f4d3f2429ab5731ca2c7c --- /dev/null +++ b/src/main/scala/Tudo.scala @@ -0,0 +1,256 @@ +package other + +import scala.annotation.tailrec + +object Tudo { + import collection.mutable.ListBuffer + val MEPA = ListBuffer[String]() + + object rotulos { + private var num = 0 + def -- = num-=1 + def geraRotulo = { + num += 1 + "R"+ (if (num<10) "00"+num else if (num<100) "0"+num else num) + } + } + + def insereIntVars(vars: List[String], nivelLexico: Int) = { + val orgSize = vars.size + var desloc = 0 + if (orgSize == vars.distinct.size) { + TabelaSimb insere vars.map { id => + val v = Var(id, desloc, nivelLexico); desloc += 1; v + } + MEPA += "AMEM " + orgSize + } else { + println("Erro: declaração de variáveis: identificadores já declarados: "+vars.diff(vars.distinct).mkString(" ")) + } + } + + def chamaId(id: String, nvLexAtual:Int):Unit = { + + TabelaSimb.getById(id) match { + case Some(it) => it match { + case v:Var => + if (MyParser.eh_param) { + val isByRef = MyParser.procStack.top match { + case p:Procedimento => p.paramInfo(MyParser.paramCounter.get).byRef + case f:Funcao => f.paramInfo(MyParser.paramCounter.get).byRef + } + if (isByRef) + aplica("CREN "+v.nvLex+","+v.desloc) + else + aplica("CRVL "+v.nvLex+","+v.desloc) + } else + aplica("CRVL "+v.nvLex+","+v.desloc) + case p:Param => + if (MyParser.eh_param) { + val isByRef = MyParser.procStack.top match { + case p:Procedimento => p.paramInfo(MyParser.paramCounter.get).byRef + case f:Funcao => f.paramInfo(MyParser.paramCounter.get).byRef + } + if (isByRef) + if (p.byRef) aplica("CRVL "+p.nvLex+","+p.desloc) else aplica("CREN "+p.nvLex+","+p.desloc) + else + if (p.byRef) aplica("CRVI "+p.nvLex+","+p.desloc) else aplica("CRVL "+p.nvLex+","+p.desloc) + } else + if (p.byRef) aplica("CRVI "+p.nvLex+","+p.desloc) else aplica("CRVL "+p.nvLex+","+p.desloc) + + case p:Procedimento => aplica("CHPR "+p.rotEntrada+","+nvLexAtual) + + case f:Funcao => aplica("CHPR "+f.rotEntrada+","+nvLexAtual) + case other => + println("Erro(1): Identificador Inválido: "+ id) + sys.exit(1) + } + case None => + if(id!="read" && id!="write") { + println("Erro(2): Identificador Inválido: "+ id); + sys.exit(1) + } else id match { + case "read" => aplica("LEIT") + case "write" => aplica("IMPR") + } + } + } + + + object proc { + + val RotStack = collection.mutable.Stack[String]() + + + //DRY! + def entraProcFun(nivelLexico: Int) = { + val rotulo = rotulos.geraRotulo //rotuloEntrada + val rotuloBegin = rotulos.geraRotulo + RotStack.push(rotuloBegin) //Begin + if (nivelLexico>1) { + val rotDesvio = TabelaSimb.getLastProc(nivelLexico-1) match { + case p:Procedimento => p.rotEntrada + case f:Funcao => f.rotEntrada + case o => println("====> "+o) + } + } + aplica(rotulo+": ENPR "+nivelLexico) + rotulo + } + + def entraProc(id:String, params:Option[ List[(Option[String],List[String])] ], nivelLexico:Int): Unit = { + val rotulo = entraProcFun(nivelLexico) + + params match { + case Some( lstParams ) if ! lstParams.isEmpty => + val ps = retornaParamsLst(lstParams, nivelLexico) + TabelaSimb.insere( Procedimento(id, ps, nivelLexico, rotulo) ) + ps.foreach { TabelaSimb.insere } + case None => + TabelaSimb.insere( Procedimento(id, List.empty, nivelLexico, rotulo) ) + } + } + + def entraFunc(id:String, params:Option[ List[(Option[String],List[String])] ], nivelLexico:Int):Unit = { + val rotulo = entraProcFun(nivelLexico) + + params match { + case Some( lstParams ) if ! lstParams.isEmpty => + val ps = retornaParamsLst(lstParams, nivelLexico) + val desloc = -4-ps.size + TabelaSimb.insere( Funcao(id,ps,desloc,nivelLexico,rotulo) ) + ps.foreach { TabelaSimb.insere } + case None => + TabelaSimb.insere( Funcao(id, null, -4, nivelLexico,rotulo) ) + } + } + + def retornaParamsLst(params:List[(Option[String],List[String])], nivelLexico:Int):List[Param] = { + var desloc = -3 - params.map(_._2.size).sum + params.flatMap { + case (varOpt, idlst) => + idlst map { id => + val p = Param(id,desloc,varOpt.isDefined,nivelLexico) + desloc +=1 + p + } + } + } + + @tailrec def contaVariaveis(nvLex:Int, count:Int = 0):Int = TabelaSimb.hasNext match { + case true => TabelaSimb.top match { + case v:Var => TabelaSimb.drop; contaVariaveis(nvLex,count+1) + case p:Procedimento => if (p.nvLex>nvLex) {TabelaSimb.drop; contaVariaveis(nvLex,count)} else count + case f:Funcao => if (f.nvLex>nvLex) {TabelaSimb.drop; contaVariaveis(nvLex,count)} else count + case r:Label => + if (! r.used) {println("Warning: rótulo nunca usado: "+ r.id)} + TabelaSimb.drop + contaVariaveis(nvLex,count) + case _ => count + } + case false => count + } + + def saiProcFunc(nivelLexico:Int) { + + val numVariaveis = contaVariaveis(nivelLexico) + if (numVariaveis>0) + aplica("DMEM "+numVariaveis) + + val table = TabelaSimb.getTable + TabelaSimb.setTable( + table.dropWhile { + case p:Procedimento => if (p.nvLex>nivelLexico) true else false + case f:Funcao => if (f.nvLex>nivelLexico) true else false + case r:Label => + if (r.used) { //Se rótulo nunca usado + println("Warning: rótulo nunca usado: "+ r.id) + //sys.exit(1) + } + true + case _ => true + } + ) + + TabelaSimb.top match { + case p:Procedimento => aplica("RTPR "+ p.nvLex +","+p.paramInfo.size) + case f:Funcao => aplica("RTPR "+ f.nvLex+","+f.paramInfo.size ) + case e => println(e); println("Nao eh instancia proc nem func-> ERRO"); sys.exit(2) + } + } + } + + //ROTULOS + def insereRotulos(lstRot: List[String], nivelLexico: Int) = { + lstRot.foreach { + id => TabelaSimb insere ( Label(id,rotulos.geraRotulo,nivelLexico) ) + } + } + + def entraRotulo(rotuloLogico:String,nvLex:Int) { + val rot = TabelaSimb.getById(rotuloLogico) + rot match { + case Some(e) => e match { + case r:Label => + if (r.put) { + println("Erro: Rotulo "+r.id+" posto mais de uma vez!") + sys.exit(1) + } else { + r.put = true + //r.used = true goto should do that + aplica(r.rotulo+": ENRT "+nvLex+","+TabelaSimb.numVarsLocais(nvLex)) + } + case _ => println("Erro: Rótulo "+rotuloLogico+" não declarado!"); sys.exit(1) + } + case None => println("Erro: Rótulo "+rotuloLogico+" não declarado!"); sys.exit(1) + } + } + + def iniciaPrograma { + aplica("INPP") + } + + def encerraPrograma = { + val countVars = proc.contaVariaveis(0) + if (countVars>0) { aplica("DMEM "+countVars) } + aplica("PARA") + } + + def atribuicao(id: String) = { + val e = TabelaSimb.getById(id) + e match { + case Some(e) => e match { + case f:Funcao => aplica("ARMZ "+f.nvLex+","+f.desloc) + case v:Var => aplica("ARMZ "+v.nvLex+","+v.desloc) + case p:Param => + if (p.byRef) aplica("ARMI "+p.nvLex+","+p.desloc) else aplica("ARMZ "+p.nvLex+","+p.desloc) + case other => println("Atribuição a "+id+" é inválida!"); sys.exit(1) + } + case None => println("identificador inválido: "+id); sys.exit(1) + } + } + + def literal(num: Int) = { + aplica("CRCT "+num) + } + + def aplica(cmdMEPA: String) { + MEPA += cmdMEPA + } + + def gotoRotulo(rot: String, nivelLexico: Int) { + val r = TabelaSimb.getById(rot) + r match { + case Some(s) => s match { + case r:Label => + r.used = true + aplica("DSVR "+r.rotulo+","+r.nvLex+","+nivelLexico) + case _ => println("goto para rótulo não declarado! (goto "+rot+")"); sys.exit(1) + } + case None => println("goto para rótulo não declarado! (goto "+rot+")"); sys.exit(1) + } + } + + def reservadas = List("program", "label", "var", "procedure", "function","begin","end", + "if", "then", "else", "while", "do", "or", "and","div","not") + +} \ No newline at end of file