feat: imports parser

This commit is contained in:
2025-03-13 08:18:44 +00:00
parent 905a5e5b61
commit e881b736f8
3 changed files with 32 additions and 6 deletions

View File

@@ -72,7 +72,7 @@ def frontend(
): Either[NonEmptyList[Error], microWacc.Program] = ): Either[NonEmptyList[Error], microWacc.Program] =
parser.parse(contents) match { parser.parse(contents) match {
case Failure(msg) => Left(NonEmptyList.one(Error.SyntaxError(msg))) case Failure(msg) => Left(NonEmptyList.one(Error.SyntaxError(msg)))
case Success(prog) => case Success(ast.PartialProgram(_, prog)) =>
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
val (names, funcs) = renamer.rename(prog) val (names, funcs) = renamer.rename(prog)

View File

@@ -131,6 +131,18 @@ object ast {
/* ============================ PROGRAM STRUCTURE ============================ */ /* ============================ PROGRAM STRUCTURE ============================ */
case class ImportedFunc(sourceName: Ident, importName: Ident)(val pos: Position)
object ImportedFunc extends ParserBridgePos2[Ident, Option[Ident], ImportedFunc] {
def apply(a: Ident, b: Option[Ident])(pos: Position): ImportedFunc =
new ImportedFunc(a, b.getOrElse(a))(pos)
}
case class Import(source: StrLiter, funcs: NonEmptyList[ImportedFunc])(val pos: Position)
object Import extends ParserBridgePos2[StrLiter, NonEmptyList[ImportedFunc], Import]
case class PartialProgram(imports: List[Import], self: Program)(val pos: Position)
object PartialProgram extends ParserBridgePos2[List[Import], Program, PartialProgram]
case class Program(funcs: List[FuncDecl], main: NonEmptyList[Stmt])(val pos: Position) case class Program(funcs: List[FuncDecl], main: NonEmptyList[Stmt])(val pos: Position)
object Program extends ParserBridgePos2[List[FuncDecl], NonEmptyList[Stmt], Program] object Program extends ParserBridgePos2[List[FuncDecl], NonEmptyList[Stmt], Program]

View File

@@ -3,12 +3,12 @@ package wacc
import parsley.Result import parsley.Result
import parsley.Parsley import parsley.Parsley
import parsley.Parsley.{atomic, many, notFollowedBy, pure, unit} import parsley.Parsley.{atomic, many, notFollowedBy, pure, unit}
import parsley.combinator.{countSome, sepBy} import parsley.combinator.{countSome, sepBy, option}
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.errors.patterns.VerifiedErrors
import parsley.syntax.zipped._ import parsley.syntax.zipped._
import parsley.cats.combinator.{some} import parsley.cats.combinator.{some, sepBy1}
import cats.data.NonEmptyList import cats.data.NonEmptyList
import parsley.errors.DefaultErrorBuilder import parsley.errors.DefaultErrorBuilder
import parsley.errors.ErrorBuilder import parsley.errors.ErrorBuilder
@@ -52,8 +52,8 @@ object parser {
implicit val builder: ErrorBuilder[String] = new DefaultErrorBuilder with LexToken { implicit val builder: ErrorBuilder[String] = new DefaultErrorBuilder with LexToken {
def tokens = errTokens def tokens = errTokens
} }
def parse(input: String): Result[String, Program] = parser.parse(input) def parse(input: String): Result[String, PartialProgram] = parser.parse(input)
private val parser = lexer.fully(`<program>`) private val parser = lexer.fully(`<partial-program>`)
// Expressions // Expressions
private lazy val `<expr>`: Parsley[Expr] = precedence { private lazy val `<expr>`: Parsley[Expr] = precedence {
@@ -87,11 +87,12 @@ object parser {
IntLiter(integer).label("integer literal"), IntLiter(integer).label("integer literal"),
BoolLiter(("true" as true) | ("false" as false)).label("boolean literal"), BoolLiter(("true" as true) | ("false" as false)).label("boolean literal"),
CharLiter(charLit).label("character literal"), CharLiter(charLit).label("character literal"),
StrLiter(stringLit).label("string literal"), `<str-liter>`.label("string literal"),
PairLiter from "null", PairLiter from "null",
`<ident-or-array-elem>`, `<ident-or-array-elem>`,
Parens("(" ~> `<expr>` <~ ")") Parens("(" ~> `<expr>` <~ ")")
) )
private val `<str-liter>` = StrLiter(stringLit)
private val `<ident>` = private val `<ident>` =
Ident(ident) | some("*" | "&").verifiedExplain("pointer operators are not allowed") Ident(ident) | some("*" | "&").verifiedExplain("pointer operators are not allowed")
private lazy val `<ident-or-array-elem>` = private lazy val `<ident-or-array-elem>` =
@@ -127,6 +128,19 @@ object parser {
invalid syntax check, this only happens at most once per program so this is not a major invalid syntax check, this only happens at most once per program so this is not a major
concern. concern.
*/ */
private lazy val `<partial-program>` = PartialProgram(
many(`<import>`),
`<program>`
)
private lazy val `<import>` = Import(
"import" ~> `<import-filename>`,
"(" ~> 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"),
option("as" ~> `<ident>`).label("imported function alias")
)
private lazy val `<program>` = Program( private lazy val `<program>` = Program(
"begin" ~> ( "begin" ~> (
many( many(