繁体   English   中英

Scala解析器和组合器:java.lang.RuntimeException:字符串匹配正则表达式“ \\ z”

[英]Scala Parser and combinators: java.lang.RuntimeException: string matching regex `\z' expected

作为我的硕士论文的一部分,我正在尝试使用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)

此外,如果我直接调用“和”解析器而不是“公式”解析器,则它可以正常工作。 因此,问题似乎出在这一行:

def formula: Parser[Formula] = literal | and

因为它试图将整行解析为单个文字。 然后,它可以正确地解析present(A),但不会失败于“&”(不是文字解析器的一部分)并返回解析为“和”项,但会失败,并带有异常。

我不能因为...的热爱而已。明白为什么它会尝试完全匹配任何'\\ z'。 它没有包含在我的语法中,即使是-也不应该失败并尝试将其解析为下一个术语,而不是异常退出吗? 我认为存在一些我不知道的针对字符串结尾术语的内置功能,而认为存在某些显而易见的东西让我感到困惑。

迫切需要任何帮助,非常感谢,并在此先感谢您。

丹·特鲁(Dan True)

我将为命题公式添加一个类似的解析器。 也许这可能对您有帮助。

'+'=顶/真

'-'=底/假

'!' =否定

'&'=连词

'|' =析取

'>'=含义

'<'=等价

object FormulaParser extends StandardTokenParsers with PackratParsers {
  //Symbols for all connectives
  private val parseSymbols = List("(", ")", "+", "-", "!", "&", "|", ">", "<")
  lexical.delimiters ++= parseSymbols

  private lazy val formula: PackratParser[Formula] = implication | equivalence | conjunction | disjunction | term
  private lazy val formulaWithoutBrackets: PackratParser[Formula] = implication | equivalence | conjunction | disjunction | termWithoutBrackets

  private lazy val term: PackratParser[Formula] = top | bottom | variable | parens | negation
  private lazy val termWithoutBrackets = top | bottom | variable | negation

  private lazy val top: PackratParser[Formula] = "+" ^^^ { Top() }
  private lazy val bottom: PackratParser[Formula] = "-" ^^^ { Bottom() }
  private lazy val variable: PackratParser[Formula] = ident ^^ { Variable(_) }
  private lazy val parens: PackratParser[Formula] = "(" ~> formulaWithoutBrackets <~ ")"
  private lazy val negation: PackratParser[Formula] = "!" ~> term ^^ { Negation(_) }

  private lazy val conjunction: PackratParser[Formula] = term ~ "&" ~ term ~ rep("&" ~> term) ^^ {
    case p ~ "&" ~ q ~ conj => conj.foldLeft(Conjunction(p,q))((con, elem) => Conjunction(con, elem))
  }

  private lazy val disjunction: PackratParser[Formula] = term ~ "|" ~ term ~ rep("|" ~> term) ^^ {
    case p ~ "|" ~ q ~ disj => disj.foldLeft(Disjunction(p,q))((dis, elem) => Disjunction(dis, elem))
  }

  private lazy val implication: PackratParser[Formula] = (conjunction | disjunction | term) ~ ">" ~ (conjunction | disjunction | term) ^^ { case p ~ ">" ~ q => Implication(p, q) }

  private lazy val equivalence: PackratParser[Formula] = (conjunction | disjunction | term) ~ "<" ~ (conjunction | disjunction | term) ^^ { case p ~ "<" ~ q => Equivalence(p, q) }
}

这样,您可以解析输入: (p & q) | (!q > (r & s)) (p & q) | (!q > (r & s))

在这里,合取和析取也比蕴涵和等效具有更强的约束力。

p & q > r | s p & q > r | s将导致Implication(Conjunction(Variable(p), Variable(q)), Disjunction(Variable(r), Variable(s)))

好。 如果仅仅是由于左递归,我有一个类似的解析器,在这里我解决了。

您必须更改以下内容:

def and: Parser[Formula] = literal~conjOp~literal~rep(conjOp ~> literal) ^^ {
  case p ~ conjOp ~ q ~ conj => conj.foldLeft(Conjunction(p,q))(Conjunction(_, _))
}
def formula: Parser[Formula] = and | literal

由于最后只有通过Conjunction连接的Literals ,您可以重写and按此进行操作。

代码稍微复杂一点的示例:

input: p(A,B) & ~p(B) & p(C)
result: Conjunction(Conjunction(Atom(p(A,B)),NotAtom(Atom(p(B)))),Atom(p(C)))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM