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