2013-12-13 166 views
0

它是我第一次使用scala的解析器组合器。 我有这种情况,我有一个'类型'的列表,他们可以扩展其他类型,或不。 如果他们这样做,我只是在类型和它的父类型之间创建一个映射。 如果不是,我只是将类型映射到“对象”。 (类型只是字符串名称)解析器组合器可选部分

他们是这样写的:

type1 type2 type3 - parentType 

type0a type0b 

在这种情况下,他们将隐含地- object

我试图执行它采用以下方式,但不编译。它说它需要一个选项[〜列表[字符串,字符串],它发现〜[a,b]。它也表示它不能在第一个理解中找到价值名称,事实上它是在案例模式匹配中指定的。现在有点混淆实际发生的事情。

def type_list = ((name+) ~ ("-" ~> parent_type)?) ^^ { 
    case names ~ parent_type => for (name <- names) yield name -> parent_type 
    case names => for (name <- names) yield name -> "object" 
} 

def name = """[a-zA-Z\d]+""".r 

其实我只是希望这个返回一个Map[String, String],如果parent_type缺少它应该默认为“对象”。 如何最好地解决这个问题?

回答

3

这里有几件事情正在进行。

首先优先〜和?意味着不是将(解析器[List [String]](名称+)与(“ - ”〜> parent_type)组合起来?这是一个解析器[选项[字符串]]你实际上包装整个事情?如果有意义的话,就得到一个Parser [Option [〜[List [String],String]]。

最简单的解决方案是使用一组额外的括号。

所以,你要开始:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) 

然后在映射函数什么会你会收到一个〜[列表[字符串],选择[字符串]与名称的列表和一个可选的parent_type。 在模式匹配方面,你总是得到name〜parent_type,其中后者是一个Option [String]。 所以基本上你的第二种模式是无效的。

所以你既可以这样做:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ { 
    case names ~ Some(parent_type) => for (name <- names) yield name -> parent_type 
    case names ~ None => for (name <- names) yield name -> "object" 
} 

或者你也可以简化这个到:

def type_list = ((name+) ~ (("-" ~> parent_type)?)) ^^ { 
    case names ~ parent_type => for (name <- names) yield name -> parent_type.getOrElse("object) 
} 
+0

谢谢......这些单子仍设法把我偏离了轨道。感谢更简单的版本。 – jbx