В Java говорится в Универсальной Книге, при контрастировании различия между Шаблонами C++ и Универсальным Java:
В C++ возникает проблема, потому что>> без пространства обозначает оператор сдвига вправо. Java решает проблему приемом в грамматике.)
Каков этот прием?
Фактически это будет исправлено в C ++ в следующей версии. На самом деле здесь не так уж много уловок; если вы встретите >> в процессе синтаксического анализа универсального шаблона или шаблона, где вместо этого вы ожидали>, значит, у вас уже есть достаточно информации, чтобы сгенерировать сообщение об ошибке. И, если у вас достаточно информации для создания сообщения об ошибке, у вас также достаточно информации, чтобы интерпретировать >> как два отдельных токена:>, за которым следует>.
Парсер javac OpenJDK, JavacParser
, обрабатывает токены лексера GTGTGTEQ
( >>> =
), GTGTEQ
, GTEQ
, GTGTGT
( >>>
) и GTGT
в токен с одним меньше »>
'при анализе аргументов типа.
Вот отрывок волшебства из 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;
}
Можно ясно видеть, что это действительно уловка, и это в грамматике :)
{{1 }}The Java Language Specification, Third Edition показывает полную грамматику, оба оператора сдвига перечислены в InfixOp
продукции, нет никакого (очевидного) трюка. чтобы определить, какая операция >, >> или >>> предназначена, будет решено сканером, используя lookahead технику.
Это простой хак парсера/лексического анализатора. Лексический анализатор обычно распознает пару >>
как одну лексему. Однако, когда в середине разбора родового типа, синтаксический анализатор говорит лексическому анализатору не распознавать >>
.
Исторически сложилось так, что C++ не делал этого ради простоты реализации, но это можно (и будет) исправить, используя тот же трюк.
Это не совсем трюк, они просто определили грамматику так, что лексема сдвига вправо является синонимом двух скобок с прямым углом (что позволяет этой лексеме закрывать шаблон). Вы все еще можете создавать неоднозначности, которые должны быть разрешены с помощью круглых скобок, но однозначные последовательности разбираются без вмешательства разработчика. Это также сделано в C++0x.