2015-02-10 32 views
1

我正在嘗試使用解析器組合器在Scala中編寫一個SemVer(http://semver.org)解析器,以此來熟悉它們。解析Scala中的SemVer

這是我當前的代碼:

case class SemVer(major: Int, minor: Int, patch: Int, prerelease: Option[List[String]], metadata: Option[List[String]]) { 
    override def toString = s"$major.$minor.$patch" + prerelease.map("-" + _.mkString(".")).getOrElse("") + metadata.map("+" + _.mkString(".")) 
} 

class VersionParser extends RegexParsers { 
    def number: Parser[Int] = """(0|[1-9]\d*)""".r ^^ (_.toInt) 
    def separator: Parser[String] = """\.""".r 
    def prereleaseSeparator: Parser[String] = """-""".r 
    def metadataSeparator: Parser[String] = """\+""".r 
    def identifier: Parser[String] = """([0-9A-Za-z-])+""".r ^^ (_.toString) 

    def prereleaseIdentifiers: Parser[List[String]] = (number | identifier) ~ rep(separator ~> (number | identifier)) ^^ { 
    case first ~ rest => List(first.toString) ++ rest.map(_.toString) 
    } 

    def metadataIdentifiers: Parser[List[String]] = identifier ~ rep(separator ~> identifier) ^^ { 
    case first ~ rest => List(first.toString) ++ rest.map(_.toString) 
    } 
} 

我想知道我應該如何解析標識符搶鮮部分,因爲它不允許前導零的數字標識符,且當我嘗試使用我目前的解析解析器前導零(例如在「01.2.3」中)只是成爲一個包含元素0的列表。

更一般地說,應該如何檢測字符串不符合SemVer規範並因此強制失敗條件?

回答

1

經過一番玩弄和一些搜索後,我發現問題是我正在調用parse方法而不是parseAll方法。由於parse基本上可以解析,因此在無法解析時結束,因此它可以接受部分正確的字符串。使用parseAll將強制所有輸入進行解析,並且如果解析停止後仍有輸入,則失敗。這正是我所期待的。