feat: add option flag, greedy compilation of multiple files, and refactor to... #41

Merged
gc1523 merged 34 commits from master into intelliwacc-ide 2025-03-13 23:28:08 +00:00
30 changed files with 774 additions and 306 deletions
Showing only changes of commit 67e85688b2 - Show all commits

View File

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