类型参数中的“>>”是否使用特殊规则进行标记化?

2022-09-04 23:06:00

我对Java规范关于如何标记此代码感到困惑:

ArrayList<ArrayList<Integer>> i;

规格说:

在每一步都使用尽可能长的翻译,即使结果最终没有做出正确的程序,而另一个词法翻译会。

据我所知,应用“最长匹配”规则将导致令牌:

  • 数组列表
  • <
  • 数组列表
  • <
  • 整数
  • >>
  • ;

这不会解析。但是,当然,这段代码被解析得很好。

这种情况的正确规格是什么?

这是否意味着正确的词法分析器必须是上下文无关的?使用常规词法分析器似乎是不可能的。


答案 1

根据阅读@sm4链接的代码,看起来策略是:

  • 正常标记化输入。因此,将被标记为 - 8个令牌,而不是9个。A<B<C>> i;A, <, B, <, C, >>, i, ;

  • 在分层解析期间,当需要解析泛型和 a 时,如果下一个令牌以 -- , , , , 或 - 只需敲掉并把缩短的令牌推回令牌流。示例:当解析器在处理 typeArguments 规则时到达时,它成功解析 typeArguments,并且剩余的令牌流现在略有不同,因为第一个令牌流被拉出以匹配 typeArguments。>>>>>>>>=>>=>>>=>>>, i, ;>, i, ;>>>

因此,尽管标记化确实正常发生,但如有必要,在分层分析阶段会发生一些重新标记化。


答案 2

Java 10 语言规范(3.2 词法翻译)指出:

在每一步都使用尽可能长的翻译,即使结果最终没有做出正确的程序,而另一个词法翻译会。有一个例外:如果在类型上下文中发生词法转换 (§4.11),并且输入流具有两个或多个连续的>字符,后跟一个非>字符,则必须将每个>字符转换为数字比较运算符>的令牌。
输入字符 a--b 被标记化 (§3.5) 为 a、--, b,这不是任何语法正确程序的一部分,即使标记化 a、-, -, b 可能是语法正确程序的一部分。
如果没有>字符的规则,List<List<String>>中的两个连续>括号将被标记化为>>的有符号右移位运算符,而 List<List<List<String>>>等类型中的三个连续>括号将被标记为无符号右移位运算符>>>。更糟糕的是,在 List<List<List<List<String>>>>等类型中对四个或多个连续>括号进行标记化将是模棱两可的,因为>、>>和>>>标记的各种组合可以表示>>>>字符。

C++的早期版本显然也遭受了这种情况的影响,因此在两个相邻的小于(<)和大于(>)符号之间至少需要一个空格,例如.幸运的是,没有了。vector <vector<int> >


推荐