Merge branch 'master' into 'scaladocs'
# Conflicts: # src/main/wacc/parser.scala
This commit is contained in:
commit
c92ae5a707
@ -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>`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user