[antlr-interest] Using lexer rules properly

spoulson at explodingcoder.com spoulson at explodingcoder.com
Wed Jun 18 10:21:00 PDT 2008


Hello all,

This group has graciously helped me before to use ANTLR in a C# project I'm working on.  If you remember, I'm parsing strings that denote datetime syntax for single or recurring events.  So far I've been able to operate properly but it seems I'm having a lexer ambiguity causing me some issues.

I've pasted below a sample working except of my current grammar.  This will accept single datetime ranges in the format: "2008-06-17 14:30:00 lasting T30" for an event on 6/17/2008 at 2:30pm lasting 30 seconds.  My full grammar has many other expression types.  I want to add a new one to describe a cron syntax as "cron 0 * * * *", which for example would recur at the top of every hour.

I decide to add a new lexer rule to parse the individual fields within the cron string:

CRON_TERM: '!'? (UINT | '-' | '/' | '*' | '>' | '<')+;

I also labeled UINT as "fragment" since it's used within another lexer rule.

This tests out great along with a simple parser rule for the cron expression.  However, now the rest of my grammar is broken and the original test case fails in datetime_p with NoViableAltException and matches nothing.  There seems to be an ambiguity between UINT and CRON_TERM that's breaking anywhere else where I parse a number.  It doesn't matter what order I place CRON_TERM, I get the same result.

What am I doing wrong?

Thanks in advance.

----- Cut -----

grammar TimeDeftest1;

options {
   language=CSharp;
   output=AST;
}

once_p returns [OneTimeSchedule value]: (
   start=datetime_p ('lasting' duration=timespan_p)?
);

//
// Time units
//
datetime_p returns [DateTime value]: (
   (y=year_p '-' mo=month_p '-' d=day_p)?
   h=hour24_p ':' m=minute60_p (':' s=second60_p ('.' ms=millisecond1000_p)? )?
);

year_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
month_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
day_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
hour24_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
minute60_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
second60_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
millisecond1000_p returns [int value]: UINT { $value = int.Parse($UINT.text); };
days_p returns [int value]: int_p { $value = int.Parse($int_p.text); };

timespan_p returns [TimeSpan value]: (
   'T' (((d=days_p '.')? h=hours_p ':')? m=minutes_p ':')? s=seconds_p ('.' ms=milliseconds_p)?
);

hours_p returns [int value]: int_p { $value = int.Parse($int_p.text); };
minutes_p returns [int value]: int_p { $value = int.Parse($int_p.text); };
seconds_p returns [int value]: int_p { $value = int.Parse($int_p.text); };
milliseconds_p returns [int value]: int_p { $value = int.Parse($int_p.text); };

int_p: '-'? UINT;

UINT: ('0'..'9')+;

WS: (' '|'\t'|'\r\n'|'\r')+ { $channel = HIDDEN; };




More information about the antlr-interest mailing list