0

Are there some 'date parser' library that does for dates what FParsec does to strings ?

That is, you either specify rules and it will match against them to recognize the supplied patterns.


Conversely, are there any libraries to generate dates based on some parsing rules ? The idea would be to supply user with a 'real time' completion to guide him to a valid future fparsec matching.

(does this problem of generative parsing has a name in the secluded parsing circles ?)

nicolas
  • 9,549
  • 3
  • 39
  • 83
  • 1
    http://stackoverflow.com/questions/5630012/fparsec-how-to-parse-date-in-fparsec-newbie – Onorio Catenacci Apr 30 '12 at 16:56
  • hi, the thing is I would like to parse on dates, not on strings... rules would be 'next wednesday after the 5th of the month' etc.. – nicolas Apr 30 '12 at 16:59
  • 3
    That's not parsing--that's a rule engine. – Onorio Catenacci Apr 30 '12 at 16:59
  • 2
    Hmmmm... That doesn't sound like parsing at all, more like queries. Perhaps you could reword your question and include a few examples? – kvb Apr 30 '12 at 17:00
  • @OnorioCatenacci Just like FParsec are 'rules' that are 'matched' (success, failures) – nicolas Apr 30 '12 at 17:02
  • 1
    @OnorioCatenacci afaik, a parser, at its core, is something yielding a combination of a success state, a result, and what is left to parse (a string in fparsec). Translated to dates, it is exactly the same, except what is left to parse is a series of dates. – nicolas May 01 '12 at 08:44

1 Answers1

8

You can define a simple domain specific language (DSL) to express these kinds of rules. The type corresponding to your "parser" is actually just a function that takes a date and returns boolean:

type DateClassifier = DC of (DateTime -> bool)

You can easily define some simple functions:

// Succeeds when the date is wednesday
let wednesday = DC (fun dt -> dt.DayOfWeek = DayOfWeek.Wednesday)

// Succeeds if the date is after specified limit
let after limit = DC (fun dt -> dt > limit)

// Succeeds if the day is the specified value
let day d = DC (fun dt -> dt.Day = d)

// Takes two date classifiers and succeeds if either of them succeeds
let (<|>) (DC f) (DC g) = (fun dt -> f dt || g dt)

// Takes two date classifiers and succeeds if both of them succeed
let (<&>) (DC f) (DC g) = (fun dt -> f dt && g dt)

To specify your condition - "the next wednesday after the 5th of the month" - you'll need a helper that generates function that succeeds on any day following 5th, which can be done like this (this is a bit inefficient, but it is composition using existing primitives, which is nice):

let afterDay d = 
  [ for n in d + 1 .. 31 -> day n ] |> Seq.reduce (<|>)

Your specification (or "parser") that only succeeds for the day you described is then:

after DateTime.Now (wednesday <&> afterDay 5)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • That is exactly what I had in mind (of course I plan to match series of dates, and yield back values but this can be dealt with more combinators and some lifting) – nicolas May 01 '12 at 08:26