package sintatico
import lexer.Atomo

abstract trait molecula

case class Program(id:String,inOut:String*) extends molecula

case class Atribuicao(id:String, op:String, expr:Expr) extends molecula
case class ChamadaFuncao(id:String,param:Parametro*) extends molecula

case class Parametro(id:String,tipo:String)

case class Numero(valor:Int) extends molecula
case class Expr() extends molecula
case class Label(id:String) extends molecula

case class ParseResult(novoInput:List[Atomo], 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[Atomo]):ParseResult = input match { //Pode ter lista de identificadores em (imput,output)
    case Atomo("program","reservada") :: Atomo(_,"identificador") :: resto =>
      resto match {
        case Atomo(";","controle") :: rest => ParseResult(rest,true)
        case Atomo("(","controle") :: Atomo(_,"identificador") :: Atomo(",","controle") :: Atomo(_,"identificador") ::
             Atomo(")","controle") :: Atomo(";","controle") :: rest 
             => ParseResult(rest,true)
        case _ => ParseResult(Nil,false)
      }
    case _ => ParseResult(Nil,false)
  }
  
  def _var(input:List[Atomo]):ParseResult = input match {
    case Atomo("var","reservada") :: declaracoes => _vars(declaracoes)
    case _ => ParseResult(Nil,false)
  }
  
  def _vars(input:List[Atomo]):ParseResult = input match {
    case Atomo(_,"identificador") :: Atomo(":",_) :: Atomo(_,"tipo") ::
         Atomo(";","controle") :: rest =>
           rest match {
             case Atomo(_,"identificador") :: continua => _vars(rest)
             case _ => ParseResult(rest,true)
           }
    case Atomo(_,"identificador") :: Atomo(",","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 Atomo(v,_) => acc+v }}
      +"\"")
  }
//  type T = Token 
//  def _expressao(input:List[Token]):ParseResult = input match {
//  
//    case T(_,"identificador") :: T(_,"(") :: _ => //function call
//      
//    case T(_,"identificador") :: _ => //variable
//      
//    case T(op,"operador") :: _ =>
//      if (op=="+" || op=="-") {
//        
//      } else {
//        parseError("Operador encontrado em local inválido.")
//      }
//  }
  

  
}