Рекурсивное правило в ANTLR

Мне нужна идея, как выразить такое утверждение:

Int<Double<Float>>

Итак, в абстрактном виде мы должны иметь:

1.(easiest case):  a<b>
2. case: a<a<b>> 
3. case: a<a<a<b>>>
4. ....and so on...

Дело в том, что я должен включить возможность встраивать оператор формы a < b > в знаки ‹..> - так, чтобы у меня был вложенный оператор. Другими словами: я должен заменить b на a< b >. Во-вторых, количество открывающих и закрытых ‹> - знаков должно быть одинаковым.

Как я могу это сделать в ANTLR?


person user3097712    schedule 24.08.2015    source источник
comment
Забыл написать, что пользуюсь последней версией, Antlr4   -  person user3097712    schedule 24.08.2015


Ответы (1)


Правило может без проблем ссылаться на само себя¹. Допустим, у нас есть правило type, которое описывает ваш случай в минималистском подходе:

type: typeLiteral ('<' type '>')?;
typeLiteral: 'Int' | 'Double' | 'Float';

Обратите внимание, что ('<' type '>') является необязательным, обозначается символом ?, поэтому использование только typeLiteral является допустимым type. Вот синта-деревья, сгенерированные этими правилами в вашем примере Int<Double<Float>>:

Синтаксическое дерево для Int‹ Double ‹Float› ›

¹: Пока некоторые терминалы (например, '‹' или '>') могут дифференцироваться при остановке рекурсии.

Изображение создано http://ironcreek.net/phpsyntaxtree/

person Mephy    schedule 24.08.2015
comment
И в этом java можно найти реальный пример грамматика. См. Правило classOrInterfaceType. - person A wild elephant; 24.08.2015
comment
@Mephy: Когда я тестирую ваше решение, например Int ‹Float ‹Double››, затем он говорит: несоответствующий ввод «››» ожидает «› ». - person user3097712; 24.08.2015
comment
хорошо, с пробелом это работает. Но я, наверное, не понимаю в чем проблема. Где я могу прочитать что-нибудь об этом, чтобы понять это? И есть ли вариант лексера, который я могу использовать, чтобы «››» также мог работать? - person user3097712; 24.08.2015
comment
Пример грамматики C # определяет только токен GT : '>'; и использует правило синтаксического анализатора для оператора >>: right_shift: first=GT second=GT {$first.index + 1 == $second.index}? ; // Nothing between the tokens? - person Lucas Trzesniewski; 25.08.2015