From 272674145b24a875d463c216aa2797115f891c3a Mon Sep 17 00:00:00 2001
From: Lior Dinf <ls12@inf.ufpr.br>
Date: Mon, 15 Jun 2015 17:56:40 -0300
Subject: [PATCH] lala

---
 src/main/scala/other/ArqExemplos.scala | 112 ++++++++++++-
 src/main/scala/other/Parser.scala      | 223 ++++++++++---------------
 src/main/scala/other/TabelaSimb.scala  |   4 +-
 src/main/scala/other/Tudo.scala        |   4 +-
 4 files changed, 203 insertions(+), 140 deletions(-)

diff --git a/src/main/scala/other/ArqExemplos.scala b/src/main/scala/other/ArqExemplos.scala
index 151aa40..806d9d3 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 7478d69..d20ee85 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 799fe14..db2341e 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 4e733d8..fc648f1 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
-- 
GitLab