Java规范对如何标记此代码感到困惑:
ArrayList<ArrayList<Integer>> i;
规范说:
每一步都使用尽可能长的翻译,即使结果最终不会产生正确的程序,而另一个词汇翻译会。
据我了解,应用“最长匹配”规则将导致令牌:
- 数组列表
- <
- 数组列表
- <
- 整数
- >>
- 一世
- ;
这不会解析。但当然,这段代码解析得很好。
这种情况下的正确规格是什么?
这是否意味着正确的词法分析器必须是上下文无关的?使用常规词法分析器似乎不可能。
根据阅读@sm4 链接的代码,看起来策略是:
正常标记输入。所以A<B<C>> i;
将被标记为A, <, B, <, C, >>, i, ;
- 8 个标记,而不是 9 个。
在分层解析期间,在解析泛型并且>
需要 a 时,如果下一个标记以>
-- >>
、>>>
、>=
、>>=
或>>>=
-- 开头,只需>
关闭并将缩短的标记推回标记流。示例:当解析器>>, i, ;
在处理 typeArguments 规则时,它成功解析了 typeArguments,并且剩余的令牌流现在略有不同>, i, ;
,因为第一个>
被>>
拉出以匹配 typeArguments。
因此,尽管标记化确实正常发生,但如有必要,在分层解析阶段会发生一些重新标记化。
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> >
. 幸运的是,现在没有了。