Parsing Sbt解析器因OutOfMemoryException失败

Parsing Sbt解析器因OutOfMemoryException失败,parsing,sbt,Parsing,Sbt,我有一个sbt插件,其中包含类似以下内容的解析器: package sbtpin import sbt.complete._ import DefaultParsers._ object InputParser { private lazy val dotParser: Parser[Char] = '.' private lazy val objectId = identifier(Letter, IDChar | dotParser) private lazy val ad

我有一个sbt插件,其中包含类似以下内容的解析器:

package sbtpin

import sbt.complete._
import DefaultParsers._

object InputParser {
  private lazy val dotParser: Parser[Char] = '.'
  private lazy val objectId = identifier(Letter, IDChar | dotParser)

  private lazy val addCommand1 = "add" ~> Space.+ ~> objectId ~ (Space.+ ~> NotSpace.+).? map(p => AddCommand1(p._1, p._2))
  private lazy val addCommand2 = "add -n" ~> Space.+ ~> objectId ~ (Space.+ ~> NotSpace.+).? map(p => AddCommand1(p._1, p._2))
  private lazy val addCommand2 = "add -l" ~> Space.+ ~> objectId ~ (Space.+ ~> NotSpace.+).? map(p => AddCommand1(p._1, p._2))

  lazy val parser: Parser[Command] = Space.* ~> (addCommand1 | addCommand2 | addCommand3)
}
尝试使用此解析器运行测试时,会出现“java.lang.OutOfMemoryError:java堆空间”失败

位于scala.collection.mutable.StringBuilder。(StringBuilder.scala:46)
位于scala.collection.mutable.StringBuilder。(StringBuilder.scala:51)
在scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:286)
位于scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
位于scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:288)
位于scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
在scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:290)
位于scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
在sbt.complete.ParserMain$$anon$3$$anonfun$string$1.apply(Parser.scala:313)
在sbt.complete.ParserMain$$anon$3$$anonfun$string$1.apply(Parser.scala:313)
在sbt.complete.Parser$Value.map处(Parser.scala:161)
在sbt.complete.MapParser.resulty$lzycompute(Parser.scala:704)
在sbt.complete.MapParser.resulty(Parser.scala:704)
在sbt.complete.Repeat.derivate(Parser.scala:834)
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处
在sbt.complete.HomParser.derive(Parser.scala:632)处

编译也需要很长的时间,这是出乎意料的。

我意识到我在使用Space.+、Space.*等,而此时Space、OptSpace等就足够了。这是因为空格和OptSpace(在DefaultParser中定义)已经匹配多个字符

我将代码更改为以下代码,效果很好:

package sbtpin

import sbt.complete._
import DefaultParsers._

object InputParser {
  private lazy val dotParser: Parser[Char] = '.'
  private lazy val objectId = identifier(Letter, IDChar | dotParser)

  private lazy val addCommand1 = "add" ~> Space ~> objectId ~ (Space ~> NotSpace).? map(p => AddCommand1(p._1, p._2))
  private lazy val addCommand2 = "add -n" ~> Space ~> objectId ~ (Space.+ ~> NotSpace).? map(p => AddCommand1(p._1, p._2))
  private lazy val addCommand2 = "add -l" ~> Space ~> objectId ~ (Space ~> NotSpace).? map(p => AddCommand1(p._1, p._2))

  lazy val parser: Parser[Command] = OptSpace ~> (addCommand1 | addCommand2 | addCommand3)
}
这就是空间、OptSpace等在sbt中的定义方式:

/** Matches a single character that is not a whitespace character. */
lazy val NotSpaceClass = charClass(!_.isWhitespace, "non-whitespace character")

/** Matches a single whitespace character, as determined by Char.isWhitespace.*/
lazy val SpaceClass = charClass(_.isWhitespace, "whitespace character")

/** Matches a non-empty String consisting of non-whitespace characters. */
lazy val NotSpace = NotSpaceClass.+.string

/** Matches a possibly empty String consisting of non-whitespace characters. */
lazy val OptNotSpace = NotSpaceClass.*.string

/** Matches a non-empty String consisting of whitespace characters.
* The suggested tab completion is a single, constant space character.*/
lazy val Space = SpaceClass.+.examples(" ")

/** Matches a possibly empty String consisting of whitespace characters.
* The suggested tab completion is a single, constant space character.*/
lazy val OptSpace = SpaceClass.*.examples(" ")
/** Matches a single character that is not a whitespace character. */
lazy val NotSpaceClass = charClass(!_.isWhitespace, "non-whitespace character")

/** Matches a single whitespace character, as determined by Char.isWhitespace.*/
lazy val SpaceClass = charClass(_.isWhitespace, "whitespace character")

/** Matches a non-empty String consisting of non-whitespace characters. */
lazy val NotSpace = NotSpaceClass.+.string

/** Matches a possibly empty String consisting of non-whitespace characters. */
lazy val OptNotSpace = NotSpaceClass.*.string

/** Matches a non-empty String consisting of whitespace characters.
* The suggested tab completion is a single, constant space character.*/
lazy val Space = SpaceClass.+.examples(" ")

/** Matches a possibly empty String consisting of whitespace characters.
* The suggested tab completion is a single, constant space character.*/
lazy val OptSpace = SpaceClass.*.examples(" ")