Sbt Parser因OutOfMemoryException而失败

时间:2017-02-01 10:41:30

标签: parsing sbt

我有一个sbt插件,其中包含类似于此的Parser:

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堆空间"

   at scala.collection.mutable.StringBuilder.<init>(StringBuilder.scala:46)
   at scala.collection.mutable.StringBuilder.<init>(StringBuilder.scala:51)
   at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:286)
   at scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
   at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:288)
   at scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
   at scala.collection.TraversableOnce$class.mkString(TraversableOnce.scala:290)
   at scala.collection.AbstractTraversable.mkString(Traversable.scala:105)
   at sbt.complete.ParserMain$$anon$3$$anonfun$string$1.apply(Parser.scala:313)
   at sbt.complete.ParserMain$$anon$3$$anonfun$string$1.apply(Parser.scala:313)
   at sbt.complete.Parser$Value.map(Parser.scala:161)
   at sbt.complete.MapParser.resultEmpty$lzycompute(Parser.scala:704)
   at sbt.complete.MapParser.resultEmpty(Parser.scala:704)
   at sbt.complete.Repeat.derive(Parser.scala:834)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)
   at sbt.complete.HomParser.derive(Parser.scala:632)

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

1 个答案:

答案 0 :(得分:0)

我意识到我正在使用Space。+,Space。*等,当Space,OptSpace等就足够了。这是因为Space和OptSpace(在DefaultParsers中定义)已匹配多个字符。

我将代码更改为以下代码,工作正常:

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

这就是在sbt:

中定义Space,OptSpace等的方式
/** 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(" ")