2013-12-13 86 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