feat: improved error messages
This commit is contained in:
parent
4e50ed35ba
commit
4602b75628
@ -6,7 +6,8 @@ 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.cats.combinator.{sepBy1, some}
|
import parsley.syntax.zipped._
|
||||||
|
import parsley.cats.combinator.{some}
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
|
|
||||||
object parser {
|
object parser {
|
||||||
@ -72,12 +73,12 @@ object parser {
|
|||||||
)
|
)
|
||||||
private lazy val `<pair-elem-type>` =
|
private lazy val `<pair-elem-type>` =
|
||||||
(`<base-type>` <**> (`<array-type>` </> identity)) |
|
(`<base-type>` <**> (`<array-type>` </> identity)) |
|
||||||
`<pair-type>` ~> ((`<pair-elems-type>` <**> `<array-type>`) </> UntypedPairType)
|
`<pair-type>` ~> ((`<pair-elems-type>` <**> `<array-type>`.explain("for a pair to contain a pair type, it must be an array or erased pair")) </> UntypedPairType)
|
||||||
|
// TODO: better explanation here?
|
||||||
// Statements
|
// Statements
|
||||||
private lazy val `<program>` = Program(
|
private lazy val `<program>` = Program(
|
||||||
"begin" ~> many(atomic(`<type>` <~> `<ident>` <~ "(") <**> `<partial-func-decl>`),
|
"begin" ~> many(atomic(`<type>`.label("function declaration") <~> `<ident>` <~ "(") <**> `<partial-func-decl>`).label("function declaration"),
|
||||||
`<stmt>` <~ "end"
|
`<stmt>`.label("main program body") <~ "end"
|
||||||
)
|
)
|
||||||
private lazy val `<partial-func-decl>` =
|
private lazy val `<partial-func-decl>` =
|
||||||
(sepBy(`<param>`, ",") <~ ")" <~ "is" <~> `<stmt>`.guardAgainst {
|
(sepBy(`<param>`, ",") <~ ")" <~ "is" <~> `<stmt>`.guardAgainst {
|
||||||
@ -87,23 +88,28 @@ object parser {
|
|||||||
}
|
}
|
||||||
private lazy val `<param>` = Param(`<type>`, `<ident>`)
|
private lazy val `<param>` = Param(`<type>`, `<ident>`)
|
||||||
private lazy val `<stmt>`: Parsley[NonEmptyList[Stmt]] =
|
private lazy val `<stmt>`: Parsley[NonEmptyList[Stmt]] =
|
||||||
sepBy1(`<basic-stmt>`, ";")
|
(
|
||||||
|
`<basic-stmt>`.label("main program body"),
|
||||||
|
(many(";" ~> `<basic-stmt>`.label("statement after ';'"))) </> Nil
|
||||||
|
).zipped(NonEmptyList.apply)
|
||||||
|
|
||||||
private lazy val `<basic-stmt>` =
|
private lazy val `<basic-stmt>` =
|
||||||
(Skip from "skip")
|
(Skip from "skip")
|
||||||
| Read("read" ~> `<lvalue>`)
|
| Read("read" ~> `<lvalue>`)
|
||||||
| Free("free" ~> `<expr>`)
|
| Free("free" ~> `<expr>`.label("a valid expression"))
|
||||||
| Return("return" ~> `<expr>`)
|
| Return("return" ~> `<expr>`.label("a valid expression"))
|
||||||
| Exit("exit" ~> `<expr>`)
|
| Exit("exit" ~> `<expr>`.label("a valid expression"))
|
||||||
| Print("print" ~> `<expr>`, pure(false))
|
| Print("print" ~> `<expr>`.label("a valid expression"), pure(false))
|
||||||
| Print("println" ~> `<expr>`, pure(true))
|
| Print("println" ~> `<expr>`.label("a valid expression"), pure(true))
|
||||||
| If(
|
| If(
|
||||||
"if" ~> `<expr>` <~ "then",
|
"if" ~> `<expr>`.label("a valid expression") <~ "then",
|
||||||
`<stmt>` <~ "else",
|
`<stmt>` <~ "else",
|
||||||
`<stmt>` <~ "fi"
|
`<stmt>` <~ "fi"
|
||||||
)
|
)
|
||||||
| While("while" ~> `<expr>` <~ "do", `<stmt>` <~ "done")
|
| While("while" ~> `<expr>`.label("a valid expression") <~ "do", `<stmt>` <~ "done")
|
||||||
| Block("begin" ~> `<stmt>` <~ "end")
|
| Block("begin" ~> `<stmt>` <~ "end")
|
||||||
| VarDecl(`<type>`, `<ident>` <~ "=", `<rvalue>`)
|
| VarDecl(`<type>`, `<ident>` <~ "=", `<rvalue>`.label("a 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>`
|
||||||
@ -117,9 +123,10 @@ object parser {
|
|||||||
Call(
|
Call(
|
||||||
"call" ~> `<ident>` <~ "(",
|
"call" ~> `<ident>` <~ "(",
|
||||||
sepBy(`<expr>`, ",") <~ ")"
|
sepBy(`<expr>`, ",") <~ ")"
|
||||||
) | `<expr>`
|
) | `<expr>`.label("valid expression")
|
||||||
private lazy val `<pair-elem>` =
|
private lazy val `<pair-elem>` =
|
||||||
Fst("fst" ~> `<lvalue>`) | Snd("snd" ~> `<lvalue>`)
|
Fst("fst" ~> `<lvalue>`.label("a valid pair"))
|
||||||
|
| Snd("snd" ~> `<lvalue>`.label("a valid pair"))
|
||||||
private lazy val `<array-liter>` = ArrayLiter(
|
private lazy val `<array-liter>` = ArrayLiter(
|
||||||
"[" ~> sepBy(`<expr>`, ",") <~ "]"
|
"[" ~> sepBy(`<expr>`, ",") <~ "]"
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user