diff --git a/src/main/scala/other/ArqExemplos.scala b/src/main/scala/other/ArqExemplos.scala index 151aa407cf1bb432cd5de2f14202539c6b913c56..806d9d3142c617616a7874160f076d431a2e57f4 100644 --- a/src/main/scala/other/ArqExemplos.scala +++ b/src/main/scala/other/ArqExemplos.scala @@ -2,6 +2,37 @@ package other object ArqExemplos { +val p = +"""program exemplo7(input, output); +var x, y : integer; +procedure p; +var z : integer; +begin + z:=x; x:=x-1; + if z>1 + then p + else y:=1; + y:=y*z +end; + +procedure q; +var s, t : integer; +begin + s:=x; t:=x-1; x:=t; + if s=0 then y:=1 + else + if ((s div 2)*2) = s + then q + else p; + y:=y*s +end; + +begin + read(x); + q; + write(y) +end.""" + val exemplo5 = """program exemplo5 (input, output); var n, k : integer; @@ -90,5 +121,84 @@ end. """ +} -} \ No newline at end of file +/* + INPP + AMEM 2 + DSVS R00 +R01: ENPR 1 + AMEM 1 + DSVS R02 +R02: NADA + CRVL 0, 0 + ARMZ 1, 0 + CRVL 0, 0 + CRCT 1 + SUBT + ARMZ 0, 0 + CRVL 1, 0 + CRCT 1 + CMMA + DSVF R04 + CHPR R01, 1 + DSVS R03 +R04: NADA + CRCT 1 + ARMZ 0, 1 +R03: NADA + CRVL 0, 1 + CRVL 1, 0 + MULT + ARMZ 0, 1 + DMEM 1 + RTPR 1, 0 +R05: ENPR 1 + AMEM 2 + DSVS R06 +R06: NADA + CRVL 0, 0 + ARMZ 1, 0 + CRVL 0, 0 + CRCT 1 + SUBT + ARMZ 1, 1 + CRVL 1, 1 + ARMZ 0, 0 + CRVL 1, 0 + CRCT 0 + CMIG + DSVF R08 + CRCT 1 + ARMZ 0, 1 + DSVS R07 +R08: NADA + CRVL 1, 0 + CRCT 2 + DIVI + CRCT 2 + MULT + CRVL 1, 0 + CMIG + DSVF R10 + CHPR R05, 1 + DSVS R09 +R10: NADA + CHPR R01, 1 +R09: NADA +R07: NADA + CRVL 0, 1 + CRVL 1, 0 + MULT + ARMZ 0, 1 + DMEM 2 + RTPR 1, 0 +R00: NADA + LEIT + ARMZ 0, 0 + CHPR R05, 0 + CRVL 0, 1 + IMPR + DMEM 2 + PARA +*/ \ No newline at end of file diff --git a/src/main/scala/other/Parser.scala b/src/main/scala/other/Parser.scala index 7478d6958cd8bff6308c5a5258803aff1ca984b7..d20ee857a731f5af0ca51c0be7fa70a21620ef32 100644 --- a/src/main/scala/other/Parser.scala +++ b/src/main/scala/other/Parser.scala @@ -3,6 +3,7 @@ package other import scala.util.parsing.combinator._ import sun.java2d.pipe.SpanShapeRenderer.Simple import other.Tudo.rotulos +import com.sun.org.apache.xml.internal.serializer.ToStream.BoolStack class Arith extends JavaTokenParsers { //CONTROLE etc. @@ -10,8 +11,12 @@ class Arith extends JavaTokenParsers { var nivelLexico = 0 val rotStack = Tudo.proc.RotStack + val stackbooltipo = collection.mutable.Stack[String]() + val stacktipo = collection.mutable.Stack[String]() val procStack = collection.mutable.Stack[Entrada]() val paramCounterStack = collection.mutable.Stack[Int]() + + var eh_atrib = false //esta dentro de uma atribuicao def eh_param = procStack match { case stack if ! stack.isEmpty => true @@ -30,7 +35,7 @@ class Arith extends JavaTokenParsers { def program = { def programInOut = "(" ~> repsep(ident,",") <~ ")" fazTudo.iniciaPrograma - "program".iso ~> ident ~ programInOut <~ ";" ~ bloco ~ "." ^^ + "program".iso ~> ident ~ opt(programInOut) <~ ";" ~ bloco ~ "." ^^ { _ => fazTudo.encerraPrograma } } @@ -84,8 +89,8 @@ class Arith extends JavaTokenParsers { def comando_sem_rotulo:Parser[Any] = desvio | atribuicao | repeticao | condicional | comando_composto | chamaId | expr_simples - def atribuicao = ident <~ ":=" ~ expr_simples ^^ - { case id => fazTudo.atribuicao(id) } + def atribuicao = (ident ^^ {e => eh_atrib = true; e}) <~ ":=" ~ expr_simples ^^ + { case id => eh_atrib = false; fazTudo.atribuicao(id) } def desvio = "goto".iso ~> """\d+""".r ^^ { rot => fazTudo.gotoRotulo(rot,nivelLexico) } @@ -125,19 +130,20 @@ class Arith extends JavaTokenParsers { Tudo.aplica(rotFim+": NADA") } - def amem1ForFunctions(id:String) { - val opt = TabelaSimb.getById(id) - opt match { - case Some(fun) if fun.isInstanceOf[Funcao] => Tudo.aplica("AMEM 1") - case _ => //Dont care - } - } - //EXPRESSOES BOOLEANAS def boolexpr:Parser[Unit] = ( - "(" ~> boolexpr_simples ~> rep( ("and"|"or") <~ boolexpr_simples ) <~ ")" | - boolexpr_simples ~> rep ( ("and"|"or") <~ boolexpr ) + //"(" ~> boolexpr_simples ~> rep( ("and"|"or") <~ boolexpr_simples ) <~ ")" | + (boolexpr_simples ^^ {e => + val a = stackbooltipo.pop() + val b = if (stackbooltipo.isEmpty) a else stackbooltipo.pop + if (a != b) { + println("Erro de tipo: comparação entre dois tipos diferentes"); + sys.exit(1) + } + e + } ) ~> + rep ( ("and"|"or") <~ boolexpr ) ) ^^ { lst => lst.reverse.foreach { case "and" => fazTudo.aplica("CONJ") case "or" => fazTudo.aplica("DISJ")} @@ -155,6 +161,7 @@ class Arith extends JavaTokenParsers { case ">=" => fazTudo.aplica("CMAG") case "<" => fazTudo.aplica("CMME") case ">" => fazTudo.aplica("CMMA") + case _ => sys.exit(1) } def relacao = "<="|">="|"="|"<>"|"<"|">" @@ -190,25 +197,38 @@ class Arith extends JavaTokenParsers { } def expr_simples:Parser[Object] = termo ~ rep( ("+"|"-") ~ termo ) ^^ - { - case t ~ lst if ! lst.isEmpty => - lst.reverse.foreach { - case ("+" ~ t) => fazTudo.aplica("SOMA") - case ("-" ~ t) => fazTudo.aplica("SUBT") - case _ => println("op???") - } - new AnyRef - case t ~ Nil => t + { e => + if (stacktipo.distinct.size > 1) + { + println("Erro de tipo detectado!") + sys.exit(1) + } else { + stackbooltipo.push(stacktipo.top) + stacktipo.clear() + } + e match { + case t ~ lst if ! lst.isEmpty => + lst.reverse.foreach { + case ("+" ~ t) => fazTudo.aplica("SOMA") + case ("-" ~ t) => fazTudo.aplica("SUBT") + case _ => println("op???") + } + new AnyRef + case t ~ Nil => t + } } def termo = fator ~ rep( ("*"|"div"|"/") ~ fator ) ^^ - { case fat~lst if ! lst.isEmpty => - lst.map{ case ~(str,_) => str }.reverse.foreach { - case "*" => fazTudo.aplica("MULT") - case "div"|"/" => fazTudo.aplica("DIVI") - } - new AnyRef - case fat ~ Nil => fat + { e => + e match { + case fat~lst if ! lst.isEmpty => + lst.map{ case ~(str,_) => str }.reverse.foreach { + case "*" => fazTudo.aplica("MULT") + case "div"|"/" => fazTudo.aplica("DIVI") + } + new AnyRef + case fat ~ Nil => fat + } } def fator = ( "("~expr_simples~")" | chamaId | numero ) ^^ { case p:String => p; case _ => new AnyRef} @@ -235,9 +255,14 @@ class Arith extends JavaTokenParsers { def entraId(id:String) { + TabelaSimb.getById(id) match { + case Some(p) if p.isInstanceOf[Param] => stacktipo.push(p.asInstanceOf[Param].tipo) + case Some(v) if v.isInstanceOf[Var]=> stacktipo.push(v.asInstanceOf[Var].tipo) + case _ => + } if (ehProcFun(id)) { if ( TabelaSimb.getById(id).get.isInstanceOf[Funcao] ) - Tudo.aplica("AMEM 1") + if (eh_atrib) Tudo.aplica("AMEM 1") procStack.push(TabelaSimb.getById(id).get) paramCounterStack.push(0) @@ -262,7 +287,25 @@ class Arith extends JavaTokenParsers { } if (!procStack.isEmpty && procStack.top.id == "read"){ fazTudo.aplica("LEIT") - if (id != "read") fazTudo.atribuicao(id) + if (id != "read") { + var tipo = "" + TabelaSimb.getById(id) match { + case Some(s) => s match { + case v:Var => tipo = v.tipo + case p:Param => tipo = p.tipo + case _ => + } + case _ => + } + if (tipo != "") { + if (tipo != stackbooltipo.pop()) { + println("Erro de tipo: atribuição com tipos diferentes") + sys.exit(1) + } + } + + fazTudo.atribuicao(id) + } return } @@ -289,112 +332,22 @@ class Arith extends JavaTokenParsers { object MyParser extends Arith { def main(args: Array[String]) { -// if (args.size != 2) { -// println("./compilador [ArqEntrada] [NomeArquivoSaida]") -// sys.exit(1) -// } -// val pascalSource = io.Source.fromFile(args(0)).getLines().mkString("\n") - val pascalSource = ArqExemplos.exemplo8_10 - println(parseAll(PascalParser.program, pascalSource)) - Tudo.MEPA foreach println -// val mp = Tudo.MEPA -// val pw = new java.io.PrintWriter(args(1)) -// mp foreach pw.println + if (args.size != 1) { + println("./compilador [ArqEntrada]") + 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 } //TODO: function return as parameter/atribution - - - -val noloopPascalProgram = -"""program exemplo12 (input,output); - var x: integer; - function p(a:integer; var t: integer):integer; - label 200; - var a,b:integer; - c:integer; - procedure q(var a:integer; y:integer); - begin - q(a,c+b+a+20); - write(b,a); - read(a,b) - end; - begin - p := p(20,a); - t := (23 div (x/2)) + b - end; -begin - x := p(x,x); - write(x) -end. -""" - - -val loopPascalProgram = -"""program exemplo12 (input,output); - var x: integer; - function p(var t: integer):integer; - label 200; - var a,b:integer; - c:integer; - - begin - while x>2 do begin - x := x+1; - p := p(t-10) - end; - t := x - 20*4 - (23 div (x/2)) + b - end; -begin - x := p(x); - write(x) -end. -""" - -val simplePascalProgram = -"""program exemplo12 (input,output); - var x: integer; - function p(var t: integer):integer; - label 200; - var a,b,c:integer; - begin - 200: if t>3 and (p(x)<4 or t=-1) and t>=1 then - write(t); - read(x); - goto 200; - t := x - 20*4 - (23 div (x/2)) + b; - p := t - end; -begin - x := p(x); - write(x) -end. -""" -val complexPascalProgram = -"""program exemplo12 (input,output); - var x: integer; - procedure p(var t: integer); - label 100,200; - var s : integer; - function f(z:integer):integer; - begin - if z=1 then z:=2; - if z<0 and 10>2 then goto 200 - else if z=0 then f:=2 - else f:=f(z-2)*z+1 - end; - begin - 100: s:=f(t); t:=s; - if t<x then goto 100; - 200: x:=x-1 - end; - procedure r; - procedure q; - var y:integer; - begin read(y); p(y); write(y) end; - begin q end; - begin read(x); r end. -""" - } diff --git a/src/main/scala/other/TabelaSimb.scala b/src/main/scala/other/TabelaSimb.scala index 799fe14905523f90233c9404819b4b33f92b840e..db2341e77df692d1ba63261df44f043df2f8ac0b 100644 --- a/src/main/scala/other/TabelaSimb.scala +++ b/src/main/scala/other/TabelaSimb.scala @@ -6,8 +6,8 @@ case class Funcao (override val id:String, paramInfo:List[Param], desloc:Int, nvLex:Int, rotEntrada:String) extends Entrada(id) case class Procedimento(override val id:String, paramInfo:List[Param], nvLex:Int, rotEntrada:String) extends Entrada(id) -case class Param(override val id:String, desloc: Int, byRef:Boolean, nvLex:Int) extends Entrada(id) -case class Var(override val id:String, desloc: Int, nvLex:Int) 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 Label(override val id:String, rotulo:String, nvLex:Int, var used:Boolean = false, var put:Boolean = false) extends Entrada(id) object TabelaSimb { diff --git a/src/main/scala/other/Tudo.scala b/src/main/scala/other/Tudo.scala index 4e733d888b81fc63a2efcd7766e5b1c84a60f235..fc648f1d3bf62efb1ce98c5e7c65e66d2e7d8b29 100644 --- a/src/main/scala/other/Tudo.scala +++ b/src/main/scala/other/Tudo.scala @@ -285,7 +285,7 @@ object Tudo { } } - def reservadas = List("program", "label", "var", "procedure", "function","begin","end", - "if", "then", "else", "while", "do", "or", "and","div","not") +// 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