From a65cc018152379e0f8c4cff861e13d4d745c3409 Mon Sep 17 00:00:00 2001 From: Barf-Vader <47476490+Barf-Vader@users.noreply.github.com> Date: Fri, 7 Feb 2025 01:35:16 +0000 Subject: [PATCH] fix: added error messages for functions missing type, and late function decls --- src/main/wacc/lexer.scala | 7 ++++--- src/main/wacc/parser.scala | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/wacc/lexer.scala b/src/main/wacc/lexer.scala index 7a85dae..8aa4607 100644 --- a/src/main/wacc/lexer.scala +++ b/src/main/wacc/lexer.scala @@ -33,7 +33,7 @@ val errConfig = new ErrorConfig { "false" -> Label("boolean literal"), "true" -> Label("boolean literal"), "=" -> Label("assignment"), - "[" -> Label("array index") + "[" -> Label("array index"), ) } object lexer { @@ -85,9 +85,10 @@ object lexer { val errTokens = Seq( lexer.nonlexeme.names.identifier.map(v => s"identifier $v"), lexer.nonlexeme.integer.decimal32[Int].map(n => s"integer $n"), - lexer.nonlexeme.character.ascii.map(c => s"character literal \'$c\'"), + (lexer.nonlexeme.character.ascii).map(c => s"character literal \'$c\'"), lexer.nonlexeme.string.ascii.map(s => s"string literal \"$s\""), - character.whitespace.map(_ => "") +// lexer.nonlexeme.symbol("()").as("function call, bruh use keyword 'call' to call functions"), + character.whitespace.map(_ => ""), ) ++ desc.symbolDesc.hardKeywords.map { k => lexer.nonlexeme.symbol(k).as(s"keyword $k") } diff --git a/src/main/wacc/parser.scala b/src/main/wacc/parser.scala index 247ae31..654d21b 100644 --- a/src/main/wacc/parser.scala +++ b/src/main/wacc/parser.scala @@ -12,6 +12,8 @@ import cats.data.NonEmptyList import parsley.errors.DefaultErrorBuilder import parsley.errors.ErrorBuilder import parsley.errors.tokenextractors.LexToken +import parsley.errors.patterns.VerifiedErrors +import parsley.character.char object parser { import lexer.implicits.implicitSymbol @@ -48,6 +50,10 @@ object parser { case Expr case Pair + val _parensCheck = + char('(').verifiedExplain("use keyword 'call' to call functions") + + implicit val builder: ErrorBuilder[String] = new DefaultErrorBuilder with LexToken { def tokens = errTokens } @@ -66,8 +72,8 @@ object parser { GreaterEq from ">=" ) +: SOps(InfixL)( - (Add from "+").label("binary operator"), - (Sub from "-").label("binary operator") + ((Add from "+").label("binary operator") | _parensCheck), + ((Sub from "-").label("binary operator") | _parensCheck) ) +: SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +: SOps(Prefix)( @@ -117,15 +123,15 @@ object parser { // Statements private lazy val `` = Program( "begin" ~> many( - atomic(``.label("function declaration") <~> `` <~ "(") <**> `` + atomic((``.label("function declaration") <~> `` <~ "(")) <**> `` ).label("function declaration"), - ``.label("main program body") <~ "end" + ((`` <~ "(")*> fail("function is missing return type") | ``.label("main program body")) <~ "end" ) private lazy val `` = FuncDecl( - sepBy(``, ",") <~ ")" <~ "is", + sepBy(``, ",") <~ ")".label("parenthesis") <~ "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" ) private lazy val `` = Param(``, ``) @@ -150,8 +156,8 @@ object parser { ) | While("while" ~> ``.labelWithType(LabelType.Expr) <~ "do", `` <~ "done") | Block("begin" ~> `` <~ "end") - | VarDecl(``, `` <~ "=", ``.label("valid initial value for variable")) - // TODO: Can we inline the name of the variable in the message + | VarDecl(``, `` <~ "=".explain("functions must be defined on top of the main block"), + ``.label("valid initial value for variable")) | Assign(`` <~ "=", ``) private lazy val ``: Parsley[LValue] = `` | ``