From 43a742fb64b3582ccaea7aee1e725809d1e14bd8 Mon Sep 17 00:00:00 2001
From: Lior Spach <ls12@inf.ufpr.br>
Date: Mon, 15 Jun 2015 03:18:09 -0300
Subject: [PATCH] Update parser.scala

---
 src/main/scala/other/Parser.scala | 202 +++++++++++++++++++++---------
 1 file changed, 140 insertions(+), 62 deletions(-)

diff --git a/src/main/scala/other/Parser.scala b/src/main/scala/other/Parser.scala
index 83e6615..7478d69 100644
--- a/src/main/scala/other/Parser.scala
+++ b/src/main/scala/other/Parser.scala
@@ -11,48 +11,18 @@ class Arith extends JavaTokenParsers {
   val rotStack = Tudo.proc.RotStack
   
   val procStack = collection.mutable.Stack[Entrada]()
-  object paramCounter {
-    var paramCount = List[Int]()
-    def get = paramCount.last
-    def ++ = 
-      if (paramCount.isEmpty) {
-        println(paramCount)
-        println("Empty ++ in paramCount")
-        sys.exit(1)
-      } else {
-        if (paramCount.size==1)
-          paramCount = Nil
-        else 
-          paramCount = paramCount.init :+ (paramCount.last+1)
-        println("++")
-      }
-    def newCount = {
-        paramCount = paramCount :+ 0
-        println(paramCount)
-      }
-    def done = {
-      println("done")
-      paramCount match {
-        case xs if ! xs.isEmpty =>
-          val last = xs.last
-          if (xs.size==1) paramCount = Nil
-          else paramCount = xs.init
-          last
-        case Nil =>
-          println("Erro done() em paramCounter nulo"); sys.exit(1) 
-      }
-    }
-  }
-  
+  val paramCounterStack = collection.mutable.Stack[Int]()
+
   def eh_param = procStack match {
-    case stack if ! stack.isEmpty =>
-      stack.top.isInstanceOf[Procedimento] || stack.top.isInstanceOf[Funcao]
+    case stack if ! stack.isEmpty => true
+//      stack.top.isInstanceOf[Procedimento] || stack.top.isInstanceOf[Funcao]
     case _ => false
   }
   
   //PARSER
   object PascalParser {
-    implicit class isola(s:String) {
+
+    implicit class isolavel(s:String) {
       def iso = (s + "\\s").r ^^ { _.take(s.size) }
     }
     
@@ -63,16 +33,17 @@ class Arith extends JavaTokenParsers {
       "program".iso ~> ident ~ programInOut <~ ";" ~ bloco ~ "." ^^
         { _ => fazTudo.encerraPrograma }
     }
+    
     def bloco:Parser[Any] =
         (opt(dec_rotulos) ~ opt(dec_vars) ^^ 
             { _ => 
-              if (nivelLexico==0) Tudo.aplica("DSVS R000");
+              if (nivelLexico==0) Tudo.aplica("DSVS R00");
               else Tudo.aplica("DSVS "+Tudo.proc.RotStack.top)
               nivelLexico+=1 } ) ~
         (opt(dec_subrotinas) ^^ 
           { _ => 
             nivelLexico-=1
-            if (nivelLexico==0) Tudo.aplica("R000: NADA") 
+            if (nivelLexico==0) Tudo.aplica("R00: NADA") 
             else
               if (Tudo.MEPA.last == "DSVS "+Tudo.proc.RotStack.top) {
                 //DSVS R003; R003: seguidos!
@@ -96,12 +67,13 @@ class Arith extends JavaTokenParsers {
     def tipo = "integer"
     
     //SUB-ROTINAS
-    def dec_subrotinas = rep( (dec_proc | dec_func) <~ bloco ~ ";" ^^ {  e => fazTudo.proc.saiProcFunc(nivelLexico); e} )
+    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)}
+      { 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 ~ lstOptIds => fazTudo.proc.entraFunc(id, lstOptIds, nivelLexico) }
     
     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
@@ -187,9 +159,36 @@ class Arith extends JavaTokenParsers {
     def relacao = "<="|">="|"="|"<>"|"<"|">"
     
     //EXPRESSOES
+    
     def lista_expr = 
-      expr_simples ~ rep("," ~ expr_simples) ^^
-      { mkList }
+      (expr_simples ^^ { foreachExpr }) ~
+        rep("," ~> (expr_simples ^^ { foreachExpr })) ^^ { mkList }
+    
+    def foreachExpr(o:Object) = {
+      procStack.top.id  match {
+        case "write" => fazTudo.aplica("IMPR")
+        case "read"  => //ok
+        case _ =>
+      }
+      val isByRef = Tudo.isAtArgByRef()
+      inc_pCount
+      // Check for byRef args
+      o match {
+        case s:String => //Okey
+        case o => 
+          if ( procStack.top.id=="read" )
+            assert(false, "Função read recebendo uma expressão!")
+          else if (isByRef) 
+            assert(false, "Parametro por referencia recebendo valor! Funcão/procedimento: " + procStack.top.id)
+          //else println("Okey")
+      }
+      o
+    }
+    
+    def inc_pCount {
+      paramCounterStack.push(1+paramCounterStack.pop)
+    }
+    
     def expr_simples:Parser[Object] = termo ~ rep( ("+"|"-") ~ termo ) ^^
     {
       case t ~ lst if ! lst.isEmpty =>
@@ -214,22 +213,73 @@ class Arith extends JavaTokenParsers {
     def fator = ( "("~expr_simples~")" | chamaId | numero ) ^^ { case p:String => p; case _ => new AnyRef}
     
     def getParamsCount(e:Entrada) = e match {
-      case f:Funcao => f.paramInfo
-      case p:Procedimento => p.paramInfo
+      case f:Funcao => f.paramInfo.size
+      case p:Procedimento => p.paramInfo.size
     }
     
   
   def ehProcFun(id:String) = {
     TabelaSimb.getById(id) match {
-      case Some(e) => e.isInstanceOf[Procedimento] || e.isInstanceOf[Funcao]
+      case Some(e) => 
+        e.isInstanceOf[Procedimento] || e.isInstanceOf[Funcao]
       case None => false
     }
   }
+  
+  def assert(bool: => Boolean, errMsg:String) {
+    if ( ! bool ) {
+      println("Erro: " + errMsg)
+      sys.exit(1)
+    }
+  }
     
-  var passaId = ""
+  def entraId(id:String) 
+  {
+    if (ehProcFun(id)) {
+      if ( TabelaSimb.getById(id).get.isInstanceOf[Funcao] )
+        Tudo.aplica("AMEM 1")
+      procStack.push(TabelaSimb.getById(id).get)
+      paramCounterStack.push(0)
+      
+    } else if (id=="write" || id=="read") {
+      
+      procStack.push(new Entrada(id))
+      paramCounterStack.push(0)
+      id match {
+        case "write" =>
+        case "read"  =>
+      }
+      
+    }
+  }
+  
+  def saiId(id:String)
+  {
+    
+    if (id=="write" || id=="read") { 
+      procStack.pop
+      return
+    }
+    if (!procStack.isEmpty && procStack.top.id == "read"){
+      fazTudo.aplica("LEIT")
+      if (id != "read") fazTudo.atribuicao(id)
+      return
+    }
+
+      
+    if ( ehProcFun(id) ) {
+      val proc = procStack.pop
+      val nParams = paramCounterStack.pop
+      assert(nParams == getParamsCount(proc), 
+          "Número de parametros incorretos na chamada da função/procedimento "+id)
+    }
+
+    fazTudo.geraMepaDoId(id, nivelLexico)
+  }
   
   def chamaId =
-   ident <~ opt("(" ~ lista_expr ~ ")") ^^ { id => fazTudo.chamaId(id, nivelLexico); id }
+   (ident ^^ { id => entraId(id); id }) <~ opt("(" ~ lista_expr ~ ")") ^^ 
+   { id => saiId(id); id }
     
   def numero = wholeNumber ^^ { case x => fazTudo.literal(x.toInt) }
     
@@ -239,32 +289,60 @@ 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")
-    parseAll(PascalParser.program, pascalSource)
-    val mp = Tudo.MEPA
-    val pw = new java.io.PrintWriter(args(1))
-    mp foreach pw.println
+//    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
   }
   
 
-//TODO: (-x)
-//TODO: READ/WRITE COM DOIS PARAMETROS
-//TODO: Verificar número correto de parametros ao chamar funcao  
+//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,c:integer;
+  var a,b:integer;
+      c:integer;
+
   begin
     while x>2 do begin
       x := x+1;
-      p := p(t,a)
+      p := p(t-10)
     end;
     t := x - 20*4 - (23 div (x/2)) + b
   end;
-- 
GitLab