Brad Mace
Brad Mace

Reputation: 27886

ANTLR4 Rule for one or more options *in order*

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:

but not:

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?

Upvotes: 1

Views: 626

Answers (1)

Bart Kiers
Bart Kiers

Reputation: 170148

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

Upvotes: 1

Related Questions