[antlr-interest] Using lexer rules properly

Johannes Luber JALuber at gmx.de
Wed Jun 18 10:54:26 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.

Adding CRON_TERM results in eating up all those UINT tokens. Try the following:

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

Johannes

> 
> ----- 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; };
> 

-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger


More information about the antlr-interest mailing list