From 4dc0ee36d7cdf057c96a25bc02b55d7fc057173e Mon Sep 17 00:00:00 2001 From: ls12 5o Andar <ls12@inf.ufpr.br> Date: Wed, 17 Jun 2015 14:21:30 -0300 Subject: [PATCH] Add type support! (Tested) --- src/main/scala/other/Parser.scala | 41 ++++++++---- src/main/scala/other/TabelaSimb.scala | 11 ++++ src/main/scala/other/Tudo.scala | 89 +++++++++++++++++++-------- 3 files changed, 104 insertions(+), 37 deletions(-) diff --git a/src/main/scala/other/Parser.scala b/src/main/scala/other/Parser.scala index e108459..525cc6b 100644 --- a/src/main/scala/other/Parser.scala +++ b/src/main/scala/other/Parser.scala @@ -5,6 +5,9 @@ import sun.java2d.pipe.SpanShapeRenderer.Simple import other.Tudo.rotulos import com.sun.org.apache.xml.internal.serializer.ToStream.BoolStack +case class ids_t(ids:List[String], tipo: String) +case class dec_param(byRef:Boolean, ids:List[String], tipo:String) + class Arith extends JavaTokenParsers { //CONTROLE etc. val fazTudo = Tudo @@ -40,11 +43,19 @@ class Arith extends JavaTokenParsers { } def bloco:Parser[Any] = - (opt(dec_rotulos) ~ opt(dec_vars) ^^ + (opt(dec_rotulos) ~ + (opt(dec_tipos) ^^ { + case Some(tipos) => + //Add to table + TabelaSimb.insere(tipos.map{ t => Tipo(t) }) + case None => //fine + })~ + opt(dec_vars) ^^ { _ => if (nivelLexico==0) Tudo.aplica("DSVS R00"); else Tudo.aplica("DSVS "+Tudo.proc.RotStack.top) - nivelLexico+=1 } ) ~ + nivelLexico+=1 + }) ~ (opt(dec_subrotinas) ^^ { _ => nivelLexico-=1 @@ -63,25 +74,31 @@ class Arith extends JavaTokenParsers { //ROTULOS def dec_rotulos = "label".iso ~> """\d+""".r ~ rep("," ~> """\d+""".r) <~ ";" ^^ { case x~xs => fazTudo.insereRotulos(x::xs, nivelLexico) } + + //TIPOS + def dec_tipos = "type".iso ~> (def_tipo <~ ";") ~ rep(def_tipo <~ ";" ) ^^ { mkList } + + def def_tipo = ident <~ "=" ~ "integer" + + def tipo = ident //VARIAVEIS def dec_vars = "var".iso ~> dec_var ~ rep(";" ~> dec_var) <~ ";" ^^ - { case xs~xss => fazTudo.insereIntVars(xs ::: xss.flatten, nivelLexico) } - def dec_var = lista_ident <~ ":" ~ tipo + { case xss => fazTudo.insereIntVars(mkList(xss), nivelLexico) } + def dec_var = (lista_ident <~ ":") ~ tipo ^^ { case ids ~ t => ids_t(ids, t)} def lista_ident = ident ~ rep( "," ~> ident ) ^^ { mkList } - def tipo = "integer" //SUB-ROTINAS def dec_subrotinas = rep( (dec_proc | dec_func) <~ bloco ~ ";" ^^ { e => fazTudo.proc.saiProcFunc(nivelLexico); e} ) def dec_proc = "procedure".iso ~> ident ~ opt(params_formais) <~ ";" ^^ - { case id ~ lstOptIds => fazTudo.proc.entraProc(id, lstOptIds, nivelLexico) } - def dec_func = "function".iso ~> ident ~ opt(params_formais) <~ ":" ~ tipo ~ ";" ^^ - { case id ~ lstOptIds => fazTudo.proc.entraFunc(id, lstOptIds, nivelLexico) } + { case id ~ lstDecParam => fazTudo.proc.entraProc(id, lstDecParam, nivelLexico) } + def dec_func = "function".iso ~> ident ~ opt(params_formais) ~ (":" ~> tipo) <~ ";" ^^ + { case id ~ lstDecParam ~ tipo => fazTudo.proc.entraFunc(id, lstDecParam, nivelLexico, tipo) } - def params_formais = "(" ~> params ~ rep(";" ~> params) <~ ")" ^^ { s_xs => mkList(s_xs).map{case opt~id=>(opt,id)}} - def params = opt("var".iso) ~ lista_ident <~ ":" ~ tipo + def params_formais = "(" ~> params ~ rep(";" ~> params) <~ ")" ^^ { mkList } + def params = opt("var".iso) ~ lista_ident ~ (":" ~> tipo) ^^ { case v ~ ids ~ tipo => dec_param(v.isDefined, ids, tipo)} //COMANDOS def comando_composto:Parser[Any] = "begin".iso ~ comando ~ rep(";" ~ comando) ~ "end" @@ -389,15 +406,13 @@ object MyParser extends Arith { sys.exit(1) } val pascalSource = io.Source.fromFile(args(0)).getLines().mkString("\n") -// val pascalSource = ArqExemplos.p try println(parseAll(PascalParser.program, pascalSource)) catch { case e : Exception => println("Erro no programa"); sys.exit(1) } val mp = Tudo.MEPA -// mp foreach println val pw = new java.io.PrintWriter("MEPA") mp foreach pw.println - pw.close + pw.close } diff --git a/src/main/scala/other/TabelaSimb.scala b/src/main/scala/other/TabelaSimb.scala index 8946515..b71fb39 100644 --- a/src/main/scala/other/TabelaSimb.scala +++ b/src/main/scala/other/TabelaSimb.scala @@ -9,6 +9,7 @@ case class Procedimento(override val id:String, paramInfo:List[Param], case class Param(override val id:String, desloc: Int, byRef:Boolean, nvLex:Int, tipo:String = "integer") extends Entrada(id) case class Var(override val id:String, desloc: Int, nvLex:Int, tipo:String = "integer") extends Entrada(id) case class Label(override val id:String, rotulo:String, nvLex:Int, var used:Boolean = false, var put:Boolean = false) extends Entrada(id) +case class Tipo(override val id:String) extends Entrada(id) object TabelaSimb { @@ -45,6 +46,16 @@ object TabelaSimb { } } + def existeTipo(tipo:String):Boolean = { + if (tipo == "integer") return true + table.exists { e => e match { + case t:Tipo => + if (t.id == tipo) true + else false + case _ => false + }} + } + @tailrec def numVarsLocais(nvLex:Int, count:Int=0, rest:List[Entrada] = table):Int = rest match { case (v:Var) :: xs => numVarsLocais(nvLex, count+1, xs) diff --git a/src/main/scala/other/Tudo.scala b/src/main/scala/other/Tudo.scala index fc648f1..bcf6dda 100644 --- a/src/main/scala/other/Tudo.scala +++ b/src/main/scala/other/Tudo.scala @@ -15,25 +15,47 @@ object Tudo { num match { case dig if num<10 => "0"+dig case dezena if num<100 => ""+dezena - case bigger if num>=100 => "" + bigger + case maior if num>=100 => "" + maior } ) } } - def insereIntVars(vars: List[String], nivelLexico: Int) = { - val orgSize = vars.size + def insereIntVars(vars_t: List[ids_t], nivelLexico: Int) = { + + //Garante que os tipos existem + val lst_tipos = vars_t.map { case ids_t(_,t) => t } + val tipo_invalido = lst_tipos.distinct.find { t => ! TabelaSimb.existeTipo(t) } //Ache um que não existe + + tipo_invalido match { + case Some(invalido) => //Erro + println("Erro: Tipo não declarado na declaração de variáveis: "+invalido) + sys.exit(1) + case None => //Ok + } + //end + + //Garante nenhuma repetição de id + val listaIds = vars_t.map{ case ids_t(ids,_) => ids }.flatten + val totalAMEM = listaIds.size + + if (listaIds.distinct.size != listaIds.size) { + println("Erro: declaração de variáveis:") + println(" identificadores já declarados para parametros ou var: "+ + listaIds.diff(listaIds.distinct).mkString(" ")) + sys.exit(1) + } + //end + var desloc = 0 - if (orgSize == vars.distinct.size) { - TabelaSimb insere vars.map { id => - val v = Var(id, desloc, nivelLexico); desloc += 1; v - } - aplica("AMEM " + orgSize) - } else { - println("Erro: declaração de variáveis:") - println(" identificadores já declarados para parametros ou var: "+vars.diff(vars.distinct).mkString(" ")) - sys.exit(1) + vars_t.foreach { case ids_t(varsId,tipo) => + TabelaSimb insere varsId.map { id => + desloc += 1 + Var(id, desloc-1, nivelLexico,tipo) + } } + aplica("AMEM " +totalAMEM) + } def geraMepaDoId(id: String, nvLexAtual:Int): Unit = @@ -105,7 +127,7 @@ object Tudo { val rotulo = rotulos.geraRotulo //rotuloEntrada val rotuloBegin = rotulos.geraRotulo RotStack.push(rotuloBegin) //Begin - if (nivelLexico>1) { + if (nivelLexico>1) { val rotDesvio = TabelaSimb.getLastProc(nivelLexico-1) match { case p:Procedimento => p.rotEntrada case f:Funcao => f.rotEntrada @@ -116,10 +138,10 @@ object Tudo { rotulo } - def entraProc(id:String, params:Option[ List[(Option[String],List[String])] ], nivelLexico:Int): Unit = { + def entraProc(id:String, dec_ps: Option[List[dec_param]], nivelLexico:Int): Unit = { val rotulo = entraProcFun(nivelLexico) - params match { + dec_ps match { case Some( lstParams ) if ! lstParams.isEmpty => val ps = retornaParamsLst(lstParams, nivelLexico) TabelaSimb.insere( Procedimento(id, ps, nivelLexico, rotulo) ) @@ -135,14 +157,19 @@ object Tudo { } } - def entraFunc(id:String, params:Option[ List[(Option[String],List[String])] ], nivelLexico:Int):Unit = { + def entraFunc(id:String, dec_ps: Option[List[dec_param]],nivelLexico:Int, tipo:String):Unit = + { val rotulo = entraProcFun(nivelLexico) - - params match { + if ( ! TabelaSimb.existeTipo(tipo) ){ + + } + + + dec_ps 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) ) + TabelaSimb.insere( Funcao(id,ps,desloc,nivelLexico,rotulo,tipo) ) ps.foreach { param => if (TabelaSimb.temParamOuVarComMesmoId(param.id)) { println("Erro: Parâmetros com mesmo nome na função "+id+": "+ param.id) @@ -155,14 +182,26 @@ object Tudo { } } - def retornaParamsLst(params:List[(Option[String],List[String])], nivelLexico:Int):List[Param] = { - var desloc = -3 - params.map(_._2.size).sum + def retornaParamsLst(params:List[dec_param], nivelLexico:Int):List[Param] = { + var desloc = - 3 - params.map{ _.ids.size }.sum + + //Verifica tipos + var todosTipos = params.map{ _.tipo }.distinct + val invalido = todosTipos.find { t => ! TabelaSimb.existeTipo(t) } + + invalido match { + case Some(inv) => //Erro + println("Erro: Tipo não declarado na declaração de parametros: "+inv) + sys.exit(1) + case None => //Ok + } + //end + params.flatMap { - case (varOpt, idlst) => + case dec_param(byRef, idlst, tipo) => idlst map { id => - val p = Param(id,desloc,varOpt.isDefined,nivelLexico) desloc +=1 - p + Param(id,desloc-1,byRef,nivelLexico,tipo) } } } @@ -172,6 +211,7 @@ object Tudo { 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 t:Tipo => TabelaSimb.drop; contaVariaveis(nvLex,count) case r:Label => if (! r.used) {println("Warning: rótulo nunca usado: "+ r.id)} TabelaSimb.drop @@ -192,6 +232,7 @@ object Tudo { table.dropWhile { case p:Procedimento => if (p.nvLex>nivelLexico) true else false case f:Funcao => if (f.nvLex>nivelLexico) true else false + case t:Tipo => true case r:Label => if (r.used) { //Se rótulo nunca usado println("Warning: rótulo nunca usado: "+ r.id) -- GitLab