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