1

I've got a rule to match time periods specified in years, months, days, hours, minutes, and seconds. I want to allow any combination of these, so long as there's at least one, and they appear in that order.

for example:

  • 3 years, 5 days
  • 2 months, 17 seconds

but not:

  • 1 day, 1 month
  • 5 minutes, 2 hours

My current rule is:

period
    : years=INTEGER YEARS (LIST_DELIM months=INTEGER MONTHS)? (LIST_DELIM days=INTEGER DAYS)? (LIST_DELIM hours=INTEGER HOURS)? (LIST_DELIM minutes=INTEGER MINUTES)? (LIST_DELIM seconds=INTEGER SECONDS)?
    | months=INTEGER MONTHS (LIST_DELIM days=INTEGER DAYS)? (LIST_DELIM hours=INTEGER HOURS)? (LIST_DELIM minutes=INTEGER MINUTES)? (LIST_DELIM seconds=INTEGER SECONDS)?
    | days=INTEGER DAYS (LIST_DELIM hours=INTEGER HOURS)? (LIST_DELIM minutes=INTEGER MINUTES)? (LIST_DELIM seconds=INTEGER SECONDS)?
    | hours=INTEGER HOURS (LIST_DELIM minutes=INTEGER MINUTES)? (LIST_DELIM seconds=INTEGER SECONDS)?
    | minutes=INTEGER MINUTES (LIST_DELIM seconds=INTEGER SECONDS)?
    | seconds=INTEGER SECONDS
    ;

This feels like a fair amount of redundancy. Is there any way to simplify this?

Brad Mace
  • 27,194
  • 17
  • 102
  • 148

1 Answers1

1

Besides matching more loosely in your grammar and validating in a listener or visitor, no, there is no way to simplify the rule.

For readability, you might want to create separate parser rules so that you don't need to label them:

period
 : years (',' months)? (',' days)? (',' hours)? (',' minutes)? (',' seconds)?
 | months (',' days)? (',' hours)? (',' minutes)? (',' seconds)?
 | ...
 | seconds
 ;

years
 : INTEGER YEARS 
 ;

months
 : INTEGER MONTHS
 ;

...

LIST_DELIM : ',';

A related Q&A: ANTLR4: Matching all input alternatives exaclty once

Community
  • 1
  • 1
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288