1.先看Regexp.h Regexp.cc 了解Regexp语法树的结构和一些后面建立语法树所需要使用的的一些数据类型定义
2.Parse.cc中定义了一个ParseState的堆栈结构来存储Regexp结构。辅助建立完整的语法树
建立语法树的过程类似于一个词法分析器 (stringpiece(类似string类型,可看做为string类型) -> Regexp类型
每从正则表达式中读取一个字符,就建立一个对应的Regexp压入ParseState中,当遇到特定的Mark字符如:(,),|时,根据遇到的类型从堆栈中弹出若干元素合并为对应的与或树等复杂的Regexp,并压入ParseState,直到读取完毕,规约堆栈中的内容,此时堆栈中应该为一个大的Regexp语法树,表明了正则表达式的结构
DoCollapse函数:堆栈中两个mark之间的内容弹出,归约为一个大的与或树Regexp结构 a b c ->abc
DoConcatenation 调用DoCollapse来实现,将栈顶的两个元素规约为与树
DoVerticalBar = DoConcatenation( DoCollapse ) + 合并为或树(|) + PushSimpleOp(kVerticalBar)
遇到|符号时,堆栈内为 d | a b c 首先将abc合并为一个与树abc,即d | abc,然后合并为或树d|abc,再将|压入堆栈 d|abc | 。主要是d | a时,不能直接合并为或树,要等到再遇到一个mark时,将两个mark之间的结构规约,a b | c d | e f 为ab|cd|ef 而不是 a b|c d|e f,也就是要向前看一步(与编译原理中的LR1词法分析器的原理类似???)
DoNewRegexpMark = DoConcatenation(DoCollapse) + 合并为或树(@) + PushSimpleOp(kNewRegexpMark)
DoAlternation = DoVerticalBar + 弹出一个元素(|) + DoCollapse(kRegexpAlternation)
将堆栈 ab | c d 归约为 ab|cd 就是假设后面有一个|符号进行的操作,将前面的归约为一个或树
DoNewRegexp = DoNewRegexpMark + 弹出一个元素(@) + DoCollapse(kRegexpNewRegexp)
DoRightParen = DoAlternation(DoVerticalBar+DoCollapse) + 去掉括号
假设遇到了一个|标示进行处理 d | a b,假设后面有一个| ,就可以处理为d|ab
2.Parse.cc中定义了一个ParseState的堆栈结构来存储Regexp结构。辅助建立完整的语法树
建立语法树的过程类似于一个词法分析器 (stringpiece(类似string类型,可看做为string类型) -> Regexp类型
每从正则表达式中读取一个字符,就建立一个对应的Regexp压入ParseState中,当遇到特定的Mark字符如:(,),|时,根据遇到的类型从堆栈中弹出若干元素合并为对应的与或树等复杂的Regexp,并压入ParseState,直到读取完毕,规约堆栈中的内容,此时堆栈中应该为一个大的Regexp语法树,表明了正则表达式的结构
DoCollapse函数:堆栈中两个mark之间的内容弹出,归约为一个大的与或树Regexp结构 a b c ->abc
DoConcatenation 调用DoCollapse来实现,将栈顶的两个元素规约为与树
DoVerticalBar = DoConcatenation( DoCollapse ) + 合并为或树(|) + PushSimpleOp(kVerticalBar)
遇到|符号时,堆栈内为 d | a b c 首先将abc合并为一个与树abc,即d | abc,然后合并为或树d|abc,再将|压入堆栈 d|abc | 。主要是d | a时,不能直接合并为或树,要等到再遇到一个mark时,将两个mark之间的结构规约,a b | c d | e f 为ab|cd|ef 而不是 a b|c d|e f,也就是要向前看一步(与编译原理中的LR1词法分析器的原理类似???)
DoNewRegexpMark = DoConcatenation(DoCollapse) + 合并为或树(@) + PushSimpleOp(kNewRegexpMark)
DoAlternation = DoVerticalBar + 弹出一个元素(|) + DoCollapse(kRegexpAlternation)
将堆栈 ab | c d 归约为 ab|cd 就是假设后面有一个|符号进行的操作,将前面的归约为一个或树
DoNewRegexp = DoNewRegexpMark + 弹出一个元素(@) + DoCollapse(kRegexpNewRegexp)
DoRightParen = DoAlternation(DoVerticalBar+DoCollapse) + 去掉括号
遇到)符号时,堆栈内为( d | a b ,调用DoAlternation会以此规约为:( d | ab -> ( d|ab -> ( d|ab |,然后将堆栈顶的多余 | 弹出:-> ( d|ab ,然后去掉括号: (d|ab) ->d|ab 。括号中有 | 标示,因为 | 优先级比较低, 当ab 和a|b在括号中时ab不需要特别处理,而a|b需要归约为或树,然后才能去掉括号
假设遇到了一个|标示进行处理 d | a b,假设后面有一个| ,就可以处理为d|ab