* }}} parse */ * VM {{{ */ Simple recursive virtual machine based on the "Regular Expression Matching: the Virtual Machine Approach" (https://swtch.com/~rsc/regexp/regexp2.html)
(src []byte, insts []inst, pc, sp, recLevel int, ms ...*MatchData)
| 528 | // Simple recursive virtual machine based on the |
| 529 | // "Regular Expression Matching: the Virtual Machine Approach" (https://swtch.com/~rsc/regexp/regexp2.html) |
| 530 | func recursiveVM(src []byte, insts []inst, pc, sp, recLevel int, ms ...*MatchData) (bool, int, *MatchData) { |
| 531 | recLevel++ |
| 532 | if recLevel > maxRecursionLevel { |
| 533 | panic(newError(_UNKNOWN, "pattern/input too complex")) |
| 534 | } |
| 535 | var m *MatchData |
| 536 | if len(ms) == 0 { |
| 537 | m = newMatchState() |
| 538 | } else { |
| 539 | m = ms[0] |
| 540 | } |
| 541 | redo: |
| 542 | inst := insts[pc] |
| 543 | switch inst.OpCode { |
| 544 | case opChar: |
| 545 | if sp >= len(src) || !inst.Class.Matches(int(src[sp])) { |
| 546 | return false, sp, m |
| 547 | } |
| 548 | pc++ |
| 549 | sp++ |
| 550 | goto redo |
| 551 | case opMatch: |
| 552 | return true, sp, m |
| 553 | case opTailMatch: |
| 554 | return sp >= len(src), sp, m |
| 555 | case opJmp: |
| 556 | pc = inst.Operand1 |
| 557 | goto redo |
| 558 | case opSplit: |
| 559 | if ok, nsp, _ := recursiveVM(src, insts, inst.Operand1, sp, recLevel, m); ok { |
| 560 | return true, nsp, m |
| 561 | } |
| 562 | pc = inst.Operand2 |
| 563 | goto redo |
| 564 | case opSave: |
| 565 | s := m.setCapture(inst.Operand1, sp) |
| 566 | if ok, nsp, _ := recursiveVM(src, insts, pc+1, sp, recLevel, m); ok { |
| 567 | return true, nsp, m |
| 568 | } |
| 569 | m.restoreCapture(inst.Operand1, s) |
| 570 | return false, sp, m |
| 571 | case opPSave: |
| 572 | m.addPosCapture(inst.Operand1, sp+1) |
| 573 | pc++ |
| 574 | goto redo |
| 575 | case opBrace: |
| 576 | if sp >= len(src) || int(src[sp]) != inst.Operand1 { |
| 577 | return false, sp, m |
| 578 | } |
| 579 | count := 1 |
| 580 | for sp = sp + 1; sp < len(src); sp++ { |
| 581 | if int(src[sp]) == inst.Operand2 { |
| 582 | count-- |
| 583 | } |
| 584 | if count == 0 { |
| 585 | pc++ |
| 586 | sp++ |
| 587 | goto redo |
no test coverage detected
searching dependent graphs…