From f5323224800a4b460b5ea369bcaa301c36ff3840 Mon Sep 17 00:00:00 2001
From: ls12 5o Andar <ls12@inf.ufpr.br>
Date: Fri, 22 May 2015 16:54:29 -0300
Subject: [PATCH] versao nova

---
 src/main/scala/lexer/Definicoes.scala    |  5 ++-
 src/main/scala/lexer/Lexer.scala         | 19 ++++++++--
 src/main/scala/lexer/LexerHelper.scala   | 25 +++++++++++--
 src/main/scala/lexer/Test.scala          | 25 ++++++++++---
 src/main/scala/semantico/Casos.scala     | 47 ++++++++++++++++++++++++
 src/main/scala/semantico/Expr.scala      |  1 +
 src/main/scala/semantico/TestCasos.scala | 31 ++++++++++++++++
 7 files changed, 140 insertions(+), 13 deletions(-)
 create mode 100644 src/main/scala/semantico/Casos.scala
 create mode 100644 src/main/scala/semantico/Expr.scala
 create mode 100644 src/main/scala/semantico/TestCasos.scala

diff --git a/src/main/scala/lexer/Definicoes.scala b/src/main/scala/lexer/Definicoes.scala
index 7258671..1bd969f 100644
--- a/src/main/scala/lexer/Definicoes.scala
+++ b/src/main/scala/lexer/Definicoes.scala
@@ -4,13 +4,15 @@ package lexer
 trait Definicoes {
   //Conjuntos
   val palavrasReservadas = List("begin", "end", "function", "procedure", "var", "program",
-                                "label","integer","goto","if","then","else","read","write",
+                                "label","goto","if","then","else","read","write",
                                 "while","do")
+  val tipos = List("integer")
   val letras = List.concat('a' to 'z', 'A' to 'Z', "_")
   val numeros = ('0' to '9').toList
   val separadores = List(' ', '\t', '\n', ';',',',':')
   val operadores = 
     "+ - * / += -= *= /= ++ -- = < > <= >= <> :=".split(" ").toList 
+  val operadoresArit = "+-*/".sliding(1).toList
     
   //Funcoes booleanas
   val operadorValido = (s: String) => operadores.contains(s)
@@ -20,4 +22,5 @@ trait Definicoes {
   val ehEspacoLinTab = (c: Char) => c == ' ' || c == '\t' || c == '\n' || c == 13
   val ehSeparador = (c: Char) => separadores.contains(c)
   val ehPalavraReservada = (s: String) => palavrasReservadas.contains(s)
+  val ehTipo = (s: String) => tipos.contains(s)
 }
\ No newline at end of file
diff --git a/src/main/scala/lexer/Lexer.scala b/src/main/scala/lexer/Lexer.scala
index fe95170..ad084ff 100644
--- a/src/main/scala/lexer/Lexer.scala
+++ b/src/main/scala/lexer/Lexer.scala
@@ -7,24 +7,37 @@ case class Token(val valor: String, val func: String)
 
 object Lexer {
   val h = new LexerHelper
-
+  var linhaAtual = 1
   @tailrec 
   final def getTokens(input: List[Char], acc:List[Token] = Nil): List[Token] = input match  {
     case letra :: _ if h.ehLetra(letra) =>
       val token = h.casoLetra(input)
       getTokens(input.drop(token.valor.size), token :: acc)
+      
     case op :: _ if h.ehOp(op) =>
       val token = h.casoOp(input)
       getTokens(input.drop(token.valor.size), token :: acc)
+      
     case escape :: _ if h.ehEspacoLinTab(escape) =>
+      if (escape == '\n') linhaAtual+=1
       getTokens( input.dropWhile{h.ehEspacoLinTab}, acc )
-//    case comment :: rest if comment=="(" && rest.head == "*" =>
-      //treat Comment
+      
+    case comment :: rest if comment=='(' && rest.head == '*' =>
+      val index = rest.tail.indexOfSlice("*)")
+      if (index == -1) h.erro("Comentário não foi fechado")
+      getTokens( rest.tail.drop(index+2), acc )
+            
+    case num :: _ if h.ehNum(num) =>
+      val token = h.caseNum(input)
+      getTokens(input.drop(token.valor.size), token :: acc)
+      
     case other :: _ if "(),;.".contains(other) =>
       val token = Token(""+other, "controle")
       getTokens(input.tail, token :: acc)
+      
     case Nil =>
       acc.reverse
+      
     case _ =>
       println("EMPTY? "+input.head.toInt + '\n'.toInt)
       sys.exit()
diff --git a/src/main/scala/lexer/LexerHelper.scala b/src/main/scala/lexer/LexerHelper.scala
index 581fcae..9a5c578 100644
--- a/src/main/scala/lexer/LexerHelper.scala
+++ b/src/main/scala/lexer/LexerHelper.scala
@@ -1,20 +1,22 @@
 
 package lexer
 
+import scala.annotation.tailrec
+
 class LexerHelper extends Definicoes {
 
   //Acoes
-  def erro(msg: String) = { println("Erro: " + msg); sys.exit(1) }
+  def erro(msg: String) = { println("Erro: " + msg +" (linha:"+Lexer.linhaAtual+")"); sys.exit(1) }
 
   //TAKES
-  def takeOp(input:List[Char],acc:String = ""):String = input match {
+  @tailrec final def takeOp(input:List[Char],acc:String = ""):String = input match {
     case Nil => acc
     case op :: rest if ehOp(op) =>
       takeOp(rest,acc+op)
     case notOp :: rest if !ehOp(notOp) =>
       acc
   }
-  def take(input: List[Char], acc: String = ""): String = {
+  @tailrec final def take(input: List[Char], acc: String = ""): String = {
     def isNotASeparatorNorOperator: Boolean  = ! (ehSeparador(input.head) || ehOp(input.head))
     input match { 
       case in :: _ if ehLetra(in) || ehNum(in) =>
@@ -23,6 +25,12 @@ class LexerHelper extends Definicoes {
         acc
     }
   }
+  @tailrec final def takeNum(input: List[Char], acc:String = ""):String = input match {
+    case Nil => acc
+    case num if ehNum(input.head) => takeNum(input.tail, acc+input.head)
+    case letra if ehLetra(input.head) => erro("número inválido")
+    case sep if ehSeparador(input.head) || ehOp(input.head) => acc
+  }
   
   //CASOS
   def casoLetra(input: List[Char]):Token = {
@@ -30,7 +38,9 @@ class LexerHelper extends Definicoes {
     val forwardInput = input.drop(palavra.size)
     val valido = palavra.forall
            { ch => ehLetra(ch) || ehNum(ch) }
-    val tipo = if (ehPalavraReservada(palavra)) "reservada" else "identificador"
+    val tipo = if (ehPalavraReservada(palavra)) "reservada"
+               else if (ehTipo(palavra)) "tipo"
+               else "identificador"
     Token(palavra, tipo)
   }
   def casoOp(input: List[Char]):Token = {
@@ -41,4 +51,11 @@ class LexerHelper extends Definicoes {
       case _ => erro("operador invalido" + fullOp)
     }
   }
+
+  def caseNum(input: List[Char]):Token = {
+    val num = takeNum(input)
+    Token(num,"numero")
+  }
+
+
 }
\ No newline at end of file
diff --git a/src/main/scala/lexer/Test.scala b/src/main/scala/lexer/Test.scala
index 4112782..cf34bb5 100644
--- a/src/main/scala/lexer/Test.scala
+++ b/src/main/scala/lexer/Test.scala
@@ -29,11 +29,17 @@ object Test {
     val testString = simplePascalProgram.toList
     val answer = List(
         Token("program","reservada"),Token("exemplo12","identificador"),Token("(","controle"),Token("input","identificador"),Token(",","controle"),Token("output","identificador"),Token(")","controle"),Token(";","controle"),
-        Token("var","reservada"),Token("x","identificador"),Token(":","dois pontos"),Token("integer","reservada"),
-        Token(";","controle"),Token("procedure","reservada"),Token("p","identificador"),Token("(","controle"),
-        Token("var","reservada"),Token("t","identificador"),Token(":","dois pontos"),Token("integer","reservada"),
-        Token(")","controle"),Token(";","controle"),Token("begin","reservada"),Token("read","reservada"),
-        Token("(","controle"),Token("x","identificador"),Token(")","controle"),Token(";","controle"),Token("t","identificador"),Token(":=","operador"),
+        Token("var","reservada"),Token("x","identificador"),Token(":","dois pontos"),Token("integer","tipo"),
+        Token(";","controle"),Token("procedure","reservada"),Token("p","identificador"),
+        Token("(","controle"),Token("var","reservada"),Token("t","identificador"),Token(":","dois pontos"),Token("integer","tipo"),Token(")","controle"),
+        Token(";","controle"),
+        Token("label","reservada"), Token("100","numero"), Token(",","controle"), Token("200","numero"),Token(";","controle"),
+        Token("begin","reservada"),Token("read","reservada"),
+        Token("(","controle"),Token("x","identificador"),Token(")","controle"),Token(";","controle"),
+        Token("200","numero"),Token(":","dois pontos"),
+        Token("x","identificador"),Token(":=","operador"),Token("x","identificador"),Token("+","operador"),
+        Token("20","numero"),Token(";","controle"),
+        Token("t","identificador"),Token(":=","operador"),
         Token("x","identificador"),Token("end","reservada"),Token(";","controle"),Token("begin","reservada"),
         Token("p","identificador"),Token("(","controle"),Token("x","identificador"),Token(")","controle"),
         Token(";","controle"),Token("write","reservada"),Token("(","controle"),Token("x","identificador"),
@@ -47,8 +53,17 @@ val simplePascalProgram =
 """program exemplo12 (input,output);
   var x: integer;
   procedure p(var t: integer);
+  label 100,200;
   begin
     read(x);
+    200: x:= x + 20 ; (* 
+    Big comentary with alot of junk to test it well
+        [awdfkaw op wadk p203 43 4 3 42iojio3j awdfkaw op wadk p203 43 4 3 42iojio3j ]
+        [awdfkaw op wadk p203 43 4 3 42iojio3j                                       ]
+        [dwopkda0)))*                                                                ]
+        [345634523))))                                                               ]
+        [=40=-=2=-=13=230    (***                                                    ]
+    *)
     t := x
   end;
 begin 
diff --git a/src/main/scala/semantico/Casos.scala b/src/main/scala/semantico/Casos.scala
new file mode 100644
index 0000000..6286f4e
--- /dev/null
+++ b/src/main/scala/semantico/Casos.scala
@@ -0,0 +1,47 @@
+package semantico
+import lexer.Token
+
+case class ParseResult(novoInput:List[Token], aceita:Boolean)
+
+trait Casos {
+  var linhaAtual = 0 //TODO: how to keep track of newline on semantic parser?
+  def parseError(msg:String) = {
+    println("[Erro] linha:"+linhaAtual+" => "+ msg)
+    sys.exit(1)
+  }
+  
+  def _program (input: List[Token]):ParseResult = input match {
+    case Token("program","reservada") :: Token(_,"identificador") :: resto =>
+      resto match {
+        case Token(";","controle") :: rest => ParseResult(rest,true)
+        case Token("(","controle") :: Token(_,"identificador") :: Token(",","controle") :: Token(_,"identificador") ::
+             Token(")","controle") :: Token(";","controle") :: rest 
+             => ParseResult(rest,true)
+        case _ => ParseResult(Nil,false)
+      }
+    case _ => ParseResult(Nil,false)
+  }
+  
+  def _var(input:List[Token]):ParseResult = input match {
+    case Token("var","reservada") :: declaracoes => _vars(declaracoes)
+    case _ => ParseResult(Nil,false)
+  }
+  def _vars(input:List[Token]):ParseResult = input match {
+    case Token(_,"identificador") :: Token(":",_) :: Token(_,"tipo") ::
+         Token(";","controle") :: rest =>
+           rest match {
+             case Token(_,"identificador") :: continua => _vars(rest)
+             case _ => ParseResult(rest,true)
+           }
+    case Token(_,"identificador") :: Token(",","controle") :: rest=> _vars(rest)
+    case Nil =>
+      parseError("Declaração de variável")
+    case rest => 
+      parseError("Declaração de variável incorreta em \""+
+          rest.take(3).foldLeft(""){ (acc,t) => t match {case Token(v,_) => acc+v }}
+      +"\"")
+  }
+  
+
+  
+}
\ No newline at end of file
diff --git a/src/main/scala/semantico/Expr.scala b/src/main/scala/semantico/Expr.scala
new file mode 100644
index 0000000..98bde06
--- /dev/null
+++ b/src/main/scala/semantico/Expr.scala
@@ -0,0 +1 @@
+package semantico
diff --git a/src/main/scala/semantico/TestCasos.scala b/src/main/scala/semantico/TestCasos.scala
new file mode 100644
index 0000000..019fd36
--- /dev/null
+++ b/src/main/scala/semantico/TestCasos.scala
@@ -0,0 +1,31 @@
+package semantico
+
+object TestCasos {
+  
+  def main(args:Array[String]) {
+    println("Test 1(program): " + test1)
+    println("Test 2(var): " + test2)
+  }
+  
+  def test1:Boolean = {
+    val casos = new AnyRef with Casos
+    val input = lexer.Lexer.getTokens("program myProgram23(input,output);".toList);
+    val parseResult = casos._program(input)
+    parseResult.aceita
+  }
+  
+  def test2:Boolean = {
+    val casos = new AnyRef with Casos
+    val input = lexer.Lexer.getTokens(
+"""
+var
+  a,b:integer;
+  c33:integer; c1,c2,c3,c4 ,v4,b5:integer;
+  c33 , a23 :integer;
+begin
+  lala
+end.""".toList);
+    val parseResult = casos._var(input)
+    parseResult.aceita
+  }
+}
\ No newline at end of file
-- 
GitLab