package wacc import parsley.Result import parsley.Parsley import parsley.Parsley.{atomic, many, pure} import parsley.combinator.{countSome, sepBy} import parsley.expr.{precedence, SOps, InfixL, InfixN, InfixR, Prefix, Atoms} import parsley.cats.combinator.{sepBy1, some} import cats.data.NonEmptyList object parser { import lexer.implicits.implicitSymbol import lexer.{ident, integer, charLit, stringLit} import ast._ def parse(input: String): Result[String, Program] = parser.parse(input) private val parser = lexer.fully(``) // Expressions private lazy val ``: Parsley[Expr] = precedence { SOps(InfixR)(Or from "||") +: SOps(InfixR)(And from "&&") +: SOps(InfixN)(Eq from "==", Neq from "!=") +: SOps(InfixN)( Less from "<", LessEq from "<=", Greater from ">", GreaterEq from ">=" ) +: SOps(InfixL)(Add from "+", Sub from "-") +: SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +: SOps(Prefix)( Not from "!", Negate from "-", Len from "len", Ord from "ord", Chr from "chr" ) +: `` } // Atoms private lazy val ``: Atoms[Expr6] = Atoms( IntLiter(integer), BoolLiter(("true" as true) | ("false" as false)), CharLiter(charLit), StrLiter(stringLit), PairLiter from "null", ``, Parens("(" ~> `` <~ ")") ) private val `` = Ident(ident) private lazy val `` = `` <**> (`` identity) private val `` = some("[" ~> `` <~ "]") map { indices => ArrayElem((_: Ident), indices) } // Types private lazy val ``: Parsley[Type] = (`` | (`` ~> ``)) <**> (`` identity) private val `` = (IntType from "int") | (BoolType from "bool") | (CharType from "char") | (StringType from "string") private lazy val `` = countSome("[" ~> "]") map { cnt => ArrayType((_: Type), cnt) } private val `` = "pair" private val ``: Parsley[PairType] = PairType( "(" ~> `` <~ ",", `` <~ ")" ) private lazy val `` = (`` <**> (`` identity)) | `` ~> ((`` <**> ``) UntypedPairType) // Statements private lazy val `` = Program( "begin" ~> many(atomic(``)), `` <~ "end" ) private lazy val `` = FuncDecl( ``, `` <~ "(", sepBy(``, ",") <~ ")" <~ "is", `` <~ "end" ) private lazy val `` = Param(``, ``) private lazy val ``: Parsley[NonEmptyList[Stmt]] = sepBy1(``, ";") private lazy val `` = (Skip from atomic("skip")) | Read(atomic("read") ~> ``) | Free(atomic("free") ~> ``) | Return(atomic("return") ~> ``) | Exit(atomic("exit") ~> ``) | Print(atomic("print") ~> ``, pure(false)) | Print(atomic("println") ~> ``, pure(true)) | If( atomic("if") ~> `` <~ "then", `` <~ "else", `` <~ "fi" ) | While(atomic("while") ~> `` <~ "do", `` <~ "done") | Block(atomic("begin") ~> `` <~ "end") | VarDecl(atomic(``), `` <~ "=", ``) | Assign(`` <~ "=", ``) private lazy val ``: Parsley[LValue] = atomic(``) | atomic(``) private lazy val ``: Parsley[RValue] = atomic(``) | atomic( NewPair( "newpair" ~> "(" ~> `` <~ ",", `` <~ ")" ) ) | atomic(``) | atomic( Call( "call" ~> `` <~ "(", sepBy(``, ",") <~ ")" ) ) | `` private lazy val `` = Fst("fst" ~> ``) | Snd("snd" ~> ``) private lazy val `` = ArrayLiter( "[" ~> sepBy(``, ",") <~ "]" ) }