Pattern
在标准库中没有简单的方法可以做到这一点。
的源代码Pattern
使用递归下降解析器来创建一个对象树Node
,每个对象都支持一个match()
方法。例如,要评估|
,在第 4107 行有一个Branch
子类,它存储了可能的备选方案列表。它的match()
方法尝试每个备选方案,true
如果其中任何一个备选方案匹配且后继节点匹配,则返回。否则返回false
。
通过在解析树中插入特殊GroupHead
和GroupTail
节点来保存组,将每个组的开始和结束位置保存到Pattern
类的私有变量中。
要找出模式的哪些部分导致匹配,节点对象需要知道导致它们被创建的模式部分。解析器根本不会将该信息存储在它创建的节点中。原始模式存储在temp
数组中,递归下降解析器在解析时保留数组的cursor
索引temp
。从第 1567 行开始定义的解析器辅助方法(如peek()
and accept()
)只是cursor
根据需要递增。创建节点时, 的值cursor
不会存储在任何地方。但是该值对于重建模式的哪些部分对应于匹配是必要的。
为什么Pattern
不保存此信息是可以理解的:它会减慢所有正则表达式的计算速度,但几乎不会使用附加功能。
一种可能性是创建一个修改版本,该版本进行Pattern
适当的簿记以将匹配追溯到它们来自的模式部分。为了存储每个节点对应的模式的哪一部分,您可以让构造函数存储该字段Node()
的副本。cursor
但是为了使用该数据来查找模式的哪些部分匹配,您需要更新每个Node
子类的match()
方法以根据…的每个子类的语义来存储范围Node
。
祝你好运!