简体   繁体   English

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

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

I am trying to parse some text following a grammer for Dynamic Epistemic Logic using Scala's RegexParser, as part of my Master Thesis. 作为我的硕士论文的一部分,我正在尝试使用Scala的RegexParser解析动态认知逻辑的语法之后的一些文本。 But I keep getting the same error on simple logical conjunctions. 但是我在简单的逻辑连接上仍然遇到相同的错误。 I understand where and why it's failing, but not why it's matching what it is in the first place. 我了解失败的原因和原因,但不明白为什么它与最初的情况相匹配。

My Code (severely boiled down to isolate the problem): 我的代码(经过仔细研究以找出问题所在):

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)
  }
}

I am calling the DomainParser.test() function externally from java. 我从Java外部调用DomainParser.test()函数。 The input is 输入是

present(A) & ~present(B)

which should yield: 应该产生:

Conjunction(Atom(present((A))),NotAtom(Atom(present((B)))))

but instead gives me the error: 但是给了我错误:

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)

Furthermore, if I call the 'and' parser directly instead of the 'formula' parser, it works fine. 此外,如果我直接调用“和”解析器而不是“公式”解析器,则它可以正常工作。 Hence the problem seems to be with this line: 因此,问题似乎出在这一行:

def formula: Parser[Formula] = literal | and

Because it attempts to parse the whole line as a single literal. 因为它试图将整行解析为单个文字。 It then parses present(A) correctly, but instead of failing on the '&' (not part of literal's parser) and returning to parse as an 'and'-term, it fails with the exception. 然后,它可以正确地解析present(A),但不会失败于“&”(不是文字解析器的一部分)并返回解析为“和”项,但会失败,并带有异常。

I cannot for the love of... see why it tries to match any '\\z' at all. 我不能因为...的热爱而已。明白为什么它会尝试完全匹配任何'\\ z'。 It is not included in the grammar by me, and even if it was - shouldn't it fail and try to parse as the next term instead of exiting with an exception? 它没有包含在我的语法中,即使是-也不应该失败并尝试将其解析为下一个术语,而不是异常退出吗? I am torn between thinking there is some in-built functionality for end-of-string terms that I do not know, to thinking there is something hugely obvious staring me in the face. 我认为存在一些我不知道的针对字符串结尾术语的内置功能,而认为存在某些显而易见的东西让我感到困惑。

Any help would be sorely needed, very welcome and thank you very much in advance. 迫切需要任何帮助,非常感谢,并在此先感谢您。

Dan True 丹·特鲁(Dan True)

I'll just add a similar Parser for propositional formulas I made. 我将为命题公式添加一个类似的解析器。 Maybe this might help you. 也许这可能对您有帮助。

'+' = top/true '+'=顶/真

'-' = bottom/false '-'=底/假

'!' '!' = negation =否定

'&' = conjunction '&'=连词

'|' '|' = disjunction =析取

'>' = implication '>'=含义

'<' = equivalence '<'=等价

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) }
}

With this you can parse input like: (p & q) | (!q > (r & s)) 这样,您可以解析输入: (p & q) | (!q > (r & s)) (p & q) | (!q > (r & s))

Here Conjunction and Disjunction also bind stronger than Implication and Equivalence. 在这里,合取和析取也比蕴涵和等效具有更强的约束力。

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

Ok. 好。 If it's just due to the left-recursion I have a similar parser, where I resolved that. 如果仅仅是由于左递归,我有一个类似的解析器,在这里我解决了。

You have to change the following: 您必须更改以下内容:

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

Since in the end there are only Literals connected via Conjunction , you can rewrite and like that. 由于最后只有通过Conjunction连接的Literals ,您可以重写and按此进行操作。

Slightly more complex example with your code: 代码稍微复杂一点的示例:

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