从用Scala解析器组合编写的解析器中返回有意义的错误消息
-
08-10-2019 - |
题
我尝试使用解析器组合器在Scala中编写解析器。如果我递归匹配,
def body: Parser[Body] =
("begin" ~> statementList ) ^^ {
case s => { new Body(s); }
}
def statementList : Parser[List[Statement]] =
("end" ^^ { _ => List() } )|
(statement ~ statementList ^^ { case statement ~ statementList => statement :: statementList })
然后,每当语句中有故障时,我会得到很好的错误。但是,这是丑陋的长密码。所以我想写这个:
def body: Parser[Body] =
("begin" ~> statementList <~ "end" ) ^^ {
case s => { new Body(s); }
}
def statementList : Parser[List[Statement]] =
rep(statement)
该代码有效,但仅在第一个语句中存在错误时才打印有意义的消息。如果是在以后的陈述中,则该消息将变得痛苦地无法使用,因为解析器希望看到整个错误的陈述被“ end”代币取代:
Exception in thread "main" java.lang.RuntimeException: [4.2] error: "end" expected but "let" found
let b : string = x(3,b,"WHAT???",!ERRORHERE!,7 )
^
我的问题:有没有办法获得 代表 和 repsep 与有意义的错误消息结合使用,将镜片放在正确的位置而不是重复片段的开始?
解决方案 2
啊,找到了解决方案!事实证明,您需要使用主解析器上的功能短语来返回一个新解析器 不太愿意追踪。 (我想知道这到底是什么意思,也许,如果发现一条线路破裂,它将不会追踪?) 跟踪发生故障的最后一个位置。
更改:
def parseCode(code: String): Program = {
program(new lexical.Scanner(code)) match {
case Success(program, _) => program
case x: Failure => throw new RuntimeException(x.toString())
case x: Error => throw new RuntimeException(x.toString())
}
}
def program : Parser[Program] ...
进入:
def parseCode(code: String): Program = {
phrase(program)(new lexical.Scanner(code)) match {
case Success(program, _) => program
case x: Failure => throw new RuntimeException(x.toString())
case x: Error => throw new RuntimeException(x.toString())
}
}
def program : Parser[Program] ...
其他提示
您可以通过组合“自制”来做到这一点 rep
具有非背带的方法内部语句。例如:
scala> object X extends RegexParsers {
| def myrep[T](p: => Parser[T]): Parser[List[T]] = p ~! myrep(p) ^^ { case x ~ xs => x :: xs } | success(List())
| def t1 = "this" ~ "is" ~ "war"
| def t2 = "this" ~! "is" ~ "war"
| def t3 = "begin" ~ rep(t1) ~ "end"
| def t4 = "begin" ~ myrep(t2) ~ "end"
| }
defined module X
scala> X.parse(X.t4, "begin this is war this is hell end")
res13: X.ParseResult[X.~[X.~[String,List[X.~[X.~[String,String],String]]],String]] =
[1.27] error: `war' expected but ` ' found
begin this is war this is hell end
^
scala> X.parse(X.t3, "begin this is war this is hell end")
res14: X.ParseResult[X.~[X.~[String,List[X.~[X.~[String,String],String]]],String]] =
[1.19] failure: `end' expected but ` ' found
begin this is war this is hell end
^
不隶属于 StackOverflow