Merge branch 'master' into 'scaladocs'

# Conflicts:
#   src/main/wacc/parser.scala
This commit is contained in:
Connolly, Guy 2025-02-07 16:47:59 +00:00
commit c92ae5a707

View File

@ -6,12 +6,14 @@ import parsley.Parsley.{atomic, many, notFollowedBy, pure}
import parsley.combinator.{countSome, sepBy} import parsley.combinator.{countSome, sepBy}
import parsley.expr.{precedence, SOps, InfixL, InfixN, InfixR, Prefix, Atoms} import parsley.expr.{precedence, SOps, InfixL, InfixN, InfixR, Prefix, Atoms}
import parsley.errors.combinator._ import parsley.errors.combinator._
import parsley.errors.patterns.VerifiedErrors
import parsley.syntax.zipped._ import parsley.syntax.zipped._
import parsley.cats.combinator.{some} import parsley.cats.combinator.{some}
import cats.data.NonEmptyList import cats.data.NonEmptyList
import parsley.errors.DefaultErrorBuilder import parsley.errors.DefaultErrorBuilder
import parsley.errors.ErrorBuilder import parsley.errors.ErrorBuilder
import parsley.errors.tokenextractors.LexToken import parsley.errors.tokenextractors.LexToken
import parsley.character.char
object parser { object parser {
import lexer.implicits.implicitSymbol import lexer.implicits.implicitSymbol
@ -48,7 +50,9 @@ object parser {
case Expr case Expr
case Pair case Pair
// Lexer-backed errorBuilder val _parensCheck =
char('(').verifiedExplain("functions can only be called using 'call' keyword")
implicit val builder: ErrorBuilder[String] = new DefaultErrorBuilder with LexToken { implicit val builder: ErrorBuilder[String] = new DefaultErrorBuilder with LexToken {
def tokens = errTokens def tokens = errTokens
} }
@ -67,8 +71,8 @@ object parser {
GreaterEq from ">=" GreaterEq from ">="
) +: ) +:
SOps(InfixL)( SOps(InfixL)(
(Add from "+").label("binary operator"), ((Add from "+").label("binary operator") | _parensCheck),
(Sub from "-").label("binary operator") ((Sub from "-").label("binary operator") | _parensCheck)
) +: ) +:
SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +: SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +:
SOps(Prefix)( SOps(Prefix)(
@ -92,7 +96,8 @@ object parser {
`<ident-or-array-elem>`, `<ident-or-array-elem>`,
Parens("(" ~> `<expr>` <~ ")") Parens("(" ~> `<expr>` <~ ")")
) )
private val `<ident>` = Ident(ident) private val `<ident>` =
Ident(ident) | some("*" | "&").verifiedExplain("pointer operators are not allowed")
private lazy val `<ident-or-array-elem>` = private lazy val `<ident-or-array-elem>` =
`<ident>` <**> (`<array-indices>` </> identity) `<ident>` <**> (`<array-indices>` </> identity)
private val `<array-indices>` = ArrayElem(some("[" ~> `<expr>` <~ "]")) private val `<array-indices>` = ArrayElem(some("[" ~> `<expr>` <~ "]"))
@ -125,18 +130,23 @@ object parser {
concern. concern.
*/ */
private lazy val `<program>` = Program( private lazy val `<program>` = Program(
"begin" ~> many( "begin" ~> (
atomic(`<type>`.label("function declaration") <~> `<ident>` <~ "(") <**> `<partial-func-decl>` many(
).label("function declaration"), atomic(
(atomic(`<ident>` <~ "(") ~> fail("function is missing return type") | `<stmt>`.label( `<type>`.label("function declaration") <~> `<ident>` <~ "("
) <**> `<partial-func-decl>`
).label("function declaration") |
atomic(`<ident>` <~ "(").verifiedExplain("function declaration is missing return type")
),
`<stmt>`.label(
"main program body" "main program body"
)) <~ "end" ) <~ "end"
) )
private lazy val `<partial-func-decl>` = private lazy val `<partial-func-decl>` =
FuncDecl( FuncDecl(
sepBy(`<param>`, ",") <~ ")" <~ "is", sepBy(`<param>`, ",") <~ ")" <~ "is",
`<stmt>`.guardAgainst { `<stmt>`.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" } <~ "end"
) )
private lazy val `<param>` = Param(`<type>`, `<ident>`) private lazy val `<param>` = Param(`<type>`, `<ident>`)
@ -161,7 +171,14 @@ object parser {
) )
| While("while" ~> `<expr>`.labelWithType(LabelType.Expr) <~ "do", `<stmt>` <~ "done") | While("while" ~> `<expr>`.labelWithType(LabelType.Expr) <~ "do", `<stmt>` <~ "done")
| Block("begin" ~> `<stmt>` <~ "end") | Block("begin" ~> `<stmt>` <~ "end")
| VarDecl(`<type>`, `<ident>` <~ "=", `<rvalue>`) | VarDecl(
`<type>`,
`<ident>` <~ ("=" | "(".verifiedExplain(
"all function declarations must be above the main program body"
)),
`<rvalue>`.label("valid initial value for variable")
)
// TODO: Can we inline the name of the variable in the message
| Assign(`<lvalue>` <~ "=", `<rvalue>`) | Assign(`<lvalue>` <~ "=", `<rvalue>`)
private lazy val `<lvalue>`: Parsley[LValue] = private lazy val `<lvalue>`: Parsley[LValue] =
`<pair-elem>` | `<ident-or-array-elem>` `<pair-elem>` | `<ident-or-array-elem>`