【发布时间】:2014-03-06 00:30:51
【问题描述】:
作为我硕士论文的一部分,我正在尝试使用 Scala 的 RegexParser 按照动态认知逻辑的语法解析一些文本。但是我在简单的逻辑连词上总是遇到同样的错误。我知道它在哪里以及为什么会失败,但不知道为什么它首先匹配它。
我的代码(严重归结为隔离问题):
import scala.util.parsing.combinator._
class Formula() {
def and(q:Formula) = Conjunction(this, q) // ∧
}
abstract class Literal extends Formula
abstract class Constant extends Formula
case class Atom(symbol:String) extends Literal
case class NotAtom(p:Atom) extends Literal
case class Conjunction(p:Formula, q:Formula) extends Formula
class mapParser extends RegexParsers {
val conjOp = "&"
val negOp = "~"
val listseparator = ","
val leftparen = "("
val rightparen = ")"
def id:Parser[String] = "[a-z_]+".r // fluents are never capitalized. but may have underscore.
def litargs: Parser[String] = repsep("[a-zA-Z]+".r,listseparator) ^^ {case list => "(" + list.toString.stripPrefix("List") + ")"}
def atom: Parser[Atom] = id~leftparen~litargs~rightparen ^^ {case head~_~tail~_ => Atom(head+tail)}
def negAtom: Parser[NotAtom] = negOp~>atom ^^ (NotAtom(_))
def literal: Parser[Literal] = negAtom | atom
def and: Parser[Formula] = formula~conjOp~formula ^^ {case p1~_~p2 => Conjunction(p1,p2)}
def formula: Parser[Formula] = literal | and
};
object DomainParser extends mapParser {
def test() = {
val domainDesc ="present(A) & ~present(B)";
println("input: " + domainDesc)
println("result: " + apply(domainDesc))
}
def apply(domainDesc: String) = parseAll(formula, domainDesc) match {
case Success(result, _) => result
case failure : NoSuccess => scala.sys.error(failure.msg)
}
}
我正在从 java 外部调用 DomainParser.test() 函数。输入是
present(A) & ~present(B)
应该产生:
Conjunction(Atom(present((A))),NotAtom(Atom(present((B)))))
但是却给了我错误:
Exception in thread "main" java.lang.RuntimeException: string matching regex `\z' expected but `&' found
at scala.sys.package$.error(package.scala:27)
at mAp.DomainParser$.apply(DEL.scala:48)
at mAp.DomainParser$.test(DEL.scala:43)
at mAp.DomainParser.test(DEL.scala)
at ma.MA.main(MA.java:8)
此外,如果我直接调用“and”解析器而不是“formula”解析器,它可以正常工作。因此问题似乎出在这一行:
def formula: Parser[Formula] = literal | and
因为它试图将整行解析为单个文字。然后它会正确解析 present(A),但不会在 '&'(不是文字解析器的一部分)上失败并作为 'and'-term 返回解析,而是失败并出现异常。
我不能看在... 看看为什么它会尝试匹配任何 '\z'。它不包含在我的语法中,即使它是 - 它不应该失败并尝试解析为下一个术语而不是异常退出吗?我在认为有一些我不知道的字符串结尾术语的内置功能与认为有一些非常明显的东西在盯着我之间徘徊。
非常需要任何帮助,非常欢迎,并在此先感谢您。
丹真
【问题讨论】:
-
带有多个“&”的输入会是什么样子?
present(A) & ~present(B) & present(C)? -
是的。哪个(如果我正确指定了 BNF)应该希望匹配类似的内容: Conjunction(Conjunction(Atom(present((A))),NotAtom(Atom(present((B)))), (Atom(present((C )))))
-
好吧,我不是正则表达式方面的专家,但你可以看看这个帖子:stackoverflow.com/questions/1798738/… 似乎首先尝试了文字并成功,但随后
\z代表预计输入结束,但字符串的其余部分仍然是& ~present(B) -
Kigyo:是的,我后来发现了同样的问题。所以我需要找到一种方法,让 Literal regex 在后面跟着空格和分隔符时失败而不是成功。谢谢你。我看看能不能搞定。
-
解决了,但由于左递归导致堆栈溢出。我决定删除中缀符号,取而代之的是 "&(present(A), ~present(B)) 似乎工作正常。欢迎提供有关如何实现中缀运算符符号的任何提示。