refactor: further commenting to the parser

This commit is contained in:
Guy C 2025-02-07 16:13:50 +00:00
parent d0324518b6
commit 09036040d6

View File

@ -73,6 +73,7 @@ object parser {
SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +: SOps(InfixL)(Mul from "*", Div from "/", Mod from "%") +:
SOps(Prefix)( SOps(Prefix)(
Not from "!", Not from "!",
// notFollowedBy(negateCheck) ensures that negative numbers are parsed as a single int literal
(Negate from (notFollowedBy(negateCheck) ~> "-")).hide, (Negate from (notFollowedBy(negateCheck) ~> "-")).hide,
Len from "len", Len from "len",
Ord from "ord", Ord from "ord",
@ -114,7 +115,16 @@ object parser {
((`<pair-elems-type>` <**> `<array-type>`) ((`<pair-elems-type>` <**> `<array-type>`)
.map(arr => (_: UntypedPairType) => arr) </> identity)) .map(arr => (_: UntypedPairType) => arr) </> identity))
// Statements /** Statements
*
* Atomic is used in two places here:
* 1. Atomic for function return type - code may be a variable declaration instead, If we were
* to factor out the type, the resulting code would be rather messy. It can only fail once
* in the entire program so it creates minimal overhead.
* 2. Atomic for function missing return type check - there is no easy way around an explicit
* invalid syntax check, this only happens at most once per program so this is not a major
* concern.
*/
private lazy val `<program>` = Program( private lazy val `<program>` = Program(
"begin" ~> many( "begin" ~> many(
atomic(`<type>`.label("function declaration") <~> `<ident>` <~ "(") <**> `<partial-func-decl>` atomic(`<type>`.label("function declaration") <~> `<ident>` <~ "(") <**> `<partial-func-decl>`
@ -175,6 +185,13 @@ object parser {
) )
extension (stmts: NonEmptyList[Stmt]) { extension (stmts: NonEmptyList[Stmt]) {
/** Determines whether a function body is guaranteed to return in all cases This is required as
* all functions must end via a "return" or "exit" statement
*
* @return
* true if the statement list ends in a return statement, false otherwise
*/
def isReturning: Boolean = stmts.last match { def isReturning: Boolean = stmts.last match {
case Return(_) | Exit(_) => true case Return(_) | Exit(_) => true
case If(_, thenStmt, elseStmt) => thenStmt.isReturning && elseStmt.isReturning case If(_, thenStmt, elseStmt) => thenStmt.isReturning && elseStmt.isReturning