From e787d7168fc2b05a0eb54e9b93a2975742e0a2f0 Mon Sep 17 00:00:00 2001 From: Barf-Vader <47476490+Barf-Vader@users.noreply.github.com> Date: Thu, 6 Feb 2025 16:59:04 +0000 Subject: [PATCH] refactor: implemented labelAndExplain(), combining the two, and provided explanations for expr Co-authored-by: gc1523 --- src/main/wacc/parser.scala | 57 +++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/main/wacc/parser.scala b/src/main/wacc/parser.scala index f4c0293..609af07 100644 --- a/src/main/wacc/parser.scala +++ b/src/main/wacc/parser.scala @@ -10,11 +10,42 @@ import parsley.syntax.zipped._ import parsley.cats.combinator.{some} import cats.data.NonEmptyList + object parser { import lexer.implicits.implicitSymbol import lexer.{ident, integer, charLit, stringLit, negateCheck} import ast._ + //error extensions + extension [A](p: Parsley[A]) { + + //combines label and explain together into one function call + def labelAndExplain(label: String, explanation: String): Parsley[A] = { + p.label(label).explain(explanation) + } + def labelAndExplain(t: LabelType): Parsley[A] = { + t match { + case LabelType.Expr => + labelWithType(t).explain( + "a valid expression can start with: null, literals, identifiers, unary operators, or parentheses. " + + "Expressions can also contain array indexing and binary operators. " + + "Pair extraction is not allowed in expressions, only in assignments.") + case _ => labelWithType(t) + } + } + + def labelWithType(t: LabelType): Parsley[A] = { + t match { + case LabelType.Expr => p.label("valid expression") + case LabelType.Pair => p.label("valid pair") + } + } + } + + enum LabelType: + case Expr + case Pair + def parse(input: String): Result[String, Program] = parser.parse(input) private val parser = lexer.fully(``) @@ -77,7 +108,7 @@ object parser { private lazy val `` = (`` <**> (`` identity)) | `` ~> ((`` <**> ``.explain( - "for a pair to contain a pair type, it must be an array or erased pair" + "non-erased pair types cannot be nested" )) UntypedPairType) // TODO: better explanation here? // Statements @@ -89,7 +120,7 @@ object parser { ) private lazy val `` = (sepBy(``, ",") <~ ")" <~ "is" <~> ``.guardAgainst { - case stmts if !stmts.isReturning => Seq("All functions must end in a returning statement") + case stmts if !stmts.isReturning => Seq("all functions must end in a returning statement") } <~ "end") map { (params, stmt) => (FuncDecl((_: Type), (_: Ident), params, stmt)).tupled } @@ -103,19 +134,19 @@ object parser { private lazy val `` = (Skip from "skip") | Read("read" ~> ``) - | Free("free" ~> ``.label("a valid expression")) - | Return("return" ~> ``.label("a valid expression")) - | Exit("exit" ~> ``.label("a valid expression")) - | Print("print" ~> ``.label("a valid expression"), pure(false)) - | Print("println" ~> ``.label("a valid expression"), pure(true)) + | Free("free" ~> ``.labelAndExplain(LabelType.Expr)) + | Return("return" ~> ``.labelAndExplain(LabelType.Expr)) + | Exit("exit" ~> ``.labelAndExplain(LabelType.Expr)) + | Print("print" ~> ``.labelAndExplain(LabelType.Expr), pure(false)) + | Print("println" ~> ``.labelAndExplain(LabelType.Expr), pure(true)) | If( - "if" ~> ``.label("a valid expression") <~ "then", + "if" ~> ``.labelWithType(LabelType.Expr) <~ "then", `` <~ "else", `` <~ "fi" ) - | While("while" ~> ``.label("a valid expression") <~ "do", `` <~ "done") + | While("while" ~> ``.labelWithType(LabelType.Expr) <~ "do", `` <~ "done") | Block("begin" ~> `` <~ "end") - | VarDecl(``, `` <~ "=", ``.label("a valid initial value for variable")) + | VarDecl(``, `` <~ "=", ``.label("valid initial value for variable")) // TODO: Can we inline the name of the variable in the message | Assign(`` <~ "=", ``) private lazy val ``: Parsley[LValue] = @@ -130,10 +161,10 @@ object parser { Call( "call" ~> `` <~ "(", sepBy(``, ",") <~ ")" - ) | ``.label("valid expression") + ) | ``.labelWithType(LabelType.Expr) private lazy val `` = - Fst("fst" ~> ``.label("a valid pair")) - | Snd("snd" ~> ``.label("a valid pair")) + Fst("fst" ~> ``.label("valid pair")) + | Snd("snd" ~> ``.label("valid pair")) private lazy val `` = ArrayLiter( "[" ~> sepBy(``, ",") <~ "]" )