2011-02-03 54 views
2

我正在爲外部工具的命令行界面編寫解析器,並且我正在使用Scala的解析器組合器庫。作爲這個的一部分,我需要解析格式爲的標準日期EEE MMM d HH:mm:ss yyyy Z用標準模式解析CharSequence中的日期...

Scala的解析器組合器是「基於流的」並且與CharSequence的而不是字符串一起使用。這使我很難使用來自JodaTime的java.text.DateTimeFormatDateTimeFormat,因爲它們都與Strings一起使用。現在,我必須編寫自己的正則表達式解析器來解析日期,但我更願意將已完成的工作與JodaTime合併到我的解析器中。我真的不想重新發明輪子。我一直在尋找JodaTime的源代碼,我不確定爲什麼它需要使用Strings而不是CharSequences。我錯過了一些方面?

回答

0

這是現在我的解決方案:

我分叉喬達時間和一些小的修改爲它在CharSequence作品的String!而非。這是在這裏https://github.com/hedefalk/joda-time/commit/ef3bdafd89b334fb052ce0dd192613683b3486a4

然後,我可以寫一個DateParser這樣的:

trait DateParsers extends RegexParsers { 
    def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] { 
    val dateFormat = DateTimeFormat.forPattern(pattern); 

    def jodaParse(text: CharSequence, offset: Int) = { 
     val mutableDateTime = new MutableDateTime 
     val newPos = dateFormat.parseInto(mutableDateTime, text, offset) 
     (mutableDateTime.toDateTime, newPos) 
    } 

    def apply(in: Input) = { 
     val source = in.source 
     val offset = in.offset 
     val start = handleWhiteSpace(source, offset) 
     val (dateTime, endPos) = jodaParse(source, start) 
     if (endPos >= 0) 
     Success(dateTime, in.drop(endPos - offset)) 
     else 
     Failure("Failed to parse date", in.drop(start - offset)) 
    } 
    } 
} 

那麼我可以用這個特質有像生產規則:

private[this] def dateRow = "date:" ~> dateTime("EEE MMM d HH:mm:ss yyyy Z") 

我是不是超負荷工作呢?我現在真的很累...

1

明白了,現在。好的,有一個比分叉更簡單的解決方案。這裏:

trait DateParsers extends RegexParsers { 
    def dateTime(pattern: String): Parser[DateTime] = new Parser[DateTime] { 
    val dateFormat = DateTimeFormat.forPattern(pattern); 

    def jodaParse(text: CharSequence, offset: Int) = { 
     val mutableDateTime = new MutableDateTime 
     val maxInput = text.source.subSequence(offset, dateFormat.estimateParsedLength + offset).toString 
     val newPos = dateFormat.parseInto(mutableDateTime, maxInput, 0) 
     (mutableDateTime.toDateTime, newPos + offset) 
    } 

    def apply(in: Input) = { 
     val source = in.source 
     val offset = in.offset 
     val start = handleWhiteSpace(source, offset) 
     val (dateTime, endPos) = jodaParse(source, start) 
     if (endPos >= 0) 
     Success(dateTime, in.drop(endPos - offset)) 
     else 
     Failure("Failed to parse date", in.drop(start - offset)) 
    } 
    } 
} 
+0

對不起,當然!但是輸入仍然是`Reader [Elem]`,``source``方法返回`CharSequence`。我沒有看到如何使用它來將字符串傳遞到外部解析框架。對我來說,這似乎是一件不可能的事情,因爲組合器在流中工作。你基本上不知道日期字符串會有多少個字符,因此需要一個可以處理流的日期分析器,並給出它已經消耗了多少流的信息。 – 2011-02-03 14:37:36

+0

我指的是最終組合語法分析器的輸入。我試圖編寫的解析器的輸出應該是一個日期。 – 2011-02-03 14:51:53

+0

@hedefalk它是`scala.util.parsing.input.Reader`,你可以繼承任何你需要的東西。例如,您可以使用詞法分析器返回標記,然後使用標記進行處理。請發佈一些你正在嘗試做的代碼,因爲它不清楚。 – 2011-02-03 15:18:09

0

我不確定你在問什麼。你問爲什麼RegexParser.parse()in參數需要CharSequence?如果是的話還有另一種重載RegexParser.parse(),需要一個Reader,你可以寫一個簡單的轉換功能,像這樣:

def stringToReader(str: String): Reader = new StringReader(str) 

關於日期的格式,我覺得完全沒有把它定義爲在解析器的令牌。

希望這會有所幫助。