Надеюсь, я правильно понял ваш вопрос.
Рассмотрим С.
У него есть несколько знаков препинания, которые начинаются одинаково:
+
, ++
, +=
-
, --
, -=
, ->
<
, <=
, <<
, <<=
- ...
Чтобы выяснить, какой это, когда вы видите первый +
или -
или <
, вам нужно посмотреть вперед на один символ на входе (а затем, возможно, еще один для <<=
) .
Подобная вещь может произойти на более высоком уровне:
{
ident1 ident2;
ident3;
ident4:;
}
Здесь ident1
, ident3
и ident4
могут начинать объявление, выражение или метку. Вы не можете сказать, какой из них сразу. Вы можете обратиться к своим существующим объявлениям, чтобы узнать, известны ли ident1
или ident3
(как тип или переменная / функция / перечисление), но это все еще неоднозначно, потому что может следовать двоеточие, и если это так, это метка, потому что это разрешено использовать один и тот же идентификатор как для метки, так и для типа / переменной / функции / перечисления (эти два пространства имен не пересекаются), например:
{
typedef int ident1;
ident1 ident2; // same as int ident2
int ident3 = 0;
ident3; // unused expression of value 0
ident1:; // unused label
ident2:; // unused label
ident3:; // unused label
}
Таким образом, вам вполне может понадобиться заглянуть в будущее персонажа или токена (или "непрочитанного"), чтобы справиться с подобными ситуациями.