Skip to content
Snippets Groups Projects
Commit 4dc0ee36 authored by Lior Spach's avatar Lior Spach
Browse files

Add type support! (Tested)

parent 11afea5d
Branches
No related tags found
No related merge requests found
...@@ -5,6 +5,9 @@ import sun.java2d.pipe.SpanShapeRenderer.Simple ...@@ -5,6 +5,9 @@ import sun.java2d.pipe.SpanShapeRenderer.Simple
import other.Tudo.rotulos import other.Tudo.rotulos
import com.sun.org.apache.xml.internal.serializer.ToStream.BoolStack 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 { class Arith extends JavaTokenParsers {
//CONTROLE etc. //CONTROLE etc.
val fazTudo = Tudo val fazTudo = Tudo
...@@ -40,11 +43,19 @@ class Arith extends JavaTokenParsers { ...@@ -40,11 +43,19 @@ class Arith extends JavaTokenParsers {
} }
def bloco:Parser[Any] = 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"); if (nivelLexico==0) Tudo.aplica("DSVS R00");
else Tudo.aplica("DSVS "+Tudo.proc.RotStack.top) else Tudo.aplica("DSVS "+Tudo.proc.RotStack.top)
nivelLexico+=1 } ) ~ nivelLexico+=1
}) ~
(opt(dec_subrotinas) ^^ (opt(dec_subrotinas) ^^
{ _ => { _ =>
nivelLexico-=1 nivelLexico-=1
...@@ -64,24 +75,30 @@ class Arith extends JavaTokenParsers { ...@@ -64,24 +75,30 @@ class Arith extends JavaTokenParsers {
def dec_rotulos = "label".iso ~> """\d+""".r ~ rep("," ~> """\d+""".r) <~ ";" ^^ def dec_rotulos = "label".iso ~> """\d+""".r ~ rep("," ~> """\d+""".r) <~ ";" ^^
{ case x~xs => fazTudo.insereRotulos(x::xs, nivelLexico) } { 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 //VARIAVEIS
def dec_vars = "var".iso ~> dec_var ~ rep(";" ~> dec_var) <~ ";" ^^ def dec_vars = "var".iso ~> dec_var ~ rep(";" ~> dec_var) <~ ";" ^^
{ case xs~xss => fazTudo.insereIntVars(xs ::: xss.flatten, nivelLexico) } { case xss => fazTudo.insereIntVars(mkList(xss), nivelLexico) }
def dec_var = lista_ident <~ ":" ~ tipo def dec_var = (lista_ident <~ ":") ~ tipo ^^ { case ids ~ t => ids_t(ids, t)}
def lista_ident = ident ~ rep( "," ~> ident ) ^^ { mkList } def lista_ident = ident ~ rep( "," ~> ident ) ^^ { mkList }
def tipo = "integer"
//SUB-ROTINAS //SUB-ROTINAS
def dec_subrotinas = rep( (dec_proc | dec_func) <~ bloco ~ ";" ^^ def dec_subrotinas = rep( (dec_proc | dec_func) <~ bloco ~ ";" ^^
{ e => fazTudo.proc.saiProcFunc(nivelLexico); e} ) { e => fazTudo.proc.saiProcFunc(nivelLexico); e} )
def dec_proc = "procedure".iso ~> ident ~ opt(params_formais) <~ ";" ^^ def dec_proc = "procedure".iso ~> ident ~ opt(params_formais) <~ ";" ^^
{ case id ~ lstOptIds => fazTudo.proc.entraProc(id, lstOptIds, nivelLexico) } { case id ~ lstDecParam => fazTudo.proc.entraProc(id, lstDecParam, nivelLexico) }
def dec_func = "function".iso ~> ident ~ opt(params_formais) <~ ":" ~ tipo ~ ";" ^^ def dec_func = "function".iso ~> ident ~ opt(params_formais) ~ (":" ~> tipo) <~ ";" ^^
{ case id ~ lstOptIds => fazTudo.proc.entraFunc(id, lstOptIds, nivelLexico) } { 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_formais = "(" ~> params ~ rep(";" ~> params) <~ ")" ^^ { mkList }
def params = opt("var".iso) ~ lista_ident <~ ":" ~ tipo def params = opt("var".iso) ~ lista_ident ~ (":" ~> tipo) ^^ { case v ~ ids ~ tipo => dec_param(v.isDefined, ids, tipo)}
//COMANDOS //COMANDOS
def comando_composto:Parser[Any] = "begin".iso ~ comando ~ rep(";" ~ comando) ~ "end" def comando_composto:Parser[Any] = "begin".iso ~ comando ~ rep(";" ~ comando) ~ "end"
...@@ -389,12 +406,10 @@ object MyParser extends Arith { ...@@ -389,12 +406,10 @@ object MyParser extends Arith {
sys.exit(1) sys.exit(1)
} }
val pascalSource = io.Source.fromFile(args(0)).getLines().mkString("\n") val pascalSource = io.Source.fromFile(args(0)).getLines().mkString("\n")
// val pascalSource = ArqExemplos.p
try try
println(parseAll(PascalParser.program, pascalSource)) println(parseAll(PascalParser.program, pascalSource))
catch { case e : Exception => println("Erro no programa"); sys.exit(1) } catch { case e : Exception => println("Erro no programa"); sys.exit(1) }
val mp = Tudo.MEPA val mp = Tudo.MEPA
// mp foreach println
val pw = new java.io.PrintWriter("MEPA") val pw = new java.io.PrintWriter("MEPA")
mp foreach pw.println mp foreach pw.println
pw.close pw.close
......
...@@ -9,6 +9,7 @@ case class Procedimento(override val id:String, paramInfo:List[Param], ...@@ -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 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 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 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 { object TabelaSimb {
...@@ -45,6 +46,16 @@ 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 @tailrec
def numVarsLocais(nvLex:Int, count:Int=0, rest:List[Entrada] = table):Int = rest match { def numVarsLocais(nvLex:Int, count:Int=0, rest:List[Entrada] = table):Int = rest match {
case (v:Var) :: xs => numVarsLocais(nvLex, count+1, xs) case (v:Var) :: xs => numVarsLocais(nvLex, count+1, xs)
......
...@@ -15,25 +15,47 @@ object Tudo { ...@@ -15,25 +15,47 @@ object Tudo {
num match { num match {
case dig if num<10 => "0"+dig case dig if num<10 => "0"+dig
case dezena if num<100 => ""+dezena 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) = { def insereIntVars(vars_t: List[ids_t], nivelLexico: Int) = {
val orgSize = vars.size
var desloc = 0 //Garante que os tipos existem
if (orgSize == vars.distinct.size) { val lst_tipos = vars_t.map { case ids_t(_,t) => t }
TabelaSimb insere vars.map { id => val tipo_invalido = lst_tipos.distinct.find { t => ! TabelaSimb.existeTipo(t) } //Ache um que não existe
val v = Var(id, desloc, nivelLexico); desloc += 1; v
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
} }
aplica("AMEM " + orgSize) //end
} else {
//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("Erro: declaração de variáveis:")
println(" identificadores já declarados para parametros ou var: "+vars.diff(vars.distinct).mkString(" ")) println(" identificadores já declarados para parametros ou var: "+
listaIds.diff(listaIds.distinct).mkString(" "))
sys.exit(1) sys.exit(1)
} }
//end
var desloc = 0
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 = def geraMepaDoId(id: String, nvLexAtual:Int): Unit =
...@@ -116,10 +138,10 @@ object Tudo { ...@@ -116,10 +138,10 @@ object Tudo {
rotulo 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) val rotulo = entraProcFun(nivelLexico)
params match { dec_ps match {
case Some( lstParams ) if ! lstParams.isEmpty => case Some( lstParams ) if ! lstParams.isEmpty =>
val ps = retornaParamsLst(lstParams, nivelLexico) val ps = retornaParamsLst(lstParams, nivelLexico)
TabelaSimb.insere( Procedimento(id, ps, nivelLexico, rotulo) ) TabelaSimb.insere( Procedimento(id, ps, nivelLexico, rotulo) )
...@@ -135,14 +157,19 @@ object Tudo { ...@@ -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) val rotulo = entraProcFun(nivelLexico)
if ( ! TabelaSimb.existeTipo(tipo) ){
}
params match { dec_ps match {
case Some( lstParams ) if ! lstParams.isEmpty => case Some( lstParams ) if ! lstParams.isEmpty =>
val ps = retornaParamsLst(lstParams, nivelLexico) val ps = retornaParamsLst(lstParams, nivelLexico)
val desloc = -4-ps.size 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 => ps.foreach { param =>
if (TabelaSimb.temParamOuVarComMesmoId(param.id)) { if (TabelaSimb.temParamOuVarComMesmoId(param.id)) {
println("Erro: Parâmetros com mesmo nome na função "+id+": "+ param.id) println("Erro: Parâmetros com mesmo nome na função "+id+": "+ param.id)
...@@ -155,14 +182,26 @@ object Tudo { ...@@ -155,14 +182,26 @@ object Tudo {
} }
} }
def retornaParamsLst(params:List[(Option[String],List[String])], nivelLexico:Int):List[Param] = { def retornaParamsLst(params:List[dec_param], nivelLexico:Int):List[Param] = {
var desloc = -3 - params.map(_._2.size).sum 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 { params.flatMap {
case (varOpt, idlst) => case dec_param(byRef, idlst, tipo) =>
idlst map { id => idlst map { id =>
val p = Param(id,desloc,varOpt.isDefined,nivelLexico)
desloc +=1 desloc +=1
p Param(id,desloc-1,byRef,nivelLexico,tipo)
} }
} }
} }
...@@ -172,6 +211,7 @@ object Tudo { ...@@ -172,6 +211,7 @@ object Tudo {
case v:Var => TabelaSimb.drop; contaVariaveis(nvLex,count+1) case v:Var => TabelaSimb.drop; contaVariaveis(nvLex,count+1)
case p:Procedimento => if (p.nvLex>nvLex) {TabelaSimb.drop; contaVariaveis(nvLex,count)} else count 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 f:Funcao => if (f.nvLex>nvLex) {TabelaSimb.drop; contaVariaveis(nvLex,count)} else count
case t:Tipo => TabelaSimb.drop; contaVariaveis(nvLex,count)
case r:Label => case r:Label =>
if (! r.used) {println("Warning: rótulo nunca usado: "+ r.id)} if (! r.used) {println("Warning: rótulo nunca usado: "+ r.id)}
TabelaSimb.drop TabelaSimb.drop
...@@ -192,6 +232,7 @@ object Tudo { ...@@ -192,6 +232,7 @@ object Tudo {
table.dropWhile { table.dropWhile {
case p:Procedimento => if (p.nvLex>nivelLexico) true else false case p:Procedimento => if (p.nvLex>nivelLexico) true else false
case f:Funcao => if (f.nvLex>nivelLexico) true else false case f:Funcao => if (f.nvLex>nivelLexico) true else false
case t:Tipo => true
case r:Label => case r:Label =>
if (r.used) { //Se rótulo nunca usado if (r.used) { //Se rótulo nunca usado
println("Warning: rótulo nunca usado: "+ r.id) println("Warning: rótulo nunca usado: "+ r.id)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment