2014-10-08 34 views
0

我是相当新的Scala和我想分析的情况下类的列表:解析名单

abstract class D 
case class D0(a: Int, b: Int) extends D 
case class D2(c: String, d: Int) extends D 
case class D3(e: Int, f: String) extends D 
case class D4(e: String, f: String, g: Int) extends D 

我想分析列表[d]的实例。 有一个在列表中的一个特殊的顺序可以由BNF状符号进行说明:

rep(D0 -> D4 -> rep(D2 -> opt(rep(d3)))) 

D0之后D4之后是1-n的D2,每个D2随后用1-N D3等...

我想创建类型的列表:

type T0 = (D0, D4, List[(D2, List[D3])]) 

到目前为止,我发现所有的解决方案是丑陋的和有状态。 经验丰富的Scala开发人员如何实现这一目标?

谢谢

+0

你从什么分析?也就是说,你的输入格式是什么? – sjrd 2014-10-08 20:14:48

+1

'List [D]'与您提出的结构不同。列表是一个列表。你的结构是别的。 – Daenyth 2014-10-08 20:24:45

+0

列表[D]是从基于文件的遗留数据库导入的,具有不同的记录类型,实现了分层数据库模型。 – Volker 2014-10-09 09:37:30

回答

4

这看起来太丑陋了我(假设我理解正确的问题,这不是通常被称为解析):

type T1 = (D2, List[D3]) 

// MatchError if the list doesn't look the way you expected 
def matchList(l: List[D]): List[T0] = l match { 
    case (d0: D0) :: (d4: D4) :: tail => 
    val (d2d3s, tail1) = matchD2D3s(tail) 
    (d0, d4, d2d3s) :: matchList(tail1) 
    case Nil => Nil 
} 

def matchD2D3s(l: List[D]): (List[T1], List[D]) = l match { 
    case (d2: D2) :: tail => 
    val (d3s, tail1) = tail.span(_.isInstanceOf[D3]) 
    val (otherD2D3s, tail2) = matchD2D3s(tail1) 
    ((d2, d3s) :: otherD2D3s, tail2) 
    case l => (Nil, l) // no d2s 
} 
+0

我仍然需要验证所提出的解决方案,也许在这个特殊情况下可以。对于功能性scala来说,它并不是很容易,特别是如果案例数量会增加的话。 – Volker 2014-10-09 09:38:16