diff --git a/src/main/scala/Parser.scala b/src/main/scala/Parser.scala
new file mode 100644
index 0000000000000000000000000000000000000000..83e66152a4e5f696fea951bdd949c1c42469a9f8
--- /dev/null
+++ b/src/main/scala/Parser.scala
@@ -0,0 +1,322 @@
+package other
+
+import scala.util.parsing.combinator._
+import sun.java2d.pipe.SpanShapeRenderer.Simple
+import other.Tudo.rotulos
+
+class Arith extends JavaTokenParsers {
+  //CONTROLE etc.
+  val fazTudo = Tudo
+  var nivelLexico = 0
+  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) 
+      }
+    }
+  }
+  
+  def eh_param = procStack match {
+    case stack if ! stack.isEmpty =>
+      stack.top.isInstanceOf[Procedimento] || stack.top.isInstanceOf[Funcao]
+    case _ => false
+  }
+  
+  //PARSER
+  object PascalParser {
+    implicit class isola(s:String) {
+      def iso = (s + "\\s").r ^^ { _.take(s.size) }
+    }
+    
+    //PROGRAM
+    def program  = {
+      def programInOut = "(" ~> repsep(ident,",") <~ ")"
+      fazTudo.iniciaPrograma
+      "program".iso ~> ident ~ programInOut <~ ";" ~ bloco ~ "." ^^
+        { _ => fazTudo.encerraPrograma }
+    }
+    def bloco:Parser[Any] =
+        (opt(dec_rotulos) ~ opt(dec_vars) ^^ 
+            { _ => 
+              if (nivelLexico==0) Tudo.aplica("DSVS R000");
+              else Tudo.aplica("DSVS "+Tudo.proc.RotStack.top)
+              nivelLexico+=1 } ) ~
+        (opt(dec_subrotinas) ^^ 
+          { _ => 
+            nivelLexico-=1
+            if (nivelLexico==0) Tudo.aplica("R000: NADA") 
+            else
+              if (Tudo.MEPA.last == "DSVS "+Tudo.proc.RotStack.top) {
+                //DSVS R003; R003: seguidos!
+                Tudo.rotulos.--
+                Tudo.proc.RotStack.pop()
+                Tudo.MEPA.remove(Tudo.MEPA.size - 1)
+              } else
+                Tudo.aplica(Tudo.proc.RotStack.pop()+": NADA")
+          }
+        ) ~ comando_composto
+
+    //ROTULOS
+    def dec_rotulos = "label".iso ~> """\d+""".r ~ rep("," ~> """\d+""".r) <~ ";" ^^
+      { case x~xs => fazTudo.insereRotulos(x::xs, nivelLexico) }
+    
+    //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
+    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)}
+    
+    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
+    
+    //COMANDOS
+    def comando_composto:Parser[Any] = "begin".iso ~ comando ~ rep(";" ~ comando) ~ "end"
+    def comando = opt("""\d+""".r <~ ":" ^^ { rot => fazTudo.entraRotulo(rot,nivelLexico) }) <~ comando_sem_rotulo
+    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 desvio = "goto".iso ~> """\d+""".r ^^ { rot => fazTudo.gotoRotulo(rot,nivelLexico) }
+    
+    def condicional = 
+      ("if".iso ~ boolexpr ^^ { e =>
+        val r = Tudo.rotulos.geraRotulo
+        Tudo.aplica("DSVF "+r)
+        rotStack.push(r)
+        e
+      }) ~ 
+      "then".iso ~
+      (comando_sem_rotulo ^^ { _ => Tudo.aplica(rotStack.pop+": NADA") }) ~
+      opt(
+          ("else".iso ^^ { _ =>
+            val gotoElse = Tudo.MEPA.remove(Tudo.MEPA.size - 1)//.takeWhile {_!=':'}
+            //rotStack.push(fim_if)
+            rotStack.push(rotulos.geraRotulo)
+            Tudo.aplica("DSVS "+rotStack.top) //Vai pro fim do if
+            Tudo.aplica(gotoElse)
+          }) 
+          ~ (comando_sem_rotulo ^^ { _ => Tudo.aplica(rotStack.pop+": NADA") })
+      )
+       
+    def repeticao = 
+      (("while" ^^ { _=> 
+          val rotLoop = rotulos.geraRotulo
+          Tudo.aplica(rotLoop+": NADA")
+          rotStack.push(rotLoop)
+      }) ~ boolexpr ~ "do" ^^ { _ => 
+          val rotFim = rotulos.geraRotulo
+          Tudo.aplica("DSVF "+rotFim)
+          rotStack.push(rotFim)
+      }) ~ comando_sem_rotulo ^^ { _=>
+          val rotFim = rotStack.pop
+          val rotLoop = rotStack.pop
+          Tudo.aplica("DSVS "+rotLoop)
+          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 )
+      ) ^^
+      { lst => lst.reverse.foreach { case "and" => fazTudo.aplica("CONJ")
+                                     case "or"  => fazTudo.aplica("DISJ")}
+      }
+    
+    def boolexpr_simples =
+      (
+        expr_simples ~> relacao <~ expr_simples | 
+        "(" ~ expr_simples ~> relacao <~ expr_simples ~ ")"
+      ) ^^
+          {
+            case "="  => fazTudo.aplica("CMIG")
+            case "<>" => fazTudo.aplica("CMDG")
+            case "<=" => fazTudo.aplica("CMEG")
+            case ">=" => fazTudo.aplica("CMAG")
+            case "<"  => fazTudo.aplica("CMME")
+            case ">"  => fazTudo.aplica("CMMA")
+          }
+    def relacao = "<="|">="|"="|"<>"|"<"|">"
+    
+    //EXPRESSOES
+    def lista_expr = 
+      expr_simples ~ rep("," ~ expr_simples) ^^
+      { mkList }
+    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  
+    }
+    
+    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 
+      }
+    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
+    }
+    
+  
+  def ehProcFun(id:String) = {
+    TabelaSimb.getById(id) match {
+      case Some(e) => e.isInstanceOf[Procedimento] || e.isInstanceOf[Funcao]
+      case None => false
+    }
+  }
+    
+  var passaId = ""
+  
+  def chamaId =
+   ident <~ opt("(" ~ lista_expr ~ ")") ^^ { id => fazTudo.chamaId(id, nivelLexico); id }
+    
+  def numero = wholeNumber ^^ { case x => fazTudo.literal(x.toInt) }
+    
+  }
+}
+
+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
+  }
+  
+
+//TODO: (-x)
+//TODO: READ/WRITE COM DOIS PARAMETROS
+//TODO: Verificar número correto de parametros ao chamar funcao  
+  
+val loopPascalProgram = 
+"""program exemplo12 (input,output);
+  var x: integer;
+  function p(var t: integer):integer;
+  label 200;
+  var a,b,c:integer;
+  begin
+    while x>2 do begin
+      x := x+1;
+      p := p(t,a)
+    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.
+"""
+
+}