Help needed on DateTime Literal

Mar 23, 2011 at 9:48 AM

Can anyone please help me in creating a DateTime literal for Irony? I was using the one mentioned in this thread but it seems to be faulty, in case of ANY parsing error (irrespective of date values) it is showing the message "A DateTime Literal must end with a #" . Really missing a built-in date-time literal in Irony. Any kind of help would be highly appreciated.

 

Mar 23, 2011 at 11:24 AM

This is what I am using, it is not the ultimate best solution, but it works (btw, does anybody knows how to add rules of reduction to irony?):

            var digit = ToTerm( "0" ) | ToTerm( "1" ) | ToTerm( "2" ) | ToTerm( "3" ) | ToTerm( "4" ) | ToTerm( "5" ) | ToTerm( "6" ) | ToTerm( "7" ) | ToTerm( "8" ) | ToTerm( "9" );

            var month = new NonTerminal( "month", digit + digit );
            var day = new NonTerminal( "day", digit + digit );
            var year = new NonTerminal( "year", digit + digit + digit + digit );
            var date = new NonTerminal( "date", ToTerm( "#" ) + year + "-" + month + "-" + day + "#" );

And to retrieve the date from the parse tree:

           switch ( node.Term.Name ) {
...
                        case "date":
                            var d = node.ChildNodes[ 0 ].ChildNodes[ 1 ].ChildNodes[ 0 ].FirstChild.Term.Name
                                + node.ChildNodes[ 0 ].ChildNodes[ 1 ].ChildNodes[ 1 ].FirstChild.Term.Name
                                + node.ChildNodes[ 0 ].ChildNodes[ 1 ].ChildNodes[ 2 ].FirstChild.Term.Name
                                + node.ChildNodes[ 0 ].ChildNodes[ 1 ].ChildNodes[ 3 ].FirstChild.Term.Name
                                + "/"
                                + node.ChildNodes[ 0 ].ChildNodes[ 3 ].ChildNodes[ 0 ].FirstChild.Term.Name
                                + node.ChildNodes[ 0 ].ChildNodes[ 3 ].ChildNodes[ 1 ].FirstChild.Term.Name
                                + "/"
                                + node.ChildNodes[ 0 ].ChildNodes[ 5 ].ChildNodes[ 0 ].FirstChild.Term.Name
                                + node.ChildNodes[ 0 ].ChildNodes[ 5 ].ChildNodes[ 1 ].FirstChild.Term.Name;
                            return DateTime.Parse( d );
...

I would like to see better solutions...

Coordinator
Mar 23, 2011 at 5:35 PM

If you want VB-like literal, use the following:

            var dateLiteral = new QuotedValueLiteral("dateLiteral""#"TypeCode.DateTime);
            dateLiteral.ErrorAlias = "#MM/DD/YYYY#";

in this case it is date surrounded by "#". The second line is for better error reporting. You can also set DAteTimeFormat property if you want to change the default (american-style date).

Mar 23, 2011 at 6:15 PM

First of all thanks for your responses. That was quick. Anyway @rivantsov the literal you specified would limit me to the #MM/DD/YYYY# format only. I was looking for a more generic literal who can parse those string values as datetime, which are parse-able by the .net framework's DateTime structure itself. Precisely I was looking for a date time literal which can recognize the following patterns as valid date-time value

#5/1/2008 8:30:52 AM#
#2011-03-22T14:09:15.4205455+05:30#
#5/1/2008#
#2011-03-22#
and so on.

 Any idea on how to achieve that? Again thanks in advance.

Coordinator
Mar 23, 2011 at 6:23 PM

change the DateTimeFormat. If the format is not fixed, then make the output type string, hook to ValidateToken event, and inside the handler provide your own way of converting the token string to the DateTime value;

you probably need to try different formats, with TryParse or smth like this; after you parse successfully, set the Value of the output token:

 

 

        void dateLiteral_ValidateToken(object sender, ParsingEventArgs e)
        {
            var dateString = e.Context.CurrentToken.Value;
            // try parsing dateString
            DateTime dateValue;
            if (DateTime.TryParse(..., out dateValue))
                .....
            e.Context.CurrentToken.Value = dateValue; 
        }
Mar 23, 2011 at 6:41 PM

Excellent. This is even more quicker. That is the exact thing I was looking for. Thanks a million.

Mar 23, 2011 at 6:47 PM
Edited Mar 23, 2011 at 7:12 PM

@rivantsov just one more thing. Suppose DateTime is not able to parse the string, then how should report a parsing error in the else block of your code? Thanks in advance.

Edit:

Never mind I got it, which is as follows

 

else
{      
e.Context.CurrentToken = e.Context.Source.CreateErrorToken("{0} is not a valid date-time value", dateString);
}