В Java Generic Book, сравнивая разницу между С++ Templates и Java Generic, говорится:
В С++ возникает проблема, потому что → без пробела обозначает правый сдвиг. Java исправляет проблема с помощью трюка в грамматике.)
Что это за трюк?
В Java Generic Book, сравнивая разницу между С++ Templates и Java Generic, говорится:
В С++ возникает проблема, потому что → без пробела обозначает правый сдвиг. Java исправляет проблема с помощью трюка в грамматике.)
Что это за трюк?
Это фактически фиксируется в С++ в следующей версии. На самом деле это не очень трюк; если вы столкнулись с → во время разбора общего шаблона или шаблона, где вместо этого вы ожидали > , то у вас уже достаточно информации для генерации сообщения об ошибке. И, если у вас достаточно информации для генерации сообщения об ошибке, у вас также будет достаточно информации, чтобы интерпретировать → как два отдельных токена: > , а затем > .
Парсер javac OpenJDK, JavacParser
, массирует токены лексера GTGTGTEQ
(>>>=
), GTGTEQ
, GTEQ
, GTGTGT
(>>>
) и GTGT
в токен с одним less '>
' при анализе аргументов типа.
Вот фрагмент магии от JavacParser#typeArguments()
:
switch (S.token()) {
case GTGTGTEQ:
S.token(GTGTEQ);
break;
case GTGTEQ:
S.token(GTEQ);
break;
case GTEQ:
S.token(EQ);
break;
case GTGTGT:
S.token(GTGT);
break;
case GTGT:
S.token(GT);
break;
default:
accept(GT);
break;
}
Можно ясно видеть, что это действительно трюк, и это в грамматике:)
Это простой синтаксический анализатор/лексер. Лексический анализатор обычно распознает пару >>
как один токен. Однако, когда в середине разбора общего типа анализатор говорит лексеру не распознавать >>
.
Исторически С++ не делал этого ради простоты реализации, но он может (и будет) исправляться с использованием того же трюка.
Это не совсем трюк, они просто определили грамматику таким образом, что маркер правого сдвига синоним с двумя прямоугольными скобками (таким образом позволяя этому токену закрыть шаблон). Вы все же можете создавать неоднозначности, которые должны быть решены с помощью круглых скобок, но однозначные последовательности анализируются без вмешательства разработчиков. Это также делается в С++ 0x.
Спецификация языка Java, третье издание показывает полную грамматику, оба оператора сдвига перечислены в InfixOp
production, нет (очевидный) трюк. для определения того, какая операция > , → или → > намерена, будет решаться с помощью lookahead.