File: Executor.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (103 lines) | stat: -rw-r--r-- 3,205 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

@_implementationOnly import _RegexParser

struct Executor {
  // TODO: consider let, for now lets us toggle tracing
  var engine: Engine

  init(program: MEProgram) {
    self.engine = Engine(program)
  }

  @available(SwiftStdlib 5.7, *)
  func firstMatch<Output>(
    _ input: String,
    subjectBounds: Range<String.Index>,
    searchBounds: Range<String.Index>,
    graphemeSemantic: Bool
  ) throws -> Regex<Output>.Match? {
    var cpu = engine.makeFirstMatchProcessor(
      input: input,
      subjectBounds: subjectBounds,
      searchBounds: searchBounds)
#if PROCESSOR_MEASUREMENTS_ENABLED
    defer { if cpu.metrics.shouldMeasureMetrics { cpu.printMetrics() } }
#endif
    var low = searchBounds.lowerBound
    let high = searchBounds.upperBound
    while true {
      if let m: Regex<Output>.Match = try _match(
        input, from: low, using: &cpu
      ) {
        return m
      }
      if low >= high { return nil }
      if graphemeSemantic {
        low = input.index(
          low, offsetBy: 1, limitedBy: searchBounds.upperBound) ?? searchBounds.upperBound
      } else {
        input.unicodeScalars.formIndex(after: &low)
      }
      cpu.reset(currentPosition: low)
    }
  }

  @available(SwiftStdlib 5.7, *)
  func match<Output>(
    _ input: String,
    in subjectBounds: Range<String.Index>,
    _ mode: MatchMode
  ) throws -> Regex<Output>.Match? {
    var cpu = engine.makeProcessor(
      input: input, bounds: subjectBounds, matchMode: mode)
#if PROCESSOR_MEASUREMENTS_ENABLED
    defer { if cpu.metrics.shouldMeasureMetrics { cpu.printMetrics() } }
#endif
    return try _match(input, from: subjectBounds.lowerBound, using: &cpu)
  }

  @available(SwiftStdlib 5.7, *)
  func _match<Output>(
    _ input: String,
    from currentPosition: String.Index,
    using cpu: inout Processor
  ) throws -> Regex<Output>.Match? {
    // FIXME: currentPosition is already encapsulated in cpu, don't pass in
    // FIXME: cpu.consume() should return the matched range, not the upper bound
    guard let endIdx = cpu.consume() else {
      if let e = cpu.failureReason {
        throw e
      }
      return nil
    }

    let capList = MECaptureList(
      values: cpu.storedCaptures,
      referencedCaptureOffsets: engine.program.referencedCaptureOffsets)

    let range = currentPosition..<endIdx
    let caps = engine.program.captureList.createElements(capList)

    let anyRegexOutput = AnyRegexOutput(input: input, elements: caps)
    return .init(anyRegexOutput: anyRegexOutput, range: range)
  }

  @available(SwiftStdlib 5.7, *)
  func dynamicMatch(
    _ input: String,
    in subjectBounds: Range<String.Index>,
    _ mode: MatchMode
  ) throws -> Regex<AnyRegexOutput>.Match? {
    try match(input, in: subjectBounds, mode)
  }
}