func (i *inputBytes) context(pos int) syntax.EmptyOp { r1, r2 := endOfText, endOfText if pos > 0 && pos <= len(i.str) { r1, _ = utf8.DecodeLastRune(i.str[:pos]) } if pos < len(i.str) { r2, _ = utf8.DecodeRune(i.str[pos:]) } return syntax.EmptyOpContext(r1, r2) }
// onepass runs the machine over the input starting at pos. // It reports whether a match was found. // If so, m.matchcap holds the submatch information. func (m *machine) onepass(i input, pos int) bool { startCond := m.re.cond if startCond == ^syntax.EmptyOp(0) { // impossible return false } m.matched = false for i := range m.matchcap { m.matchcap[i] = -1 } r, r1 := endOfText, endOfText width, width1 := 0, 0 r, width = i.step(pos) if r != endOfText { r1, width1 = i.step(pos + width) } var flag syntax.EmptyOp if pos == 0 { flag = syntax.EmptyOpContext(-1, r) } else { flag = i.context(pos) } pc := m.op.Start inst := m.op.Inst[pc] // If there is a simple literal prefix, skip over it. if pos == 0 && syntax.EmptyOp(inst.Arg)&^flag == 0 && len(m.re.prefix) > 0 && i.canCheckPrefix() { // Match requires literal prefix; fast search for it. if i.hasPrefix(m.re) { pos += len(m.re.prefix) r, width = i.step(pos) r1, width1 = i.step(pos + width) flag = i.context(pos) pc = int(m.re.prefixEnd) } else { return m.matched } } for { inst = m.op.Inst[pc] pc = int(inst.Out) switch inst.Op { default: panic("bad inst") case syntax.InstMatch: m.matched = true if len(m.matchcap) > 0 { m.matchcap[0] = 0 m.matchcap[1] = pos } return m.matched case syntax.InstRune: if !inst.MatchRune(r) { return m.matched } case syntax.InstRune1: if r != inst.Rune[0] { return m.matched } case syntax.InstRuneAny: // Nothing case syntax.InstRuneAnyNotNL: if r == '\n' { return m.matched } // peek at the input rune to see which branch of the Alt to take case syntax.InstAlt, syntax.InstAltMatch: pc = int(onePassNext(&inst, r)) continue case syntax.InstFail: return m.matched case syntax.InstNop: continue case syntax.InstEmptyWidth: if syntax.EmptyOp(inst.Arg)&^flag != 0 { return m.matched } continue case syntax.InstCapture: if int(inst.Arg) < len(m.matchcap) { m.matchcap[inst.Arg] = pos } continue } if width == 0 { break } flag = syntax.EmptyOpContext(r, r1) pos += width r, width = r1, width1 if r != endOfText { r1, width1 = i.step(pos + width) } } return m.matched }
// match runs the machine over the input starting at pos. // It reports whether a match was found. // If so, m.matchcap holds the submatch information. func (m *machine) match(i input, pos int) bool { startCond := m.re.cond if startCond == ^syntax.EmptyOp(0) { // impossible return false } m.matched = false for i := range m.matchcap { m.matchcap[i] = -1 } runq, nextq := &m.q0, &m.q1 r, r1 := endOfText, endOfText width, width1 := 0, 0 r, width = i.step(pos) if r != endOfText { r1, width1 = i.step(pos + width) } var flag syntax.EmptyOp if pos == 0 { flag = syntax.EmptyOpContext(-1, r) } else { flag = i.context(pos) } for { if len(runq.dense) == 0 { if startCond&syntax.EmptyBeginText != 0 && pos != 0 { // Anchored match, past beginning of text. break } if m.matched { // Have match; finished exploring alternatives. break } if len(m.re.prefix) > 0 && r1 != m.re.prefixRune && i.canCheckPrefix() { // Match requires literal prefix; fast search for it. advance := i.index(m.re, pos) if advance < 0 { break } pos += advance r, width = i.step(pos) r1, width1 = i.step(pos + width) } } if !m.matched { if len(m.matchcap) > 0 { m.matchcap[0] = pos } m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag, nil) } flag = syntax.EmptyOpContext(r, r1) m.step(runq, nextq, pos, pos+width, r, flag) if width == 0 { break } if len(m.matchcap) == 0 && m.matched { // Found a match and not paying attention // to where it is, so any match will do. break } pos += width r, width = r1, width1 if r != endOfText { r1, width1 = i.step(pos + width) } runq, nextq = nextq, runq } m.clear(nextq) return m.matched }