mutating func printAsPattern()

in Sources/_MatchingEngine/Regex/Printing/PrintAsPattern.swift [49:143]


  mutating func printAsPattern(_ ast: AST.Node) {
    if patternBackoff(ast) {
      printAsCanonical(.init(ast, globalOptions: nil), delimiters: true)
      return
    }

    switch ast {
    case let .alternation(a):
      printBlock("Alternation") { printer in
        a.children.forEach { printer.printAsPattern($0) }
      }

    case let .concatenation(c):
      // Coalesce adjacent children who can produce a
      // string literal representation
      func coalesce(
        _ idx: inout Array<AST>.Index
      ) -> String? {
        let col = c.children
        var result = ""
        while idx < col.endIndex {
          let atom: AST.Atom? = col[idx].as()
          guard let str = atom?.literalStringValue else {
            break
          }
          result += str
          col.formIndex(after: &idx)
        }
        return result.isEmpty ? nil : result._quoted
      }

      // No need to nest single children concatenations
      if c.children.count == 1 {
        printAsPattern(c.children.first!)
        return
      }

      // Check for a single child post-coalescing
      var idx = c.children.startIndex
      if let s = coalesce(&idx), idx == c.children.endIndex {
        print(s)
        return
      }

      printBlock("Concatenation") { printer in
        var curIdx = c.children.startIndex
        while curIdx < c.children.endIndex {
          if let str = coalesce(&curIdx) {
            printer.print(str)
          } else {
            printer.printAsPattern(c.children[curIdx])
            c.children.formIndex(after: &curIdx)
          }
        }
      }

    case let .group(g):
      let kind = g.kind.value._patternBase
      printBlock("Group(\(kind))") { printer in
        printer.printAsPattern(g.child)
      }

    case let .conditional(c):
      print("/*TODO: conditional \(c)*/")

    case let .quantification(q):
      let amount = q.amount.value._patternBase
      let kind = q.kind.value._patternBase
      printBlock("\(amount)(\(kind))") { printer in
        printer.printAsPattern(q.child)
      }

    case let .quote(q):
      // FIXME: Count number of `#` in literal...
      print("#\"\(q.literal)\"#")

    case let .trivia(t):
      // TODO: We might want to output comments...
      _ = t
      return

    case let .atom(a):
      printAsPattern(a)

    case let .customCharacterClass(ccc):
      printAsPattern(ccc)

    case let .absentFunction(abs):
      print("/*TODO: absent function \(abs)*/")

    case .empty: print("")
    case .groupTransform:
      print("// FIXME: get group transform out of here!")
    }
  }