Как проверить диапазоны чисел в ANTLR 3?

1

Я знаю, что это может зависеть от языка, поэтому будет приемлемо решение на Java или Python.

Учитывая грамматику:

MONTH   : DIGIT DIGIT ;
DIGIT   : ('0'..'9') ;

Я хочу проверить ограничение на MONTH чтобы убедиться, что значение находится между 01 и 12. С чего мне начать поиск и как мне указать это ограничение как правило?

  • 0
    Это зависит от того, какие другие токены определены. Что 13 следует маркировать как?
  • 0
    Все, что < 1 и > 12 должно выдавать ошибку в этом случае, это будет встроено в другое правило, которое указывает MONTH в середине своего правила для форматирования.
Теги:
parsing
antlr
antlr3

2 ответа

1
Лучший ответ

Вы можете вставить собственный код, обернув вокруг него { и }. Таким образом, вы можете сделать что-то вроде:

MONTH 
  :  DIGIT DIGIT 
     {
       int month = Integer.parseInt(getText());
       // do your check here
     } 
  ;

Как вы можете видеть, я вызывал getText(), чтобы удержать согласованный текст токена.

Обратите внимание, что я предположил, что вы ссылаетесь на это правило MONTH из другого правила lexer. Если вы собираетесь генерировать исключение, если 1 > month > 12, тогда всякий раз, когда ваш источник содержит недопустимое значение месяца, не будут применяться правила парсера. Хотя правила lexer и parser могут быть смешаны в одном файле грамматики .g, исходный исходный код сначала маркируется на основе правил lexer, и как только это произошло, только тогда будут согласованы правила парсера.

  • 0
    Я не мог заставить super.getText() работать; $month.text работал. Но я сомневаюсь, что в моей грамматике есть логика синтаксического анализа даты, спецификация ISO 8061 будет довольно запутанной, если вы попытаетесь поддержать все необязательные символы и крайние варианты.
  • 0
    @Jarrod, хм, возможно, ANTLR принимает только getText() без ключевого слова super . Не проверял, извини.
-2

Вы можете использовать эту бесплатную онлайн-утилиту Regex_For_Range для создания регулярного выражения для любого непрерывного целочисленного диапазона. Для значений 01-12 (с разрешенными ведущими 0) утилита дает:

0*([1-9]|1[0-2])

Отсюда вы можете видеть, что если вы хотите ограничить это только 2-значными строками от '01' до '12', настройте это следующим образом:

0[1-9]|1[0-2]

В дни 01-31 мы получаем:

0*([1-9]|[12][0-9]|3[01])

И за 2000-2099 годы выражение просто:

20[0-9]{2}
  • 0
    Как бы это ни было хакерски и круто, это беспокоит меня как кошмар обслуживания во многих отношениях, и ANTLR не использует регулярные выражения для сравнения, это LL-парсер. Я не могу понять, где это было бы лучше, чем использовать числовое сравнение на родном языке, которое было бы самодокументированным. Если у вас есть проблема и вы решаете ее с помощью регулярных выражений, теперь у вас есть две проблемы!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню