Являются ли ">>" в параметрах типа, токенизированных с помощью специального правила?

Я смущен спецификацией Java о том, как этот код следует обозначать:

ArrayList<ArrayList<Integer>> i;

Спектр говорит:

Самый длинный возможный перевод используется на каждом шаге, даже если результат в конечном итоге не делает правильную программу, в то время как другой лексический перевод будет.

Как я понимаю, применение правила "longest match" приведет к токенам:

  • ArrayList
  • <
  • ArrayList
  • <
  • Integer <Литий → >
  • я
  • ;

который не будет разбираться. Но, конечно, этот код разбирается просто отлично.

Какова правильная спецификация для этого случая?

Означает ли это, что правильный лексер должен быть контекстным? Это не представляется возможным с помощью regular lexer.

Ответ 1

Основываясь на чтении кода, связанного с @sm4, похоже, что стратегия такова:

  • токенизировать вход нормально. Таким образом, A<B<C>> i; будет обозначаться как A, <, B, <, C, >>, i, ; - 8 токенов, а не 9.

  • при иерархическом разборе, когда требуется работать с синтаксическими анализами дженериков и >, если следующий токен начинается с > - >>, >>>, >=, >>=, или >>>= - просто отбросьте > и вытащите укороченный токен обратно в поток токенов. Пример: когда парсер получает значение >>, i, ; во время работы над правилом typeArguments, он успешно разбирает typeArguments, а оставшийся токен ток теперь немного отличается от >, i, ;, так как первый > of >> был снят с match typeArguments.

Итак, хотя токенизация происходит нормально, при необходимости происходит повторная токенизация в иерархической фазе разбора.