SBT依赖解析器中的NoSuchElementException

时间:2016-11-04 08:16:06

标签: scala sbt

在SBT插件中,我想编写一个带有制表符完成的解析器,它接受并解析函数名称及其参数:

case class Param( name : String, tpe : String ) // tpe is for param type
case class Func( name : String, params : immutable.Seq[Param] )

def funcAndParamsParser( funcs : immutable.Set[Func] ) : Parser[(Func,immutable.Seq[String])] = ???

为了实现这一点,我将问题分解为几个部分:

def funcParser( funcs : immutable.Set[Func] ) : Parser[Func] = {
  val funcsByName = funcs.map( func => (func.name, func) ).toMap
  NotSpace.examples( funcsByName.keySet ).map( funcsByName )
}

def paramParser( param : Param ) : Parser[String] = {
  NotSpace.examples( s"<${param.name}, of type ${param.tpe}>" )
}

def paramsParser( params : immutable.Seq[Param] ) : Parser[immutable.Seq[String]] = {
  params.map( paramParser ).foldLeft( success( immutable.Seq.empty[String] ) ){
    (nascent, next) => nascent.flatMap( partial => Space ~> next.map( str => partial :+ str ) )
  }
}

最后我可以实现主要事件:

def funcAndParamsParser( funcs : immutable.Set[Func] ) : Parser[(Func,immutable.Seq[String])] = {
  funcParser( funcs ).flatMap( func => paramsParser( func.params ).map( seq => ( func, seq ) ) )
}

所有辅助解析器都可以正常工作,但最终组合funcAndParamsParser(...)失败并带有NoSuchElementException

val func0 = Func( "move", Param("x", "Int") :: Param("y", "Int") :: Nil )
val func1 = Func( "fill", Param("color", "Color") :: Nil )
val testParser = Space ~> funcAndParamsParser( immutable.Set( func0, func1 ) )

当我将此解析器嵌入调用InputTask的{​​{1}}时,它似乎有效。在任务名称之后键入testParser.parsed然后<space>,我得到了预期的函数列表(尽管省略了<tab>的第二个参数的示例选项卡完成。

move

然而,解析器总是最终失败。如果我输入应该是有效输入的内容:

> tmpTestDynamicParser 
fill <color, of type Color>   move <x, of type Int>

或者如果我键入部分输入然后选项卡:

> tmpTestDynamicParser move 3 5

我得到一个难以理解的异常:

> tmpTestDynamicParser mo

对于SBT解析器来说,这似乎应该是一个简单的用例,但我对如何修复神秘的Exception感到茫然,并且通常会让事情变得有效。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

行。所以,我是个白痴。

问题在于:

def funcParser( funcs : immutable.Set[Func] ) : Parser[Func] = {
  val funcsByName = funcs.map( func => (func.name, func) ).toMap
  NotSpace.examples( funcsByName.keySet ).map( funcsByName )
}

NotSpace可以为funcsByName的密钥中未包含的项目生成成功的有效结果,当该结果用作{{1}的密钥时,会激发NoSuchElementException }。解决方案是使用一系列与Map链接在一起的文字解析器:

|