refactor: fMap to replace fOption, fList and fNonEmptyList

This commit is contained in:
2025-03-13 14:03:53 +00:00
parent 0497dd34a0
commit 67e85688b2

View File

@@ -10,11 +10,13 @@ import parsley.errors.combinator._
import parsley.errors.patterns.VerifiedErrors
import parsley.syntax.zipped._
import parsley.cats.combinator.{some, sepBy1}
import cats.syntax.all._
import cats.data.NonEmptyList
import parsley.errors.DefaultErrorBuilder
import parsley.errors.ErrorBuilder
import parsley.errors.tokenextractors.LexToken
import parsley.expr.GOps
import cats.Functor
object parser {
import lexer.implicits.implicitSymbol
@@ -62,17 +64,11 @@ object parser {
private def fParsley[A](p: Parsley[A]): FParsley[A] =
p map { a => file => a }
private def fList[A](p: Parsley[List[File => A]]): FParsley[List[A]] =
p map { l => file => l.map(_(file)) }
private def fNonEmptyList[A](p: Parsley[NonEmptyList[File => A]]): FParsley[NonEmptyList[A]] =
p map { l => file => l.map(_(file)) }
private def fPair[A, B](p: Parsley[(File => A, File => B)]): FParsley[(A, B)] =
p map { case (a, b) => file => (a(file), b(file)) }
private def fOption[A](p: Parsley[Option[File => A]]): FParsley[Option[A]] =
p map { l => file => l.map(_(file)) }
private def fMap[A, F[_]: Functor](p: Parsley[F[File => A]]): FParsley[F[A]] =
p map { funcs => file => funcs.map(_(file)) }
// Expressions
private lazy val `<expr>`: FParsley[Expr] = precedence {
@@ -118,7 +114,7 @@ object parser {
(`<ident>` <~ ("(".verifiedExplain(
"functions can only be called using 'call' keyword"
) | unit)) <**> (`<array-indices>` </> identity)
private lazy val `<array-indices>` = ArrayElem(fNonEmptyList(some("[" ~> `<expr>` <~ "]")))
private lazy val `<array-indices>` = ArrayElem(fMap(some("[" ~> `<expr>` <~ "]")))
// Types
private lazy val `<type>`: FParsley[Type] =
@@ -148,21 +144,21 @@ object parser {
concern.
*/
private lazy val `<partial-program>` = PartialProgram(
fList(many(`<import>`)),
fMap(many(`<import>`)),
`<program>`
)
private lazy val `<import>` = Import(
"import" ~> `<import-filename>`,
"(" ~> fNonEmptyList(sepBy1(`<imported-func>`, ",")) <~ ")"
"(" ~> fMap(sepBy1(`<imported-func>`, ",")) <~ ")"
)
private lazy val `<import-filename>` = `<str-liter>`.label("import file name")
private lazy val `<imported-func>` = ImportedFunc(
`<ident>`.label("imported function name"),
fOption(option("as" ~> `<ident>`)).label("imported function alias")
fMap(option("as" ~> `<ident>`)).label("imported function alias")
)
private lazy val `<program>` = Program(
"begin" ~> (
fList(
fMap(
many(
fPair(
atomic(
@@ -180,7 +176,7 @@ object parser {
private lazy val `<partial-func-decl>` =
FuncDecl(
fPair(
(fList(sepBy(`<param>`, ",")) <~ ")" <~ "is") <~>
(fMap(sepBy(`<param>`, ",")) <~ ")" <~ "is") <~>
(`<stmt>`.guardAgainst {
// TODO: passing in an arbitrary file works but is ugly
case stmts if !(stmts(File("."))).isReturning =>
@@ -190,7 +186,7 @@ object parser {
)
private lazy val `<param>` = Param(`<type>`, `<ident>`)
private lazy val `<stmt>`: FParsley[NonEmptyList[Stmt]] =
fNonEmptyList(
fMap(
(
`<basic-stmt>`.label("main program body"),
(many(";" ~> `<basic-stmt>`.label("statement after ';'"))) </> Nil
@@ -239,13 +235,13 @@ object parser {
`<pair-elem>` |
Call(
"call" ~> `<ident>` <~ "(",
fList(sepBy(`<expr>`, ",")) <~ ")"
fMap(sepBy(`<expr>`, ",")) <~ ")"
) | `<expr>`.labelWithType(LabelType.Expr)
private lazy val `<pair-elem>` =
Fst("fst" ~> `<lvalue>`.label("valid pair"))
| Snd("snd" ~> `<lvalue>`.label("valid pair"))
private lazy val `<array-liter>` = ArrayLiter(
"[" ~> fList(sepBy(`<expr>`, ",")) <~ "]"
"[" ~> fMap(sepBy(`<expr>`, ",")) <~ "]"
)
extension (stmts: NonEmptyList[Stmt]) {