Pratt Parser如何处理这两个绑定优先级看似矛盾的表达式?
问题解答
自定义parselet先处理连续点链再处理()的方案是否可行?
完全可行。
具体实现思路是:编写自定义parselet,优先将连续的成员访问链(比如a.b、x.y.z这类结构)解析为一个完整的成员访问节点,之后再处理后续的后缀()。这样当遇到a.b()时,会先把a.b识别为一个整体的表达式节点,再将其作为函数调用的目标,最终解析为(a.b)()的结构,符合需求;而a().b()则会先解析a(),再对其结果执行.b()调用,也能得到根节点为点运算符的正确结构。
需要注意的是,要确保这个parselet的触发优先级高于后缀()的解析逻辑,或者在解析后缀()时,优先尝试匹配已解析完成的点链节点作为调用目标,避免出现拆分点链的情况。
是否存在无需特殊处理的通用解法?
有,核心是调整运算符的优先级与结合性:
将成员访问.和后缀函数调用()设置为同一优先级,并且指定为左结合。这是Java等主流语言采用的标准规则,完全不需要特殊parselet就能正确处理两种表达式:
- 对于
a().b():左结合规则会先解析左侧的a(),再将其作为.的左操作数,最终得到根节点为.的表达式,左右操作数分别是a()和b(); - 对于
a.b():左结合规则会先解析a.b,再将其作为函数调用的目标,最终得到根节点为函数调用的表达式,调用目标是a.b。
这种方案完全基于标准的运算符优先级解析逻辑(比如Pratt解析、递归下降解析),不需要额外的特殊处理,兼容性和可维护性都更强。
内容的提问来源于stack exchange,提问作者user1293321
相关产品推荐
相关产品推荐

