在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感到茫然,并且通常会让事情变得有效。任何帮助将不胜感激。
答案 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
链接在一起的文字解析器:
|