Проблема в том, что вы, похоже, хотите выполнять синтаксическую и семантическую проверку в вашем лексере и / или в вашем анализаторе. Это распространенная ошибка, которая возможна только на очень простых языках.
Что вам действительно нужно сделать, так это принять более широко в лексере и парсере, а затем выполнить семантические проверки. Насколько вы строгие в своем лексизме, зависит от вас, но у вас есть два основных варианта, в зависимости от того, нужно ли вам принимать нули, предшествующие вашим дням месяца: 1) действительно принимайте за INT, 2) определяйте DATENUM принимайте только те токены, которые являются действительными днями, но не являются действительными INT. Я рекомендую второй, потому что в коде будет меньше семантических проверок, необходимых позже (поскольку INT будут проверяться на уровне синтаксиса, и вам нужно будет только выполнять семантические проверки ваших дат. Первый подход:
INT: '0'..'9'+;
Второй подход:
DATENUM: '0' '1'..'9';
INT: '0' | SIGN? '1'..'9' '0'..'9'*;
После принятия этих правил в лексере поле даты будет либо:
date: INT '/' INT ( '/' INT )?
или
date: (INT | DATENUM) '/' (INT | DATENUM) ('/' (INT | DATENUM) )?
После этого вы выполняете семантическую проверку вашего AST, чтобы убедиться, что ваши даты действительны.
Если вы не можете выполнять семантические проверки в своей грамматике, ANTLR разрешает семантические предикаты в синтаксическом анализаторе, поэтому вы можете создать поле даты, которое проверяет такие значения:
date: month=INT '/' day=INT ( year='/' INT )? { year==null ? (/* First check /*) : (/* Second check */)}
Однако, когда вы делаете это, вы встраиваете в язык грамматику, зависящую от языка, и она не переносится на цели.