From 9f8478423934f3c540b10fb42b6c66d26d64db9e Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 25 Jan 2022 15:32:57 -0700 Subject: [PATCH 1/7] DSLTree, a shared representation for compilation and printing --- Package.swift | 1 + .../PatternConverter/PatternConverter.swift | 1 + Sources/_MatchingEngine/Regex/AST/AST.swift | 4 +- .../Regex/AST/ASTProtocols.swift | 4 +- Sources/_MatchingEngine/Regex/AST/Group.swift | 4 +- .../Regex/Printing/PrettyPrinter.swift | 28 +- .../Regex/Printing/PrintAsCanonical.swift | 2 +- .../_MatchingEngine/Regex/TreeProtocols.swift | 23 + Sources/_StringProcessing/ByteCodeGen.swift | 536 ++++++++++++++++++ Sources/_StringProcessing/Compiler.swift | 498 +--------------- .../_StringProcessing/ConsumerInterface.swift | 186 +++++- .../_StringProcessing/MatchingOptions.swift | 10 + .../PrintAsPattern.swift | 223 ++++---- .../_StringProcessing/RegexDSL/DSLTree.swift | 363 ++++++++++++ 14 files changed, 1262 insertions(+), 621 deletions(-) create mode 100644 Sources/_MatchingEngine/Regex/TreeProtocols.swift create mode 100644 Sources/_StringProcessing/ByteCodeGen.swift rename Sources/{_MatchingEngine/Regex/Printing => _StringProcessing}/PrintAsPattern.swift (65%) create mode 100644 Sources/_StringProcessing/RegexDSL/DSLTree.swift diff --git a/Package.swift b/Package.swift index a2495cb0c..23e0a72bc 100644 --- a/Package.swift +++ b/Package.swift @@ -68,6 +68,7 @@ let package = Package( dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), "_MatchingEngine", + "_StringProcessing" ]), // MARK: Exercises diff --git a/Sources/PatternConverter/PatternConverter.swift b/Sources/PatternConverter/PatternConverter.swift index 3e5d8485c..98823911b 100644 --- a/Sources/PatternConverter/PatternConverter.swift +++ b/Sources/PatternConverter/PatternConverter.swift @@ -13,6 +13,7 @@ import ArgumentParser import _MatchingEngine +import _StringProcessing @main struct PatternConverter: ParsableCommand { diff --git a/Sources/_MatchingEngine/Regex/AST/AST.swift b/Sources/_MatchingEngine/Regex/AST/AST.swift index 9e5cacd96..83c14323a 100644 --- a/Sources/_MatchingEngine/Regex/AST/AST.swift +++ b/Sources/_MatchingEngine/Regex/AST/AST.swift @@ -33,7 +33,7 @@ extension AST { /// A node in the regex AST. @frozen public indirect enum Node: - Hashable/*, _ASTPrintable ASTValue, ASTAction*/ + Hashable, _TreeNode //, _ASTPrintable ASTValue, ASTAction { /// ... | ... | ... case alternation(Alternation) @@ -94,7 +94,7 @@ extension AST.Node { } } - func `as`(_ t: T.Type = T.self) -> T? { + public func `as`(_ t: T.Type = T.self) -> T? { _associatedValue as? T } diff --git a/Sources/_MatchingEngine/Regex/AST/ASTProtocols.swift b/Sources/_MatchingEngine/Regex/AST/ASTProtocols.swift index bd70848fa..0293c8aca 100644 --- a/Sources/_MatchingEngine/Regex/AST/ASTProtocols.swift +++ b/Sources/_MatchingEngine/Regex/AST/ASTProtocols.swift @@ -19,7 +19,7 @@ // MARK: - AST parent/child -protocol _ASTNode: _ASTPrintable { +public protocol _ASTNode: _ASTPrintable { var location: SourceLocation { get } } extension _ASTNode { @@ -41,7 +41,7 @@ extension AST.Quantification: _ASTParent { var children: [AST.Node] { [child] } } extension AST.AbsentFunction: _ASTParent { - var children: [AST.Node] { + public var children: [AST.Node] { switch kind { case .repeater(let a), .stopper(let a): return [a] case .expression(let a, _, let c): return [a, c] diff --git a/Sources/_MatchingEngine/Regex/AST/Group.swift b/Sources/_MatchingEngine/Regex/AST/Group.swift index be05688be..81e0931ad 100644 --- a/Sources/_MatchingEngine/Regex/AST/Group.swift +++ b/Sources/_MatchingEngine/Regex/AST/Group.swift @@ -112,12 +112,12 @@ extension AST.Group.Kind { } } -extension AST.Group { +extension AST.Group.Kind { /// If this group is a lookaround assertion, return its direction /// and whether it is positive or negative. Otherwise returns /// `nil`. public var lookaroundKind: (forwards: Bool, positive: Bool)? { - switch self.kind.value { + switch self { case .lookahead: return (true, true) case .negativeLookahead: return (true, false) case .lookbehind: return (false, true) diff --git a/Sources/_MatchingEngine/Regex/Printing/PrettyPrinter.swift b/Sources/_MatchingEngine/Regex/Printing/PrettyPrinter.swift index eff9b80ce..f1d8c83b0 100644 --- a/Sources/_MatchingEngine/Regex/Printing/PrettyPrinter.swift +++ b/Sources/_MatchingEngine/Regex/Printing/PrettyPrinter.swift @@ -10,17 +10,17 @@ //===----------------------------------------------------------------------===// /// Track and handle state relevant to pretty-printing ASTs. -struct PrettyPrinter { +public struct PrettyPrinter { // Configuration /// Cut off pattern conversion after this many levels - var maxTopDownLevels: Int? + public var maxTopDownLevels: Int? /// Cut off pattern conversion after this tree height - var minBottomUpLevels: Int? + public var minBottomUpLevels: Int? /// How many spaces to indent with ("tab-width") - var indentWidth = 2 + public var indentWidth = 2 // Internal state @@ -38,7 +38,7 @@ struct PrettyPrinter { extension PrettyPrinter { // This might be necessary if `fileprivate` above suppresses // default struct inits. - init( + public init( maxTopDownLevels: Int? = nil, minBottomUpLevels: Int? = nil ) { @@ -53,19 +53,19 @@ extension PrettyPrinter { /// /// NOTE: If `s` includes a newline, even at the end, /// this function will not update any tracking state. - mutating func output(_ s: String) { + public mutating func output(_ s: String) { result += s } /// Terminate a line, updating any relevant state - mutating func terminateLine() { + public mutating func terminateLine() { output("\n") startOfLine = true } /// Indent a new line, if at the start of a line, otherwise /// does nothing. Updates internal state. - mutating func indent() { + public mutating func indent() { guard startOfLine else { return } let numCols = indentLevel * indentWidth output(String(repeating: " ", count: numCols)) @@ -73,12 +73,12 @@ extension PrettyPrinter { } // Finish, flush, and clear. Returns the rendered output - mutating func finish() -> String { + public mutating func finish() -> String { defer { result = "" } return result } - var depth: Int { indentLevel } + public var depth: Int { indentLevel } } // MARK: - Pretty-print interface @@ -87,7 +87,7 @@ extension PrettyPrinter { /// /// This will property indent `s`, update any internal state, /// and will also terminate the current line. - mutating func print(_ s: String) { + public mutating func print(_ s: String) { indent() output("\(s)") terminateLine() @@ -97,7 +97,7 @@ extension PrettyPrinter { /// /// This will property indent, update any internal state, /// and will also terminate the current line. - mutating func printLine(_ f: () -> String?) { + public mutating func printLine(_ f: () -> String?) { // TODO: What should we do if `f` never returns non-nil? indent() while let s = f() { @@ -107,7 +107,7 @@ extension PrettyPrinter { } /// Execute `f` at one increased level of indentation - mutating func printIndented( + public mutating func printIndented( _ f: (inout Self) -> () ) { self.indentLevel += 1 @@ -117,7 +117,7 @@ extension PrettyPrinter { /// Execute `f` inside an indented "block", which has a header /// and delimiters. - mutating func printBlock( + public mutating func printBlock( _ header: String, startDelimiter: String = "{", endDelimiter: String = "}", diff --git a/Sources/_MatchingEngine/Regex/Printing/PrintAsCanonical.swift b/Sources/_MatchingEngine/Regex/Printing/PrintAsCanonical.swift index 4888975f3..f03da54a4 100644 --- a/Sources/_MatchingEngine/Regex/Printing/PrintAsCanonical.swift +++ b/Sources/_MatchingEngine/Regex/Printing/PrintAsCanonical.swift @@ -40,7 +40,7 @@ extension AST.Node { extension PrettyPrinter { /// Will output `ast` in canonical form, taking care to /// also indent and terminate the line (updating internal state) - mutating func printAsCanonical( + public mutating func printAsCanonical( _ ast: AST, delimiters: Bool = false, terminateLine terminate: Bool = true diff --git a/Sources/_MatchingEngine/Regex/TreeProtocols.swift b/Sources/_MatchingEngine/Regex/TreeProtocols.swift new file mode 100644 index 000000000..7f1ccb5f7 --- /dev/null +++ b/Sources/_MatchingEngine/Regex/TreeProtocols.swift @@ -0,0 +1,23 @@ + + +public protocol _TreeNode { + var children: [Self]? { get } +} + +extension _TreeNode { + public var height: Int { + // FIXME: Is this right for custom char classes? + // How do we count set operations? + guard let children = self.children else { + return 1 + } + guard let max = children.lazy.map(\.height).max() else { + return 1 + } + return 1 + max + } +} + +// TODO: Pretty-printing helpers, etc + + diff --git a/Sources/_StringProcessing/ByteCodeGen.swift b/Sources/_StringProcessing/ByteCodeGen.swift new file mode 100644 index 000000000..74b3f861a --- /dev/null +++ b/Sources/_StringProcessing/ByteCodeGen.swift @@ -0,0 +1,536 @@ +import _MatchingEngine + +extension Compiler { + struct ByteCodeGen { + var options: MatchingOptions + var builder = _MatchingEngine.Program.Builder() + + mutating func finish() -> _MatchingEngine.Program { + builder.buildAccept() + return builder.assemble() + } + } +} + +extension Compiler.ByteCodeGen { + mutating func emitAtom(_ a: DSLTree.Atom) throws { + switch a { + case .any: + emitAny() + + case let .char(c): + // FIXME: Does semantic level matter? + builder.buildMatch(c) + + case let .scalar(s): + // TODO: Native instruction + builder.buildConsume(by: consumeScalar { + $0 == s + }) + + case let .assertion(kind): + try emitAssertion(kind) + + case let .backreference(ref): + try emitBackreference(ref) + + case let .unconverted(astAtom): + if let consumer = try astAtom.generateConsumer(options) { + builder.buildConsume(by: consumer) + } else { + throw Unsupported("\(astAtom._patternBase)") + } + } + } + + mutating func emitBackreference( + _ ref: AST.Reference + ) throws { + if ref.recursesWholePattern { + // TODO: A recursive call isn't a backreference, but + // we could in theory match the whole match so far... + throw Unsupported("Backreference kind: \(ref)") + } + + switch ref.kind { + case .absolute(let i): + // Backreferences number starting at 1 + builder.buildBackreference(.init(i-1)) + case .relative, .named: + throw Unsupported("Backreference kind: \(ref)") + } + } + + mutating func emitAssertion( + _ kind: AST.Atom.AssertionKind + ) throws { + // FIXME: Depends on API model we have... We may want to + // think through some of these with API interactions in mind + // + // This might break how we use `bounds` for both slicing + // and things like `firstIndex`, that is `firstIndex` may + // need to supply both a slice bounds and a per-search bounds. + switch kind { + case .startOfSubject: + builder.buildAssert { (input, pos, bounds) in + pos == input.startIndex + } + + case .endOfSubjectBeforeNewline: + builder.buildAssert { (input, pos, bounds) in + if pos == input.endIndex { return true } + return input.index(after: pos) == input.endIndex + && input[pos].isNewline + } + + case .endOfSubject: + builder.buildAssert { (input, pos, bounds) in + pos == input.endIndex + } + + case .resetStartOfMatch: + // FIXME: Figure out how to communicate this out + throw unsupported(#"\K (reset/keep assertion)"#) + + case .firstMatchingPositionInSubject: + // TODO: We can probably build a nice model with API here + builder.buildAssert { (input, pos, bounds) in + pos == bounds.lowerBound + } + + case .textSegment: + // This we should be able to do! + throw unsupported(#"\y (text segment)"#) + + case .notTextSegment: + // This we should be able to do! + throw unsupported(#"\Y (not text segment)"#) + + case .startOfLine: + builder.buildAssert { (input, pos, bounds) in + pos == input.startIndex || + input[input.index(before: pos)].isNewline + } + + case .endOfLine: + builder.buildAssert { (input, pos, bounds) in + pos == input.endIndex || input[pos].isNewline + } + + case .wordBoundary: + // TODO: May want to consider Unicode level + builder.buildAssert { (input, pos, bounds) in + // TODO: How should we handle bounds? + CharacterClass.word.isBoundary( + input, at: pos, bounds: bounds) + } + + case .notWordBoundary: + // TODO: May want to consider Unicode level + builder.buildAssert { (input, pos, bounds) in + // TODO: How should we handle bounds? + !CharacterClass.word.isBoundary( + input, at: pos, bounds: bounds) + } + } + } + + mutating func emitAny() { + switch (options.semanticLevel, options.dotMatchesNewline) { + case (.graphemeCluster, true): + builder.buildAdvance(1) + case (.graphemeCluster, false): + builder.buildConsume { input, bounds in + input[bounds.lowerBound].isNewline + ? nil + : input.index(after: bounds.lowerBound) + } + + case (.unicodeScalar, true): + // TODO: builder.buildAdvanceUnicodeScalar(1) + builder.buildConsume { input, bounds in + input.unicodeScalars.index(after: bounds.lowerBound) + } + case (.unicodeScalar, false): + builder.buildConsume { input, bounds in + input[bounds.lowerBound].isNewline + ? nil + : input.unicodeScalars.index(after: bounds.lowerBound) + } + } + } + + mutating func emitAlternation( + _ children: [DSLTree.Node] + ) throws { + // Alternation: p0 | p1 | ... | pn + // save next_p1 + // + // branch done + // next_p1: + // save next_p2 + // + // branch done + // next_p2: + // save next_p... + // + // branch done + // ... + // next_pn: + // + // done: + let done = builder.makeAddress() + for component in children.dropLast() { + let next = builder.makeAddress() + builder.buildSave(next) + try emitNode(component) + builder.buildBranch(to: done) + builder.label(next) + } + try emitNode(children.last!) + builder.label(done) + } + + mutating func emitConcatenationComponent( + _ node: DSLTree.Node + ) throws { + // TODO: Should we do anything special since we can + // be glueing sub-grapheme components together? + try emitNode(node) + } + + mutating func emitLookaround( + _ kind: (forwards: Bool, positive: Bool), + _ child: DSLTree.Node + ) throws { + guard kind.forwards else { + throw unsupported("backwards assertions") + } + + let positive = kind.positive + /* + save(restoringAt: success) + save(restoringAt: intercept) + // failure restores at intercept + clearSavePoint // remove intercept + : + clearSavePoint // remove success + fail // positive->success, negative propagates + intercept: + : + clearSavePoint // remove success + fail // positive propagates, negative->success + success: + ... + */ + + let intercept = builder.makeAddress() + let success = builder.makeAddress() + + builder.buildSave(success) + builder.buildSave(intercept) + try emitNode(child) + builder.buildClear() + if !positive { + builder.buildClear() + } + builder.buildFail() + + builder.label(intercept) + if positive { + builder.buildClear() + } + builder.buildFail() + + builder.label(success) + } + + mutating func emitGroup( + _ kind: AST.Group.Kind, _ child: DSLTree.Node + ) throws { + options.beginScope() + defer { options.endScope() } + + if let lookaround = kind.lookaroundKind { + try emitLookaround(lookaround, child) + return + } + + switch kind { + case .lookahead, .negativeLookahead, + .lookbehind, .negativeLookbehind: + fatalError("unreachable") + + case .capture, .namedCapture: + let cap = builder.makeCapture() + builder.buildBeginCapture(cap) + try emitNode(child) + builder.buildEndCapture(cap) + + case .changeMatchingOptions(let optionSequence, _): + options.apply(optionSequence) + try emitNode(child) + + default: + // FIXME: Other kinds... + try emitNode(child) + } + } + + mutating func emitQuantification( + _ amount: AST.Quantification.Amount, + _ kind: AST.Quantification.Kind, + _ child: DSLTree.Node + ) throws { + let kind = kind.applying(options) + + let (low, high) = amount.bounds + switch (low, high) { + case (_, 0): + throw Unsupported( + "TODO: Should error out earlier, maybe DSL and parser has validation logic?") + case let (n, m?) where n > m: + throw Unsupported( + "TODO: Should error out earlier, maybe DSL and parser has validation logic?") + + case let (n, m) where m == nil || n <= m!: + // Ok + break + default: + fatalError("unreachable?") + } + + // Compiler and/or parser should enforce these invariants + // before we are called + assert(high != 0) + assert((0...(high ?? Int.max)).contains(low)) + + let extraTrips: Int? + if let h = high { + extraTrips = h - low + } else { + extraTrips = nil + } + let minTrips = low + assert((extraTrips ?? 1) >= 0) + + // The below is a general algorithm for bounded and unbounded + // quantification. It can be specialized when the min + // is 0 or 1, or when extra trips is 1 or unbounded. + // + // Stuff inside `<` and `>` are decided at compile time, + // while run-time values stored in registers start with a `%` + _ = """ + min-trip-count control block: + if %minTrips is zero: + goto exit-policy control block + else: + decrement %minTrips and fallthrough + + loop-body: + evaluate the subexpression + goto min-trip-count control block + + exit-policy control block: + if %extraTrips is zero: + goto exit + else: + decrement %extraTrips and fallthrough + + : + save exit and goto loop-body + : + ratchet and goto loop + : + save loop-body and fallthrough (i.e. goto exit) + + exit + ... the rest of the program ... + """ + + // Specialization based on `minTrips` for 0 or 1: + _ = """ + min-trip-count control block: + : + goto exit-policy + : + /* fallthrough */ + + loop-body: + evaluate the subexpression + + /* fallthrough */ + """ + + // Specialization based on `extraTrips` for 0 or unbounded + _ = """ + exit-policy control block: + : + goto exit + : + /* fallthrough */ + """ + + /* + NOTE: These specializations don't emit the optimal + code layout (e.g. fallthrough vs goto), but that's better + done later (not prematurely) and certainly better + done by an optimizing compiler. + + NOTE: We're intentionally emitting essentially the same + algorithm for all quantifications for now, for better + testing and surfacing difficult bugs. We can specialize + for other things, like `.*`, later. + + When it comes time for optimizing, we can also look into + quantification instructions (e.g. reduce save-point traffic) + */ + + let minTripsControl = builder.makeAddress() + let loopBody = builder.makeAddress() + let exitPolicy = builder.makeAddress() + let exit = builder.makeAddress() + + // We'll need registers if we're (non-trivially) bounded + let minTripsReg: IntRegister? + if minTrips > 1 { + minTripsReg = builder.makeIntRegister( + initialValue: minTrips) + } else { + minTripsReg = nil + } + + let extraTripsReg: IntRegister? + if (extraTrips ?? 0) > 0 { + extraTripsReg = builder.makeIntRegister( + initialValue: extraTrips!) + } else { + extraTripsReg = nil + } + + // Set up a dummy save point for possessive to update + if kind == .possessive { + builder.pushEmptySavePoint() + } + + // min-trip-count: + // condBranch(to: exitPolicy, ifZeroElseDecrement: %min) + builder.label(minTripsControl) + switch minTrips { + case 0: builder.buildBranch(to: exitPolicy) + case 1: break + default: + assert(minTripsReg != nil, "logic inconsistency") + builder.buildCondBranch( + to: exitPolicy, ifZeroElseDecrement: minTripsReg!) + } + + // FIXME: Possessive needs a "dummy" save point to ratchet + + // loop: + // + // branch min-trip-count + builder.label(loopBody) + try emitNode(child) + if minTrips <= 1 { + // fallthrough + } else { + builder.buildBranch(to: minTripsControl) + } + + // exit-policy: + // condBranch(to: exit, ifZeroElseDecrement: %extraTrips) + // + // + // RegexProgram { - // TODO: Global matching options? - try emit(ast.root) - builder.buildAccept() - let program = builder.assemble() - return RegexProgram(program: program) - } - - func emit(_ node: AST.Node) throws { - - switch node { - case .atom(let a) where a.kind == .any: - try emitAny() - - // Single characters we just match - case .atom(let a) where a.singleCharacter != nil : - builder.buildMatch(a.singleCharacter!) - - // Alternation: p0 | p1 | ... | pn - // save next_p1 - // - // branch done - // next_p1: - // save next_p2 - // - // branch done - // next_p2: - // save next_p... - // - // branch done - // ... - // next_pn: - // - // done: - case .alternation(let alt): - let done = builder.makeAddress() - for component in alt.children.dropLast() { - let next = builder.makeAddress() - builder.buildSave(next) - try emit(component) - builder.buildBranch(to: done) - builder.label(next) - } - try emit(alt.children.last!) - builder.label(done) - - case .conditional: - throw unsupported(node.renderAsCanonical()) - - // FIXME: Wait, how does this work? - case .groupTransform(let g, _): - try emit(g.child) - - - case .concatenation(let concat): - try concat.children.forEach(emit) - - case .trivia, .empty: - break - - case .absentFunction: - throw unsupported(node.renderAsCanonical()) - - case .group(let g): - options.beginScope() - defer { options.endScope() } - - if let lookaround = g.lookaroundKind { - try emitLookaround(lookaround, g.child) - return - } - - switch g.kind.value { - case .lookahead, .negativeLookahead, - .lookbehind, .negativeLookbehind: - fatalError("unreachable") - - case .capture, .namedCapture: - let cap = builder.makeCapture() - builder.buildBeginCapture(cap) - try emit(g.child) - builder.buildEndCapture(cap) - - case .changeMatchingOptions(let optionSequence, _): - options.apply(optionSequence) - try emit(g.child) - - default: - // FIXME: Other kinds... - try emit(g.child) - } - - case .quantification(let quant): - try emitQuantification(quant) - - // For now, we model sets and atoms as consumers. - // This lets us rapidly expand support, and we can better - // design the actual instruction set with real examples - case _ where try node.generateConsumer(options) != nil: - try builder.buildConsume(by: node.generateConsumer(options)!) - - case .quote(let q): - // We stick quoted content into read-only constant strings - builder.buildMatchSequence(q.literal) - - case .atom(let a) where a.assertionKind != nil: - try emitAssertion(a.assertionKind!) - - case .atom(let a): - switch a.kind { - case .backreference(let r): - if r.recursesWholePattern { - // TODO: A recursive call isn't a backreference, but - // we could in theory match the whole match so far... - throw unsupported(node.renderAsCanonical()) - } - - switch r.kind { - case .absolute(let i): - // Backreferences number starting at 1 - builder.buildBackreference(.init(i-1)) - case .relative, .named: - throw unsupported(node.renderAsCanonical()) - } - default: - throw unsupported(node.renderAsCanonical()) - } - - case .customCharacterClass: - throw unsupported(node.renderAsCanonical()) - } - } - - func emitAny() throws { - switch (options.semanticLevel, options.dotMatchesNewline) { - case (.graphemeCluster, true): - builder.buildAdvance(1) - case (.graphemeCluster, false): - builder.buildConsume { input, bounds in - input[bounds.lowerBound].isNewline - ? nil - : input.index(after: bounds.lowerBound) - } - - case (.unicodeScalar, true): - // TODO: builder.buildAdvanceUnicodeScalar(1) - builder.buildConsume { input, bounds in - input.unicodeScalars.index(after: bounds.lowerBound) - } - case (.unicodeScalar, false): - builder.buildConsume { input, bounds in - input[bounds.lowerBound].isNewline - ? nil - : input.unicodeScalars.index(after: bounds.lowerBound) - } - } - } - - func emitAssertion(_ kind: AST.Atom.AssertionKind) throws { - // FIXME: Depends on API model we have... We may want to - // think through some of these with API interactions in mind - // - // This might break how we use `bounds` for both slicing - // and things like `firstIndex`, that is `firstIndex` may - // need to supply both a slice bounds and a per-search bounds. - switch kind { - case .startOfSubject: - builder.buildAssert { (input, pos, bounds) in - pos == input.startIndex - } - - case .endOfSubjectBeforeNewline: - builder.buildAssert { (input, pos, bounds) in - if pos == input.endIndex { return true } - return input.index(after: pos) == input.endIndex - && input[pos].isNewline - } - - case .endOfSubject: - builder.buildAssert { (input, pos, bounds) in - pos == input.endIndex - } - - case .resetStartOfMatch: - // FIXME: Figure out how to communicate this out - throw unsupported(#"\K (reset/keep assertion)"#) - - case .firstMatchingPositionInSubject: - // TODO: We can probably build a nice model with API here - builder.buildAssert { (input, pos, bounds) in - pos == bounds.lowerBound - } - - case .textSegment: - // This we should be able to do! - throw unsupported(#"\y (text segment)"#) - - case .notTextSegment: - // This we should be able to do! - throw unsupported(#"\Y (not text segment)"#) - - case .startOfLine: - builder.buildAssert { (input, pos, bounds) in - pos == input.startIndex || - input[input.index(before: pos)].isNewline - } - - case .endOfLine: - builder.buildAssert { (input, pos, bounds) in - pos == input.endIndex || input[pos].isNewline - } - - case .wordBoundary: - // TODO: May want to consider Unicode level - builder.buildAssert { (input, pos, bounds) in - // TODO: How should we handle bounds? - CharacterClass.word.isBoundary( - input, at: pos, bounds: bounds) - } - - case .notWordBoundary: - // TODO: May want to consider Unicode level - builder.buildAssert { (input, pos, bounds) in - // TODO: How should we handle bounds? - !CharacterClass.word.isBoundary( - input, at: pos, bounds: bounds) - } - } - } - - func emitLookaround( - _ kind: (forwards: Bool, positive: Bool), - _ child: AST.Node - ) throws { - guard kind.forwards else { - throw unsupported("backwards assertions") - } - - let positive = kind.positive - /* - save(restoringAt: success) - save(restoringAt: intercept) - // failure restores at intercept - clearSavePoint // remove intercept - : - clearSavePoint // remove success - fail // positive->success, negative propagates - intercept: - : - clearSavePoint // remove success - fail // positive propagates, negative->success - success: - ... - */ - - let intercept = builder.makeAddress() - let success = builder.makeAddress() - - builder.buildSave(success) - builder.buildSave(intercept) - try emit(child) - builder.buildClear() - if !positive { - builder.buildClear() - } - builder.buildFail() - - builder.label(intercept) - if positive { - builder.buildClear() - } - builder.buildFail() - - builder.label(success) - } - - - func compileQuantification( - low: Int, - high: Int?, - kind: AST.Quantification.Kind, - child: AST.Node - ) throws { - // Compiler and/or parser should enforce these invariants - // before we are called - assert(high != 0) - assert((0...(high ?? Int.max)).contains(low)) - - let extraTrips: Int? - if let h = high { - extraTrips = h - low - } else { - extraTrips = nil - } - let minTrips = low - assert((extraTrips ?? 1) >= 0) - - // The below is a general algorithm for bounded and unbounded - // quantification. It can be specialized when the min - // is 0 or 1, or when extra trips is 1 or unbounded. - // - // Stuff inside `<` and `>` are decided at compile time, - // while run-time values stored in registers start with a `%` - _ = """ - min-trip-count control block: - if %minTrips is zero: - goto exit-policy control block - else: - decrement %minTrips and fallthrough - - loop-body: - evaluate the subexpression - goto min-trip-count control block - - exit-policy control block: - if %extraTrips is zero: - goto exit - else: - decrement %extraTrips and fallthrough - - : - save exit and goto loop-body - : - ratchet and goto loop - : - save loop-body and fallthrough (i.e. goto exit) - - exit - ... the rest of the program ... - """ - - // Specialization based on `minTrips` for 0 or 1: - _ = """ - min-trip-count control block: - : - goto exit-policy - : - /* fallthrough */ - - loop-body: - evaluate the subexpression - - /* fallthrough */ - """ - - // Specialization based on `extraTrips` for 0 or unbounded - _ = """ - exit-policy control block: - : - goto exit - : - /* fallthrough */ - """ + // TODO: Handle global options + let converted = ast.root.dslTreeNode - /* - NOTE: These specializations don't emit the optimal - code layout (e.g. fallthrough vs goto), but that's better - done later (not prematurely) and certainly better - done by an optimizing compiler. - - NOTE: We're intentionally emitting essentially the same - algorithm for all quantifications for now, for better - testing and surfacing difficult bugs. We can specialize - for other things, like `.*`, later. - - When it comes time for optimizing, we can also look into - quantification instructions (e.g. reduce save-point traffic) - */ - - let minTripsControl = builder.makeAddress() - let loopBody = builder.makeAddress() - let exitPolicy = builder.makeAddress() - let exit = builder.makeAddress() - - // We'll need registers if we're (non-trivially) bounded - let minTripsReg: IntRegister? - if minTrips > 1 { - minTripsReg = builder.makeIntRegister( - initialValue: minTrips) - } else { - minTripsReg = nil - } - - let extraTripsReg: IntRegister? - if (extraTrips ?? 0) > 0 { - extraTripsReg = builder.makeIntRegister( - initialValue: extraTrips!) - } else { - extraTripsReg = nil - } - - // Set up a dummy save point for possessive to update - if kind == .possessive { - builder.pushEmptySavePoint() - } - - // min-trip-count: - // condBranch(to: exitPolicy, ifZeroElseDecrement: %min) - builder.label(minTripsControl) - switch minTrips { - case 0: builder.buildBranch(to: exitPolicy) - case 1: break - default: - assert(minTripsReg != nil, "logic inconsistency") - builder.buildCondBranch( - to: exitPolicy, ifZeroElseDecrement: minTripsReg!) - } - - // FIXME: Possessive needs a "dummy" save point to ratchet - - // loop: - // - // branch min-trip-count - builder.label(loopBody) - try emit(child) - if minTrips <= 1 { - // fallthrough - } else { - builder.buildBranch(to: minTripsControl) - } - - // exit-policy: - // condBranch(to: exit, ifZeroElseDecrement: %extraTrips) - // - // - // m: - // TODO: Parser should warn - // TODO: Should we error? - return - - case let (atLeast: n, atMost: m) where m == nil || n <= m!: - try compileQuantification( - low: n, high: m, kind: kind, child: child) - return - - default: - fatalError("unreachable") - } + var codegen = ByteCodeGen(options: options) + try codegen.emitNode(converted) + let program = codegen.finish() + return RegexProgram(program: program) } } diff --git a/Sources/_StringProcessing/ConsumerInterface.swift b/Sources/_StringProcessing/ConsumerInterface.swift index a444368c3..8b8e1dc64 100644 --- a/Sources/_StringProcessing/ConsumerInterface.swift +++ b/Sources/_StringProcessing/ConsumerInterface.swift @@ -21,8 +21,19 @@ struct Unsupported: Error, CustomStringConvertible { \(file):\(line) """ } + + init( + _ s: String, + file: StaticString = #file, + line: UInt = #line + ) { + self.message = s + self.file = file.description + self.line = Int(asserting: line) + } } +// TODO: Remove func unsupported( _ s: String, file: StaticString = #file, @@ -53,7 +64,7 @@ func unreachable( message: s, file: String(describing: file), line: line) } -extension AST.Node { +extension DSLTree.Node { /// Attempt to generate a consumer from this AST node /// /// A consumer is a Swift closure that matches against @@ -66,13 +77,73 @@ extension AST.Node { return try a.generateConsumer(opts) case .customCharacterClass(let ccc): return try ccc.generateConsumer(opts) + + case .stringLiteral: + // TODO: Should we handle this here? + return nil + + case .regexLiteral: + fatalError( + "unreachable: We should only ask atoms") + + case let .convertedRegexLiteral(n, _): + return try n.generateConsumer(opts) + case .alternation, .conditional, .concatenation, .group, - .quantification, .quote, .trivia, .empty, + .quantification, .trivia, .empty, .groupTransform, .absentFunction: return nil + + case .consumer: + fatalError("FIXME: Is this where we handle them?") + case .consumerValidator: + fatalError("FIXME: Is this where we handle them?") + case .characterPredicate: + fatalError("FIXME: Is this where we handle them?") } } } +extension DSLTree.Atom { + // TODO: If ByteCodeGen switches first, then this is + // unnecessary... + func generateConsumer( + _ opts: MatchingOptions + ) throws -> Program.ConsumeFunction? { + switch self { + + case let .char(c): + // TODO: Match level? + return { input, bounds in + let low = bounds.lowerBound + guard input[low] == c else { + return nil + } + return input.index(after: low) + } + case let .scalar(s): + return consumeScalar { $0 == s } + + case .any: + // FIXME: Should this be a total ordering? + fatalError( + "unreachable: emitAny() should be called isntead") + + case .assertion: + // TODO: We could handle, should this be total? + return nil + + case .backreference: + // TODO: Should we handle? + return nil + + case let .unconverted(a): + return try a.generateConsumer(opts) + } + + } +} + + // TODO: This is basically an AST interpreter, which would // be good or interesting to build regardless, and serves // as a compiler fall-back path @@ -96,7 +167,9 @@ extension AST.Atom { _ opts: MatchingOptions ) throws -> Program.ConsumeFunction? { // TODO: Wean ourselves off of this type... - if let cc = self.characterClass?.withMatchLevel(opts.matchLevel) { + if let cc = self.characterClass?.withMatchLevel( + opts.matchLevel + ) { return { input, bounds in // FIXME: should we worry about out of bounds? cc.matches(in: input, at: bounds.lowerBound) @@ -105,9 +178,14 @@ extension AST.Atom { switch kind { case let .scalar(s): + assertionFailure( + "Should have been handled by tree conversion") return consumeScalar { $0 == s } case let .char(c): + assertionFailure( + "Should have been handled by tree conversion") + // TODO: Match level? return { input, bounds in let low = bounds.lowerBound @@ -127,12 +205,14 @@ extension AST.Atom { } case .any: + assertionFailure( + "Should have been handled by tree conversion") fatalError(".atom(.any) is handled in emitAny") case .startOfLine, .endOfLine: // handled in emitAssertion return nil - + case .escaped, .keyboardControl, .keyboardMeta, .keyboardMetaControl, .backreference, .subpattern, .callout, .backtrackingDirective: // FIXME: implement @@ -141,6 +221,79 @@ extension AST.Atom { } } +extension DSLTree.CustomCharacterClass.Member { + func generateConsumer( + _ opts: MatchingOptions + ) throws -> Program.ConsumeFunction { + switch self { + case let .atom(a): + guard let c = try a.generateConsumer(opts) else { + throw Unsupported("Consumer for \(a)") + } + return c + case let .range(low, high): + // TODO: + guard let lhs = low.literalCharacterValue else { + throw unsupported("\(low) in range") + } + guard let rhs = high.literalCharacterValue else { + throw unsupported("\(high) in range") + } + + return { input, bounds in + // TODO: check for out of bounds? + let curIdx = bounds.lowerBound + if (lhs...rhs).contains(input[curIdx]) { + // TODO: semantic level + return input.index(after: curIdx) + } + return nil + } + + case let .custom(ccc): + return try ccc.generateConsumer(opts) + + case let .intersection(lhs, rhs): + let lhs = try lhs.generateConsumer(opts) + let rhs = try rhs.generateConsumer(opts) + return { input, bounds in + if let lhsIdx = lhs(input, bounds), + let rhsIdx = rhs(input, bounds) + { + guard lhsIdx == rhsIdx else { + fatalError("TODO: What should we do here?") + } + return lhsIdx + } + return nil + } + + case let .subtraction(lhs, rhs): + let lhs = try lhs.generateConsumer(opts) + let rhs = try rhs.generateConsumer(opts) + return { input, bounds in + if let lhsIdx = lhs(input, bounds), + rhs(input, bounds) == nil + { + return lhsIdx + } + return nil + } + + case let .symmetricDifference(lhs, rhs): + let lhs = try lhs.generateConsumer(opts) + let rhs = try rhs.generateConsumer(opts) + return { input, bounds in + if let lhsIdx = lhs(input, bounds) { + return rhs(input, bounds) == nil ? lhsIdx : nil + } + return rhs(input, bounds) + } + } + + } +} + extension AST.CustomCharacterClass.Member { func generateConsumer( _ opts: MatchingOptions @@ -235,6 +388,29 @@ extension AST.CustomCharacterClass.Member { } } +extension DSLTree.CustomCharacterClass { + func generateConsumer( + _ opts: MatchingOptions + ) throws -> Program.ConsumeFunction { + // NOTE: Easy way to implement, obviously not performant + let consumers = try members.map { + try $0.generateConsumer(opts) + } + return { input, bounds in + for consumer in consumers { + if let idx = consumer(input, bounds) { + return isInverted ? nil : idx + } + } + if isInverted { + // FIXME: semantic level + return input.index(after: bounds.lowerBound) + } + return nil + } + } +} + extension AST.CustomCharacterClass { func generateConsumer( _ opts: MatchingOptions @@ -274,7 +450,7 @@ private func consumeScalarProp( ) -> Program.ConsumeFunction { consumeScalar { p($0.properties) } } -private func consumeScalar( +func consumeScalar( _ p: @escaping (Unicode.Scalar) -> Bool ) -> Program.ConsumeFunction { { input, bounds in diff --git a/Sources/_StringProcessing/MatchingOptions.swift b/Sources/_StringProcessing/MatchingOptions.swift index 7509d3e2b..dcdddc4a8 100644 --- a/Sources/_StringProcessing/MatchingOptions.swift +++ b/Sources/_StringProcessing/MatchingOptions.swift @@ -247,3 +247,13 @@ extension MatchingOptions.Representation { [.graphemeClusterSemantics, .textSegmentGraphemeMode] } } + +extension AST.Quantification.Kind { + func applying(_ options: MatchingOptions) -> Self { + if options.isReluctantByDefault && self != .possessive { + return self == .eager ? .reluctant : .eager + } + + return self + } +} diff --git a/Sources/_MatchingEngine/Regex/Printing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift similarity index 65% rename from Sources/_MatchingEngine/Regex/Printing/PrintAsPattern.swift rename to Sources/_StringProcessing/PrintAsPattern.swift index 5f00986c0..b5f83f08a 100644 --- a/Sources/_MatchingEngine/Regex/Printing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -9,6 +9,8 @@ // //===----------------------------------------------------------------------===// +import _MatchingEngine + // TODO: Add an expansion level, both from top to bottom. // After `printAsCanonical` is fleshed out, these two // printers can call each other. This would enable @@ -31,7 +33,9 @@ extension AST { extension PrettyPrinter { /// If pattern printing should back off, prints the regex literal and returns true - mutating func patternBackoff(_ ast: AST.Node) -> Bool { + mutating func patternBackoff( + _ ast: T + ) -> Bool { if let max = maxTopDownLevels, depth >= max { return true } @@ -41,149 +45,164 @@ extension PrettyPrinter { return false } + mutating func printBackoff(_ node: DSLTree.Node) { + precondition(node.astNode != nil, "unconverted node") + printAsCanonical( + .init(node.astNode!, globalOptions: nil), + delimiters: true) + } + mutating func printAsPattern(_ ast: AST) { - // TODO: Global matching options? - printAsPattern(ast.root) + // TODO: Handle global options... + let node = ast.root.dslTreeNode + printAsPattern(convertedFromAST: node) } - mutating func printAsPattern(_ ast: AST.Node) { - if patternBackoff(ast) { - printAsCanonical(.init(ast, globalOptions: nil), delimiters: true) + // FIXME: Use of back-offs like height and depth + // imply that this DSLTree node has a corresponding + // AST. That's not always true, and it would be nice + // to have a non-backing-off pretty-printer that this + // can defer to. + private mutating func printAsPattern( + convertedFromAST node: DSLTree.Node + ) { + if patternBackoff(node) { + printBackoff(node) return } - switch ast { + switch node { + case let .alternation(a): printBlock("Alternation") { printer in - a.children.forEach { printer.printAsPattern($0) } + a.forEach { + printer.printAsPattern(convertedFromAST: $0) + } } case let .concatenation(c): - // Coalesce adjacent children who can produce a - // string literal representation - func coalesce( - _ idx: inout Array.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) + printBlock("Concatenation") { printer in + c.forEach { + printer.printAsPattern(convertedFromAST: $0) } - return result.isEmpty ? nil : result._quoted } - // No need to nest single children concatenations - if c.children.count == 1 { - printAsPattern(c.children.first!) - return + case let .group(kind, child): + let kind = kind._patternBase + printBlock("Group(\(kind))") { printer in + printer.printAsPattern(convertedFromAST: child) } - // Check for a single child post-coalescing - var idx = c.children.startIndex - if let s = coalesce(&idx), idx == c.children.endIndex { - print(s) - return - } + case .conditional: + print("/* TODO: conditional */") - 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 .quantification(amount, kind, child): + let amount = amount._patternBase + let kind = kind._patternBase + printBlock("\(amount)(\(kind))") { printer in + printer.printAsPattern(convertedFromAST: child) } - case let .group(g): - let kind = g.kind.value._patternBase - printBlock("Group(\(kind))") { printer in - printer.printAsPattern(g.child) - } + case let .atom(a): + switch a { + case .any: + print(".any") - case let .conditional(c): - print("/*TODO: conditional \(c)*/") + case let .char(c): + print(String(c)._quoted) - 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 .scalar(s): + let hex = String(s.value, radix: 16, uppercase: true) + print("\\u{\(hex)}"._quoted) + + case let .unconverted(a): + // TODO: is this always right? + // TODO: Convert built-in character classes + print(a._patternBase) + + case .assertion: + print("/* TOOD: assertions */") + case .backreference: + print("/* TOOD: backreferences */") } - case let .quote(q): - // FIXME: Count number of `#` in literal... - print("#\"\(q.literal)\"#") + case .trivia: + // What should we do? Maybe keep comments, etc? + print("") - case let .trivia(t): - // TODO: We might want to output comments... - _ = t - return + case .empty: + print("") - case let .atom(a): - printAsPattern(a) + case let .stringLiteral(v): + print(v._quoted) + + case .regexLiteral: + printBackoff(node) + + case let .convertedRegexLiteral(n, _): + // FIXME: This recursion coordinates with back-off + // check above, so it shoud work out. Need a + // cleaner way to do this. This means the argument + // label is a lie. + printAsPattern(convertedFromAST: n) 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!") - } - } - - mutating func printAsPattern(_ a: AST.Atom) { - if let s = a.literalStringValue { - print(s._quoted) - } else { - print(a._patternBase) + print("/* TODO: group transforms */") + case .consumer: + print("/* TODO: consumers */") + case .consumerValidator: + print("/* TODO: consumer validators */") + case .characterPredicate: + print("/* TODO: character predicates */") + + case .absentFunction: + print("/* TODO: absent function */") } } - mutating func printAsPattern(_ ccc: AST.CustomCharacterClass) { + // TODO: Some way to integrate this with conversion... + mutating func printAsPattern( + _ ccc: DSLTree.CustomCharacterClass + ) { let inv = ccc.isInverted ? "inverted: true" : "" printBlock("CharacterClass(\(inv))") { printer in ccc.members.forEach { printer.printAsPattern($0) } } } - mutating func printAsPattern(_ member: AST.CustomCharacterClass.Member) { + // TODO: Some way to integrate this with conversion... + mutating func printAsPattern( + _ member: DSLTree.CustomCharacterClass.Member + ) { switch member { - case .custom(let ccc): + case let .custom(ccc): printAsPattern(ccc) - case .range(let r): - if let lhs = r.lhs.literalStringValue, - let rhs = r.rhs.literalStringValue { + case let .range(lhs, rhs): + if case let .char(lhs) = lhs, + case let .char(rhs) = rhs { indent() - output(lhs._quoted) + output(String(lhs)._quoted) output("...") - output(rhs._quoted) + output(String(rhs)._quoted) terminateLine() } else { - print("// TODO: Range \(r.lhs) to \(r.rhs)") + print("// TODO: Range \(lhs) to \(rhs)") } - case .atom(let a): - if let s = a.literalStringValue { - print(s._quoted) + case let .atom(a): + if case let .char(c) = a { + print(String(c)._quoted) } else { - print(a._patternBase) + print(" // TODO: Atom \(a) ") } case .quote(let q): print("// TODO: quote \(q.literal._quoted) in custom character classes (should we split it?)") case .trivia(let t): // TODO: We might want to output comments... _ = t - case .setOperation: +case .symmetricDifference, .intersection, .subtraction: print("// TODO: Set operation: \(member)") } } @@ -195,6 +214,7 @@ extension String { } extension AST.Atom.AssertionKind { + // TODO: Some way to integrate this with conversion... var _patternBase: String { switch self { case .startOfSubject: return "Anchor(.startOfSubject)" @@ -217,11 +237,13 @@ extension AST.Atom.AssertionKind { } extension AST.Atom.CharacterProperty { + // TODO: Some way to integrate this with conversion... var _patternBase: String { "Property(\(kind._patternBase)\(isInverted ? ", inverted: true" : ""))" } } extension AST.Atom.CharacterProperty.Kind { + // TODO: Some way to integrate this with conversion... var _patternBase: String { "/* TODO: character properties */" } @@ -234,6 +256,8 @@ extension AST.Atom { /// /// TODO: We want to coalesce adjacent atoms, likely in /// caller, but we might want to be parameterized at that point. + /// + /// TODO: Some way to integrate this with conversion... var _patternBase: String { if let anchor = self.assertionKind { return anchor._patternBase @@ -325,6 +349,9 @@ extension AST.Group.Kind { return "/* TODO: atomicScriptRun */" case .changeMatchingOptions: return "/* TODO: changeMatchingOptions */" + + @unknown default: + fatalError() } } } @@ -352,17 +379,3 @@ extension AST.Quantification.Kind { } } } - -extension AST.Node { - var height: Int { - // FIXME: Is this right for custom char classes? - // How do we count set operations? - guard let children = self.children else { - return 1 - } - guard let max = children.lazy.map(\.height).max() else { - return 1 - } - return 1 + max - } -} diff --git a/Sources/_StringProcessing/RegexDSL/DSLTree.swift b/Sources/_StringProcessing/RegexDSL/DSLTree.swift new file mode 100644 index 000000000..14e74266f --- /dev/null +++ b/Sources/_StringProcessing/RegexDSL/DSLTree.swift @@ -0,0 +1,363 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +import _MatchingEngine + +struct DSLTree {} + +extension DSLTree { + indirect enum Node: _TreeNode { + /// ... | ... | ... + case alternation([Node]) + + /// ... ... + case concatenation([Node]) + + /// (...) + case group(AST.Group.Kind, Node) + + /// (?(cond) true-branch | false-branch) + case conditional( + AST.Conditional.Condition.Kind, Node, Node) + + case quantification( + AST.Quantification.Amount, + AST.Quantification.Kind, + Node) + + case customCharacterClass(CustomCharacterClass) + + case atom(Atom) + + /// Comments, non-semantic whitespace, etc + // TODO: Do we want this? Could be interesting + case trivia(String) + + // TODO: Probably some atoms, built-ins, etc. + + case empty + + case stringLiteral(String) + + /// An embedded literal + case regexLiteral(AST.Node) + + // TODO: What should we do here? + case absentFunction(AST.AbsentFunction) + + // MARK: - Tree conversions + + /// The target of AST conversion. + /// + /// Keeps original AST around for rich syntatic and source information + case convertedRegexLiteral(Node, AST.Node) + + // MARK: - Extensibility points + + /// A capturing group (TODO: is it?) with a transformation function + case groupTransform( + AST.Group.Kind, + Node, + CaptureTransform) + + case consumer(_ConsumerInterface) + + case consumerValidator(_ConsumerValidatorInterface) + + // TODO: Would this just boil down to a consumer? + case characterPredicate(_CharacterPredicateInterface) + } +} + +extension DSLTree { + struct CustomCharacterClass { + var members: [Member] + var isInverted: Bool + + enum Member { + case atom(Atom) + case range(Atom, Atom) + case custom(CustomCharacterClass) + + indirect case intersection(CustomCharacterClass, CustomCharacterClass) + indirect case subtraction(CustomCharacterClass, CustomCharacterClass) + indirect case symmetricDifference(CustomCharacterClass, CustomCharacterClass) + } + } + + enum Atom { + case char(Character) + case scalar(Unicode.Scalar) + case any + + case assertion(AST.Atom.AssertionKind) + case backreference(AST.Reference) + + case unconverted(AST.Atom) + } +} + +// CollectionConsumer +typealias _ConsumerInterface = ( + String, Range +) -> String.Index? + +// Type producing consume +typealias _ConsumerValidatorInterface = ( + String, Range +) -> (Any, Any.Type, String.Index)? + +// Character-set (post grapheme segmentation) +typealias _CharacterPredicateInterface = ( + (Character) -> Bool +) + +/* + + TODO: Use of syntactic types, like group kinds, is a + little suspect. We may want to figure out a model here. + + TODO: Do capturing groups need explicit numbers? + + TODO: Are storing closures better/worse than existentials? + + */ + +extension DSLTree.Node { + var children: [DSLTree.Node]? { + switch self { + + case let .alternation(v): return v + case let .concatenation(v): return v + + case let .convertedRegexLiteral(n, _): + // Treat this transparently + return n.children + + case let .group(_, n): return [n] + case let .groupTransform(_, n, _): return [n] + case let .quantification(_, _, n): return [n] + + case let .conditional(_, t, f): return [t,f] + + case .trivia, .empty, .stringLiteral, .regexLiteral, + .consumer, .consumerValidator, .characterPredicate, + .customCharacterClass, .atom: + return [] + + case let .absentFunction(a): + return a.children.map(\.dslTreeNode) + } + } +} + +extension DSLTree.Node { + var astNode: AST.Node? { + switch self { + case let .regexLiteral(ast): return ast + case let .convertedRegexLiteral(_, ast): return ast + default: return nil + } + } +} + +extension AST.Node { + /// Converts an AST node to a `convertedRegexLiteral` node. + var dslTreeNode: DSLTree.Node { + func wrap(_ node: DSLTree.Node) -> DSLTree.Node { + switch node { + case .convertedRegexLiteral: + assertionFailure("Double wrapping?") + default: + break + } + // TODO: Should we do this for the + // single-concatenation child too, or should? + // we wrap _that_? + return .convertedRegexLiteral(node, self) + } + + // Convert the top-level node without wrapping + func convert() -> DSLTree.Node { + switch self { + case let .alternation(v): + let children = v.children.map(\.dslTreeNode) + return .alternation(children) + + case let .concatenation(v): + // Coalesce adjacent children who can produce a + // string literal representation + let astChildren = v.children + func coalesce( + _ idx: inout Array.Index + ) -> String? { + var result = "" + while idx < astChildren.endIndex { + let atom: AST.Atom? = astChildren[idx].as() + guard let str = atom?.literalStringValue else { + break + } + result += str + astChildren.formIndex(after: &idx) + } + return result.isEmpty ? nil : result + } + + // No need to nest single children concatenations + if astChildren.count == 1 { + return astChildren.first!.dslTreeNode + } + + // Check for a single child post-coalescing + var idx = astChildren.startIndex + if let str = coalesce(&idx), + idx == astChildren.endIndex + { + return .stringLiteral(str) + } + + // Coalesce adjacent string children + var curIdx = astChildren.startIndex + var children = Array() + while curIdx < astChildren.endIndex { + if let str = coalesce(&curIdx) { + // TODO: Track source info... + children.append(.stringLiteral(str)) + } else { + children.append(astChildren[curIdx].dslTreeNode) + children.formIndex(after: &curIdx) + } + } + return .concatenation(children) + + case let .group(v): + let child = v.child.dslTreeNode + return .group(v.kind.value, child) + + case let .conditional(v): + let trueBranch = v.trueBranch.dslTreeNode + let falseBranch = v.falseBranch.dslTreeNode + return .conditional( + v.condition.kind, trueBranch, falseBranch) + + case let .quantification(v): + let child = v.child.dslTreeNode + return .quantification( + v.amount.value, v.kind.value, child) + + case let .quote(v): + return .stringLiteral(v.literal) + + case let .trivia(v): + return .trivia(v.contents) + + case let .atom(v): + if let str = v.literalStringValue { + return .stringLiteral(str) + } + return .atom(v.dslTreeAtom) + + case let .customCharacterClass(ccc): + return .customCharacterClass(ccc.dslTreeClass) + + case .empty(_): + return .empty + + case let .groupTransform(v, transform): + let child = v.child.dslTreeNode + return .groupTransform( + v.kind.value, child, transform) + + case let .absentFunction(a): + // TODO: What should this map to? + return .absentFunction(a) + } + } + + return wrap(convert()) + } +} + +extension AST.CustomCharacterClass { + var dslTreeClass: DSLTree.CustomCharacterClass { + // TODO: Not quite 1-1 + func convert( + _ member: Member + ) -> DSLTree.CustomCharacterClass.Member { + switch member { + case let .custom(ccc): + return .custom(ccc.dslTreeClass) + + case let .range(r): + return .range( + r.lhs.dslTreeAtom, r.rhs.dslTreeAtom) + + case let .atom(a): + return .atom(a.dslTreeAtom) + + case let .quote(q): + // TODO: Probably should flatten instead of nest + return .custom(.init( + members: q.literal.map { .atom(.char($0)) }, + isInverted: false)) + + case let .setOperation(lhs, op, rhs): + let lhs = DSLTree.CustomCharacterClass( + members: lhs.map(convert), + isInverted: false) + let rhs = DSLTree.CustomCharacterClass( + members: rhs.map(convert), + isInverted: false) + + switch op.value { + case .subtraction: + return .subtraction(lhs, rhs) + case .intersection: + return .intersection(lhs, rhs) + case .symmetricDifference: + return .symmetricDifference(lhs, rhs) + } + } + } + + return .init( + members: members.map(convert), + isInverted: self.isInverted) + } +} + +extension AST.Atom { + var dslTreeAtom: DSLTree.Atom { + if let kind = assertionKind { + return .assertion(kind) + } + + switch self.kind { + case let .char(c): return .char(c) + case let .scalar(s): return .scalar(s) + case .any: return .any + case let .backreference(r): return .backreference(r) + + default: return .unconverted(self) + } + } +} + +extension DSLTree.Atom { + // Return the Character or promote a scalar to a Character + var literalCharacterValue: Character? { + switch self { + case let .char(c): return c + case let .scalar(s): return Character(s) + default: return nil + } + } +} From 8a4428eecedd8b7ef79f5928af47f746921890ad Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 31 Jan 2022 16:55:13 -0700 Subject: [PATCH 2/7] Bug fix in matching engine for reading subsequences out of bounds --- Sources/_MatchingEngine/Engine/Processor.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/_MatchingEngine/Engine/Processor.swift b/Sources/_MatchingEngine/Engine/Processor.swift index 184571d61..7adcc9fa2 100644 --- a/Sources/_MatchingEngine/Engine/Processor.swift +++ b/Sources/_MatchingEngine/Engine/Processor.swift @@ -93,6 +93,12 @@ extension Processor { } extension Processor { + var slice: Input.SubSequence { + // TODO: Should we whole-scale switch to slices, or + // does that depend on options for some anchors? + input[bounds] + } + // Advance in our input // // Returns whether the advance succeeded. On failure, our @@ -125,7 +131,7 @@ extension Processor { currentPosition < end ? input[currentPosition] : nil } func load(count: Int) -> Input.SubSequence? { - let slice = input[currentPosition...].prefix(count) + let slice = self.slice[currentPosition...].prefix(count) guard slice.count == count else { return nil } return slice } From 5befaa4dc224b48540d5f73534dfe775e4a78134 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 31 Jan 2022 16:55:53 -0700 Subject: [PATCH 3/7] Base DSL on DSLTree --- .../VariadicsGenerator.swift | 6 +- Sources/_StringProcessing/ByteCodeGen.swift | 12 +- Sources/_StringProcessing/Compiler.swift | 14 +- .../_StringProcessing/ConsumerInterface.swift | 2 +- .../_StringProcessing/PrintAsPattern.swift | 2 +- .../RegexDSL/Concatenation.swift | 4082 ++++++++--------- Sources/_StringProcessing/RegexDSL/Core.swift | 35 +- Sources/_StringProcessing/RegexDSL/DSL.swift | 31 +- .../_StringProcessing/RegexDSL/DSLTree.swift | 99 +- Tests/RegexTests/MatchTests.swift | 2 +- 10 files changed, 2187 insertions(+), 2098 deletions(-) diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index 4255d3fb1..29a7e2274 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -251,13 +251,13 @@ struct VariadicsGenerator: ParsableCommand { output(" init(") outputForEach(0.. m: - throw Unsupported( - "TODO: Should error out earlier, maybe DSL and parser has validation logic?") + // TODO: Should error out earlier, maybe DSL and parser + // has validation logic? + return case let (n, m) where m == nil || n <= m!: // Ok @@ -505,7 +507,7 @@ extension Compiler.ByteCodeGen { case let .atom(a): try emitAtom(a) - case let .stringLiteral(s): + case let .quotedLiteral(s): // TODO: Should this incorporate options? builder.buildMatchSequence(s) diff --git a/Sources/_StringProcessing/Compiler.swift b/Sources/_StringProcessing/Compiler.swift index b2331d7cd..881a8a898 100644 --- a/Sources/_StringProcessing/Compiler.swift +++ b/Sources/_StringProcessing/Compiler.swift @@ -17,19 +17,23 @@ struct RegexProgram { } class Compiler { - let ast: AST + let tree: DSLTree + + // TODO: Or are these stored on the tree? var options = MatchingOptions() init(ast: AST) { - self.ast = ast + self.tree = ast.dslTree + } + + init(tree: DSLTree) { + self.tree = tree } __consuming func emit() throws -> RegexProgram { // TODO: Handle global options - let converted = ast.root.dslTreeNode - var codegen = ByteCodeGen(options: options) - try codegen.emitNode(converted) + try codegen.emitNode(tree.root) let program = codegen.finish() return RegexProgram(program: program) } diff --git a/Sources/_StringProcessing/ConsumerInterface.swift b/Sources/_StringProcessing/ConsumerInterface.swift index 8b8e1dc64..85499048b 100644 --- a/Sources/_StringProcessing/ConsumerInterface.swift +++ b/Sources/_StringProcessing/ConsumerInterface.swift @@ -78,7 +78,7 @@ extension DSLTree.Node { case .customCharacterClass(let ccc): return try ccc.generateConsumer(opts) - case .stringLiteral: + case .quotedLiteral: // TODO: Should we handle this here? return nil diff --git a/Sources/_StringProcessing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift index b5f83f08a..44599e781 100644 --- a/Sources/_StringProcessing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -133,7 +133,7 @@ extension PrettyPrinter { case .empty: print("") - case let .stringLiteral(v): + case let .quotedLiteral(v): print(v._quoted) case .regexLiteral: diff --git a/Sources/_StringProcessing/RegexDSL/Concatenation.swift b/Sources/_StringProcessing/RegexDSL/Concatenation.swift index 2871fcd21..5cc08bd8d 100644 --- a/Sources/_StringProcessing/RegexDSL/Concatenation.swift +++ b/Sources/_StringProcessing/RegexDSL/Concatenation.swift @@ -173,10 +173,10 @@ public struct Concatenate2_TT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root + ])) } } @@ -194,10 +194,10 @@ public struct Concatenate2_TV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root + ])) } } @@ -215,10 +215,10 @@ public struct Concatenate2_VT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root + ])) } } @@ -236,10 +236,10 @@ public struct Concatenate2_VV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root + ])) } } @@ -259,11 +259,11 @@ public struct Concatenate3_TTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -281,11 +281,11 @@ public struct Concatenate3_TTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -303,11 +303,11 @@ public struct Concatenate3_TVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -325,11 +325,11 @@ public struct Concatenate3_TVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -347,11 +347,11 @@ public struct Concatenate3_VTT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -369,11 +369,11 @@ public struct Concatenate3_VTV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -391,11 +391,11 @@ public struct Concatenate3_VVT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -413,11 +413,11 @@ public struct Concatenate3_VVV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root + ])) } } @@ -437,12 +437,12 @@ public struct Concatenate4_TTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -460,12 +460,12 @@ public struct Concatenate4_TTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -483,12 +483,12 @@ public struct Concatenate4_TTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -506,12 +506,12 @@ public struct Concatenate4_TTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -529,12 +529,12 @@ public struct Concatenate4_TVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -552,12 +552,12 @@ public struct Concatenate4_TVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -575,12 +575,12 @@ public struct Concatenate4_TVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -598,12 +598,12 @@ public struct Concatenate4_TVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -621,12 +621,12 @@ public struct Concatenate4_VTTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -644,12 +644,12 @@ public struct Concatenate4_VTTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -667,12 +667,12 @@ public struct Concatenate4_VTVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -690,12 +690,12 @@ public struct Concatenate4_VTVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -713,12 +713,12 @@ public struct Concatenate4_VVTT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -736,12 +736,12 @@ public struct Concatenate4_VVTV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -759,12 +759,12 @@ public struct Concatenate4_VVVT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -782,12 +782,12 @@ public struct Concatenate4_VVVV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root + ])) } } @@ -807,13 +807,13 @@ public struct Concatenate5_TTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -831,13 +831,13 @@ public struct Concatenate5_TTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -855,13 +855,13 @@ public struct Concatenate5_TTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -879,13 +879,13 @@ public struct Concatenate5_TTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -903,13 +903,13 @@ public struct Concatenate5_TTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -927,13 +927,13 @@ public struct Concatenate5_TTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -951,13 +951,13 @@ public struct Concatenate5_TTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -975,13 +975,13 @@ public struct Concatenate5_TTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -999,13 +999,13 @@ public struct Concatenate5_TVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1023,13 +1023,13 @@ public struct Concatenate5_TVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1047,13 +1047,13 @@ public struct Concatenate5_TVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1071,13 +1071,13 @@ public struct Concatenate5_TVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1095,13 +1095,13 @@ public struct Concatenate5_TVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1119,13 +1119,13 @@ public struct Concatenate5_TVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1143,13 +1143,13 @@ public struct Concatenate5_TVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1167,13 +1167,13 @@ public struct Concatenate5_TVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1191,13 +1191,13 @@ public struct Concatenate5_VTTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1215,13 +1215,13 @@ public struct Concatenate5_VTTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1239,13 +1239,13 @@ public struct Concatenate5_VTTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1263,13 +1263,13 @@ public struct Concatenate5_VTTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1287,13 +1287,13 @@ public struct Concatenate5_VTVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1311,13 +1311,13 @@ public struct Concatenate5_VTVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1335,13 +1335,13 @@ public struct Concatenate5_VTVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1359,13 +1359,13 @@ public struct Concatenate5_VTVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1383,13 +1383,13 @@ public struct Concatenate5_VVTTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1407,13 +1407,13 @@ public struct Concatenate5_VVTTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1431,13 +1431,13 @@ public struct Concatenate5_VVTVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1455,13 +1455,13 @@ public struct Concatenate5_VVTVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1479,13 +1479,13 @@ public struct Concatenate5_VVVTT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1503,13 +1503,13 @@ public struct Concatenate5_VVVTV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1527,13 +1527,13 @@ public struct Concatenate5_VVVVT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1551,13 +1551,13 @@ public struct Concatenate5_VVVVV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root + ])) } } @@ -1577,14 +1577,14 @@ public struct Concatenate6_TTTTTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1602,14 +1602,14 @@ public struct Concatenate6_TTTTTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1627,14 +1627,14 @@ public struct Concatenate6_TTTTVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1652,14 +1652,14 @@ public struct Concatenate6_TTTTVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1677,14 +1677,14 @@ public struct Concatenate6_TTTVTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1702,14 +1702,14 @@ public struct Concatenate6_TTTVTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1727,14 +1727,14 @@ public struct Concatenate6_TTTVVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1752,14 +1752,14 @@ public struct Concatenate6_TTTVVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1777,14 +1777,14 @@ public struct Concatenate6_TTVTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1802,14 +1802,14 @@ public struct Concatenate6_TTVTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1827,14 +1827,14 @@ public struct Concatenate6_TTVTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1852,14 +1852,14 @@ public struct Concatenate6_TTVTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1877,14 +1877,14 @@ public struct Concatenate6_TTVVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1902,14 +1902,14 @@ public struct Concatenate6_TTVVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1927,14 +1927,14 @@ public struct Concatenate6_TTVVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1952,14 +1952,14 @@ public struct Concatenate6_TTVVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -1977,14 +1977,14 @@ public struct Concatenate6_TVTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2002,14 +2002,14 @@ public struct Concatenate6_TVTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2027,14 +2027,14 @@ public struct Concatenate6_TVTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2052,14 +2052,14 @@ public struct Concatenate6_TVTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2077,14 +2077,14 @@ public struct Concatenate6_TVTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2102,14 +2102,14 @@ public struct Concatenate6_TVTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2127,14 +2127,14 @@ public struct Concatenate6_TVTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2152,14 +2152,14 @@ public struct Concatenate6_TVTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2177,14 +2177,14 @@ public struct Concatenate6_TVVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2202,14 +2202,14 @@ public struct Concatenate6_TVVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2227,14 +2227,14 @@ public struct Concatenate6_TVVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2252,14 +2252,14 @@ public struct Concatenate6_TVVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2277,14 +2277,14 @@ public struct Concatenate6_TVVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2302,14 +2302,14 @@ public struct Concatenate6_TVVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2327,14 +2327,14 @@ public struct Concatenate6_TVVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2352,14 +2352,14 @@ public struct Concatenate6_TVVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2377,14 +2377,14 @@ public struct Concatenate6_VTTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2402,14 +2402,14 @@ public struct Concatenate6_VTTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2427,14 +2427,14 @@ public struct Concatenate6_VTTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2452,14 +2452,14 @@ public struct Concatenate6_VTTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2477,14 +2477,14 @@ public struct Concatenate6_VTTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2502,14 +2502,14 @@ public struct Concatenate6_VTTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2527,14 +2527,14 @@ public struct Concatenate6_VTTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2552,14 +2552,14 @@ public struct Concatenate6_VTTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2577,14 +2577,14 @@ public struct Concatenate6_VTVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2602,14 +2602,14 @@ public struct Concatenate6_VTVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2627,14 +2627,14 @@ public struct Concatenate6_VTVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2652,14 +2652,14 @@ public struct Concatenate6_VTVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2677,14 +2677,14 @@ public struct Concatenate6_VTVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2702,14 +2702,14 @@ public struct Concatenate6_VTVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2727,14 +2727,14 @@ public struct Concatenate6_VTVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2752,14 +2752,14 @@ public struct Concatenate6_VTVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2777,14 +2777,14 @@ public struct Concatenate6_VVTTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2802,14 +2802,14 @@ public struct Concatenate6_VVTTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2827,14 +2827,14 @@ public struct Concatenate6_VVTTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2852,14 +2852,14 @@ public struct Concatenate6_VVTTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2877,14 +2877,14 @@ public struct Concatenate6_VVTVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2902,14 +2902,14 @@ public struct Concatenate6_VVTVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2927,14 +2927,14 @@ public struct Concatenate6_VVTVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2952,14 +2952,14 @@ public struct Concatenate6_VVTVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -2977,14 +2977,14 @@ public struct Concatenate6_VVVTTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3002,14 +3002,14 @@ public struct Concatenate6_VVVTTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3027,14 +3027,14 @@ public struct Concatenate6_VVVTVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3052,14 +3052,14 @@ public struct Concatenate6_VVVTVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3077,14 +3077,14 @@ public struct Concatenate6_VVVVTT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3102,14 +3102,14 @@ public struct Concatenate6_VVVVTV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3127,14 +3127,14 @@ public struct Concatenate6_VVVVVT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3152,14 +3152,14 @@ public struct Concatenate6_VVVVVV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root + ])) } } @@ -3179,15 +3179,15 @@ public struct Concatenate7_TTTTTTT< public typealias Match = Tuple8 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3205,15 +3205,15 @@ public struct Concatenate7_TTTTTTV< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3231,15 +3231,15 @@ public struct Concatenate7_TTTTTVT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3257,15 +3257,15 @@ public struct Concatenate7_TTTTTVV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3283,15 +3283,15 @@ public struct Concatenate7_TTTTVTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3309,15 +3309,15 @@ public struct Concatenate7_TTTTVTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3335,15 +3335,15 @@ public struct Concatenate7_TTTTVVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3361,15 +3361,15 @@ public struct Concatenate7_TTTTVVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3387,15 +3387,15 @@ public struct Concatenate7_TTTVTTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3413,15 +3413,15 @@ public struct Concatenate7_TTTVTTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3439,15 +3439,15 @@ public struct Concatenate7_TTTVTVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3465,15 +3465,15 @@ public struct Concatenate7_TTTVTVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3491,15 +3491,15 @@ public struct Concatenate7_TTTVVTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3517,15 +3517,15 @@ public struct Concatenate7_TTTVVTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3543,15 +3543,15 @@ public struct Concatenate7_TTTVVVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3569,15 +3569,15 @@ public struct Concatenate7_TTTVVVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3595,15 +3595,15 @@ public struct Concatenate7_TTVTTTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3621,15 +3621,15 @@ public struct Concatenate7_TTVTTTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3647,15 +3647,15 @@ public struct Concatenate7_TTVTTVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3673,15 +3673,15 @@ public struct Concatenate7_TTVTTVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3699,15 +3699,15 @@ public struct Concatenate7_TTVTVTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3725,15 +3725,15 @@ public struct Concatenate7_TTVTVTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3751,15 +3751,15 @@ public struct Concatenate7_TTVTVVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3777,15 +3777,15 @@ public struct Concatenate7_TTVTVVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3803,15 +3803,15 @@ public struct Concatenate7_TTVVTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3829,15 +3829,15 @@ public struct Concatenate7_TTVVTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3855,15 +3855,15 @@ public struct Concatenate7_TTVVTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3881,15 +3881,15 @@ public struct Concatenate7_TTVVTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3907,15 +3907,15 @@ public struct Concatenate7_TTVVVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3933,15 +3933,15 @@ public struct Concatenate7_TTVVVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3959,15 +3959,15 @@ public struct Concatenate7_TTVVVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -3985,15 +3985,15 @@ public struct Concatenate7_TTVVVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4011,15 +4011,15 @@ public struct Concatenate7_TVTTTTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4037,15 +4037,15 @@ public struct Concatenate7_TVTTTTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4063,15 +4063,15 @@ public struct Concatenate7_TVTTTVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4089,15 +4089,15 @@ public struct Concatenate7_TVTTTVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4115,15 +4115,15 @@ public struct Concatenate7_TVTTVTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4141,15 +4141,15 @@ public struct Concatenate7_TVTTVTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4167,15 +4167,15 @@ public struct Concatenate7_TVTTVVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4193,15 +4193,15 @@ public struct Concatenate7_TVTTVVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4219,15 +4219,15 @@ public struct Concatenate7_TVTVTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4245,15 +4245,15 @@ public struct Concatenate7_TVTVTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4271,15 +4271,15 @@ public struct Concatenate7_TVTVTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4297,15 +4297,15 @@ public struct Concatenate7_TVTVTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4323,15 +4323,15 @@ public struct Concatenate7_TVTVVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4349,15 +4349,15 @@ public struct Concatenate7_TVTVVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4375,15 +4375,15 @@ public struct Concatenate7_TVTVVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4401,15 +4401,15 @@ public struct Concatenate7_TVTVVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4427,15 +4427,15 @@ public struct Concatenate7_TVVTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4453,15 +4453,15 @@ public struct Concatenate7_TVVTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4479,15 +4479,15 @@ public struct Concatenate7_TVVTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4505,15 +4505,15 @@ public struct Concatenate7_TVVTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4531,15 +4531,15 @@ public struct Concatenate7_TVVTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4557,15 +4557,15 @@ public struct Concatenate7_TVVTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4583,15 +4583,15 @@ public struct Concatenate7_TVVTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4609,15 +4609,15 @@ public struct Concatenate7_TVVTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4635,15 +4635,15 @@ public struct Concatenate7_TVVVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4661,15 +4661,15 @@ public struct Concatenate7_TVVVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4687,15 +4687,15 @@ public struct Concatenate7_TVVVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4713,15 +4713,15 @@ public struct Concatenate7_TVVVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4739,15 +4739,15 @@ public struct Concatenate7_TVVVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4765,15 +4765,15 @@ public struct Concatenate7_TVVVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4791,15 +4791,15 @@ public struct Concatenate7_TVVVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4817,15 +4817,15 @@ public struct Concatenate7_TVVVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4843,15 +4843,15 @@ public struct Concatenate7_VTTTTTT< public typealias Match = Tuple7 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4869,15 +4869,15 @@ public struct Concatenate7_VTTTTTV< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4895,15 +4895,15 @@ public struct Concatenate7_VTTTTVT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4921,15 +4921,15 @@ public struct Concatenate7_VTTTTVV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4947,15 +4947,15 @@ public struct Concatenate7_VTTTVTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4973,15 +4973,15 @@ public struct Concatenate7_VTTTVTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -4999,15 +4999,15 @@ public struct Concatenate7_VTTTVVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5025,15 +5025,15 @@ public struct Concatenate7_VTTTVVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5051,15 +5051,15 @@ public struct Concatenate7_VTTVTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5077,15 +5077,15 @@ public struct Concatenate7_VTTVTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5103,15 +5103,15 @@ public struct Concatenate7_VTTVTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5129,15 +5129,15 @@ public struct Concatenate7_VTTVTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5155,15 +5155,15 @@ public struct Concatenate7_VTTVVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5181,15 +5181,15 @@ public struct Concatenate7_VTTVVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5207,15 +5207,15 @@ public struct Concatenate7_VTTVVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5233,15 +5233,15 @@ public struct Concatenate7_VTTVVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5259,15 +5259,15 @@ public struct Concatenate7_VTVTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5285,15 +5285,15 @@ public struct Concatenate7_VTVTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5311,15 +5311,15 @@ public struct Concatenate7_VTVTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5337,15 +5337,15 @@ public struct Concatenate7_VTVTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5363,15 +5363,15 @@ public struct Concatenate7_VTVTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5389,15 +5389,15 @@ public struct Concatenate7_VTVTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5415,15 +5415,15 @@ public struct Concatenate7_VTVTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5441,15 +5441,15 @@ public struct Concatenate7_VTVTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5467,15 +5467,15 @@ public struct Concatenate7_VTVVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5493,15 +5493,15 @@ public struct Concatenate7_VTVVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5519,15 +5519,15 @@ public struct Concatenate7_VTVVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5545,15 +5545,15 @@ public struct Concatenate7_VTVVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5571,15 +5571,15 @@ public struct Concatenate7_VTVVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5597,15 +5597,15 @@ public struct Concatenate7_VTVVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5623,15 +5623,15 @@ public struct Concatenate7_VTVVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5649,15 +5649,15 @@ public struct Concatenate7_VTVVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5675,15 +5675,15 @@ public struct Concatenate7_VVTTTTT< public typealias Match = Tuple6 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5701,15 +5701,15 @@ public struct Concatenate7_VVTTTTV< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5727,15 +5727,15 @@ public struct Concatenate7_VVTTTVT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5753,15 +5753,15 @@ public struct Concatenate7_VVTTTVV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5779,15 +5779,15 @@ public struct Concatenate7_VVTTVTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5805,15 +5805,15 @@ public struct Concatenate7_VVTTVTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5831,15 +5831,15 @@ public struct Concatenate7_VVTTVVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5857,15 +5857,15 @@ public struct Concatenate7_VVTTVVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5883,15 +5883,15 @@ public struct Concatenate7_VVTVTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5909,15 +5909,15 @@ public struct Concatenate7_VVTVTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5935,15 +5935,15 @@ public struct Concatenate7_VVTVTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5961,15 +5961,15 @@ public struct Concatenate7_VVTVTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -5987,15 +5987,15 @@ public struct Concatenate7_VVTVVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6013,15 +6013,15 @@ public struct Concatenate7_VVTVVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6039,15 +6039,15 @@ public struct Concatenate7_VVTVVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6065,15 +6065,15 @@ public struct Concatenate7_VVTVVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6091,15 +6091,15 @@ public struct Concatenate7_VVVTTTT< public typealias Match = Tuple5 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6117,15 +6117,15 @@ public struct Concatenate7_VVVTTTV< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6143,15 +6143,15 @@ public struct Concatenate7_VVVTTVT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6169,15 +6169,15 @@ public struct Concatenate7_VVVTTVV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6195,15 +6195,15 @@ public struct Concatenate7_VVVTVTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6221,15 +6221,15 @@ public struct Concatenate7_VVVTVTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6247,15 +6247,15 @@ public struct Concatenate7_VVVTVVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6273,15 +6273,15 @@ public struct Concatenate7_VVVTVVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6299,15 +6299,15 @@ public struct Concatenate7_VVVVTTT< public typealias Match = Tuple4 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6325,15 +6325,15 @@ public struct Concatenate7_VVVVTTV< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6351,15 +6351,15 @@ public struct Concatenate7_VVVVTVT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6377,15 +6377,15 @@ public struct Concatenate7_VVVVTVV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6403,15 +6403,15 @@ public struct Concatenate7_VVVVVTT< public typealias Match = Tuple3 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6429,15 +6429,15 @@ public struct Concatenate7_VVVVVTV< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6455,15 +6455,15 @@ public struct Concatenate7_VVVVVVT< public typealias Match = Tuple2 public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6481,15 +6481,15 @@ public struct Concatenate7_VVVVVVV< public typealias Match = Substring public let regex: Regex init(_ x0: T0, _ x1: T1, _ x2: T2, _ x3: T3, _ x4: T4, _ x5: T5, _ x6: T6) { - regex = .init(ast: concat( - x0.regex.ast.root, - x1.regex.ast.root, - x2.regex.ast.root, - x3.regex.ast.root, - x4.regex.ast.root, - x5.regex.ast.root, - x6.regex.ast.root - )) + regex = .init(node: .concatenation([ + x0.regex.root, + x1.regex.root, + x2.regex.root, + x3.regex.root, + x4.regex.root, + x5.regex.root, + x6.regex.root + ])) } } @@ -6503,4 +6503,4 @@ extension RegexBuilder { -// END AUTO-GENERATED CONTENT +// END AUTO-GENERATED CONTENT \ No newline at end of file diff --git a/Sources/_StringProcessing/RegexDSL/Core.swift b/Sources/_StringProcessing/RegexDSL/Core.swift index 9b1e6e6af..99e99da7d 100644 --- a/Sources/_StringProcessing/RegexDSL/Core.swift +++ b/Sources/_StringProcessing/RegexDSL/Core.swift @@ -54,26 +54,45 @@ public struct Regex: RegexProtocol { /// A program representation that caches any lowered representation for /// execution. internal class Program { - /// The underlying AST. - let ast: AST + /// The underlying IR. + /// + /// FIXME: If Regex is the unit of composition, then it should be a Node instead, + /// and we should have a separate type that handled both global options and, + /// likely, compilation/caching. + let tree: DSLTree + /// The legacy `RECode` for execution with a legacy VM. lazy private(set) var legacyLoweredProgram: RECode = { do { + guard let ast = tree.ast else { + throw "Extended support unavailable in legacy VM" + } return try compile(ast) } catch { fatalError("Regex engine internal error: \(String(describing: error))") } }() /// The program for execution with the matching engine. - lazy private(set) var loweredProgram = try! Compiler(ast: ast).emit() + lazy private(set) var loweredProgram = try! Compiler(tree: tree).emit() init(ast: AST) { - self.ast = ast + self.tree = ast.dslTree + } + init(tree: DSLTree) { + self.tree = tree } } let program: Program - var ast: AST { program.ast } +// var ast: AST { program.ast } + + var root: DSLTree.Node { + program.tree.root + } + + var hasCapture: Bool { + program.tree.hasCapture + } init(ast: AST) { self.program = Program(ast: ast) @@ -82,6 +101,10 @@ public struct Regex: RegexProtocol { self.program = Program(ast: .init(ast, globalOptions: nil)) } + init(node: DSLTree.Node) { + self.program = Program(tree: .init(node, options: nil)) + } + // Compiler interface. Do not change independently. @usableFromInline init(_regexString pattern: String) { @@ -139,7 +162,7 @@ extension RegexProtocol { return unsafeBitCast(x, to: Match.self) } // TODO: Remove this branch when the matching engine supports captures. - if regex.ast.hasCapture { + if regex.hasCapture { let vm = HareVM(program: regex.program.legacyLoweredProgram) guard let (range, captures) = vm.execute( input: input, in: inputRange, mode: mode diff --git a/Sources/_StringProcessing/RegexDSL/DSL.swift b/Sources/_StringProcessing/RegexDSL/DSL.swift index fde14a674..d90af6db8 100644 --- a/Sources/_StringProcessing/RegexDSL/DSL.swift +++ b/Sources/_StringProcessing/RegexDSL/DSL.swift @@ -66,8 +66,8 @@ public struct OneOrMore: RegexProtocolWithComponent { public let regex: Regex public init(component: Component) { - self.regex = .init(ast: - oneOrMore(of: component.regex.ast.root) + self.regex = .init(node: .quantification( + .oneOrMore, .eager, component.regex.root) ) } @@ -92,8 +92,8 @@ public struct Repeat< public let regex: Regex public init(component: Component) { - self.regex = .init(ast: - zeroOrMore(of: component.regex.ast.root)) + self.regex = .init(node: .quantification( + .zeroOrMore, .eager, component.regex.root)) } public init(@RegexBuilder _ content: () -> Component) { @@ -115,8 +115,8 @@ public struct Optionally: RegexProtocolWithComponent { public let regex: Regex public init(component: Component) { - self.regex = .init(ast: - zeroOrOne(of: component.regex.ast.root)) + self.regex = .init(node: .quantification( + .zeroOrOne, .eager, component.regex.root)) } public init(@RegexBuilder _ content: () -> Component) { @@ -141,9 +141,9 @@ public struct Alternation< public let regex: Regex public init(_ first: Component1, _ second: Component2) { - regex = .init(ast: alt( - first.regex.ast.root, second.regex.ast.root - )) + regex = .init(node: .alternation([ + first.regex.root, second.regex.root + ])) } public init( @@ -167,19 +167,18 @@ public struct CapturingGroup: RegexProtocol { init( _ component: Component ) { - self.regex = .init(ast: - group(.capture, component.regex.ast.root) - ) + self.regex = .init(node: .group( + .capture, component.regex.root)) } init( _ component: Component, transform: CaptureTransform ) { - self.regex = .init( - ast: .groupTransform( - .init(.init(faking: .capture), component.regex.ast.root, .fake), - transform: transform)) + self.regex = .init(node: .groupTransform( + .capture, + component.regex.root, + transform)) } init( diff --git a/Sources/_StringProcessing/RegexDSL/DSLTree.swift b/Sources/_StringProcessing/RegexDSL/DSLTree.swift index 14e74266f..e5f426c3d 100644 --- a/Sources/_StringProcessing/RegexDSL/DSLTree.swift +++ b/Sources/_StringProcessing/RegexDSL/DSLTree.swift @@ -11,7 +11,15 @@ import _MatchingEngine -struct DSLTree {} +struct DSLTree { + var root: Node + var options: Options? + + init(_ r: Node, options: Options?) { + self.root = r + self.options = options + } +} extension DSLTree { indirect enum Node: _TreeNode { @@ -45,7 +53,7 @@ extension DSLTree { case empty - case stringLiteral(String) + case quotedLiteral(String) /// An embedded literal case regexLiteral(AST.Node) @@ -148,7 +156,7 @@ extension DSLTree.Node { case let .conditional(_, t, f): return [t,f] - case .trivia, .empty, .stringLiteral, .regexLiteral, + case .trivia, .empty, .quotedLiteral, .regexLiteral, .consumer, .consumerValidator, .characterPredicate, .customCharacterClass, .atom: return [] @@ -175,7 +183,9 @@ extension AST.Node { func wrap(_ node: DSLTree.Node) -> DSLTree.Node { switch node { case .convertedRegexLiteral: - assertionFailure("Double wrapping?") + // FIXME: how can this happen? +// assertionFailure("Double wrapping?") + return node default: break } @@ -197,18 +207,23 @@ extension AST.Node { // string literal representation let astChildren = v.children func coalesce( - _ idx: inout Array.Index - ) -> String? { + _ idx: Array.Index + ) -> (Array.Index, String)? { var result = "" + var idx = idx while idx < astChildren.endIndex { let atom: AST.Atom? = astChildren[idx].as() - guard let str = atom?.literalStringValue else { + + // TODO: For printing, nice to coalesce + // scalars literals too. We likely need a different + // approach even before we have a better IR. + guard let char = atom?.singleCharacter else { break } - result += str + result.append(char) astChildren.formIndex(after: &idx) } - return result.isEmpty ? nil : result + return result.count <= 1 ? nil : (idx, result) } // No need to nest single children concatenations @@ -217,20 +232,20 @@ extension AST.Node { } // Check for a single child post-coalescing - var idx = astChildren.startIndex - if let str = coalesce(&idx), + if let (idx, str) = coalesce(astChildren.startIndex), idx == astChildren.endIndex { - return .stringLiteral(str) + return .quotedLiteral(str) } // Coalesce adjacent string children var curIdx = astChildren.startIndex var children = Array() while curIdx < astChildren.endIndex { - if let str = coalesce(&curIdx) { + if let (nextIdx, str) = coalesce(curIdx) { // TODO: Track source info... - children.append(.stringLiteral(str)) + children.append(.quotedLiteral(str)) + curIdx = nextIdx } else { children.append(astChildren[curIdx].dslTreeNode) children.formIndex(after: &curIdx) @@ -254,15 +269,12 @@ extension AST.Node { v.amount.value, v.kind.value, child) case let .quote(v): - return .stringLiteral(v.literal) + return .quotedLiteral(v.literal) case let .trivia(v): return .trivia(v.contents) case let .atom(v): - if let str = v.literalStringValue { - return .stringLiteral(str) - } return .atom(v.dslTreeAtom) case let .customCharacterClass(ccc): @@ -282,7 +294,8 @@ extension AST.Node { } } - return wrap(convert()) + let converted = convert() + return wrap(converted) } } @@ -361,3 +374,51 @@ extension DSLTree.Atom { } } } + +extension DSLTree { + struct Options { + // TBD + } +} + +extension DSLTree { + var ast: AST? { + guard let root = root.astNode else { + return nil + } + // TODO: Options mapping + return AST(root, globalOptions: nil) + } +} + +extension AST.GlobalMatchingOptionSequence { + var dslTreeOptions: DSLTree.Options { + // TODO: map options + return .init() + } +} + +extension AST { + var dslTree: DSLTree { + return DSLTree( + root.dslTreeNode, options: globalOptions?.dslTreeOptions) + } +} + +extension DSLTree { + var hasCapture: Bool { + root.hasCapture + } +} +extension DSLTree.Node { + var hasCapture: Bool { + switch self { + case .group(let k, _) where k.isCapturing, + .groupTransform(let k, _, _) where k.isCapturing: + return true + default: + break + } + return self.children?.any(\.hasCapture) ?? false + } +} diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index e29907d8c..6248698fa 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -1147,7 +1147,7 @@ extension RegexTests { // Expectation: A standalone Unicode scalar value in a regex literal // can match either that specific scalar value or participate in matching // as a character. - + firstMatchTest(#"\u{65}\u{301}$"#, input: eDecomposed, match: eDecomposed) // FIXME: Decomposed character in regex literal doesn't match an equivalent character firstMatchTest(#"\u{65}\u{301}$"#, input: eComposed, match: eComposed, From 3fb53591a6e109fb4c0527542fa403f943e237a3 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 1 Feb 2022 16:38:29 -0700 Subject: [PATCH 4/7] DSLTree support for CaptureStructure --- .../Regex/Parse/CaptureStructure.swift | 185 ++++++++++++------ .../_MatchingEngine/Regex/TreeProtocols.swift | 2 + .../_StringProcessing/RegexDSL/DSLTree.swift | 55 ++++++ 3 files changed, 183 insertions(+), 59 deletions(-) diff --git a/Sources/_MatchingEngine/Regex/Parse/CaptureStructure.swift b/Sources/_MatchingEngine/Regex/Parse/CaptureStructure.swift index e5fd2470c..0702715fb 100644 --- a/Sources/_MatchingEngine/Regex/Parse/CaptureStructure.swift +++ b/Sources/_MatchingEngine/Regex/Parse/CaptureStructure.swift @@ -25,71 +25,138 @@ public enum CaptureStructure: Equatable { } } +extension CaptureStructure { + public init( + alternating children: C + ) where C.Element: _TreeNode { + assert(children.count > 1) + self = children + .map(\.captureStructure) + .reduce(.empty, +) + .map(CaptureStructure.optional) + } + public init( + concatenating children: C + ) where C.Element: _TreeNode { + self = children.map(\.captureStructure).reduce(.empty, +) + } + + public init( + grouping child: T, as kind: AST.Group.Kind + ) { + let innerCaptures = child.captureStructure + switch kind { + case .capture: + self = .atom() + innerCaptures + case .namedCapture(let name): + self = .atom(name: name.value) + innerCaptures + case .balancedCapture(let b): + self = .atom(name: b.name?.value) + innerCaptures + default: + precondition(!kind.isCapturing) + self = innerCaptures + } + } + + public init( + grouping child: T, + as kind: AST.Group.Kind, + withTransform transform: CaptureTransform + ) { + let innerCaptures = child.captureStructure + switch kind { + case .capture: + self = .atom(type: AnyType(transform.resultType)) + innerCaptures + case .namedCapture(let name): + self = .atom(name: name.value, type: AnyType(transform.resultType)) + + innerCaptures + default: + self = innerCaptures + } + } + + // TODO: We'll likely want/need a generalization of + // conditional's condition kind. + public init( + condition: AST.Conditional.Condition.Kind, + trueBranch: T, + falseBranch: T + ) { + // A conditional's capture structure is effectively that of an alternation + // between the true and false branches. However the condition may also + // have captures in the case of a group condition. + var captures = CaptureStructure.empty + switch condition { + case .group(let g): + captures = captures + AST.Node.group(g).captureStructure + default: + break + } + let branchCaptures = trueBranch.captureStructure + + falseBranch.captureStructure + self = captures + branchCaptures.map( + CaptureStructure.optional) + } + + public init( + quantifying child: T, amount: AST.Quantification.Amount + ) { + self = child.captureStructure.map( + amount == .zeroOrOne + ? CaptureStructure.optional + : CaptureStructure.array) + } + + // TODO: Will need to adjust for DSLTree support, and + // "absent" isn't the best name for these. + public init( + absent kind: AST.AbsentFunction.Kind + ) { + // Only the child of an expression absent function is relevant, as the + // other expressions don't actually get matched against. + switch kind { + case .expression(_, _, let child): + self = child.captureStructure + case .clearer, .repeater, .stopper: + self = .empty + } + } + +} + extension AST.Node { public var captureStructure: CaptureStructure { // Note: This implementation could be more optimized. switch self { - case .alternation(let alternation): - assert(alternation.children.count > 1) - return alternation.children - .map(\.captureStructure) - .reduce(.empty, +) - .map(CaptureStructure.optional) - case .concatenation(let concatenation): - return concatenation.children.map(\.captureStructure).reduce(.empty, +) - case .group(let group): - let innerCaptures = group.child.captureStructure - switch group.kind.value { - case .capture: - return .atom() + innerCaptures - case .namedCapture(let name): - return .atom(name: name.value) + innerCaptures - case .balancedCapture(let b): - return .atom(name: b.name?.value) + innerCaptures - default: - precondition(!group.kind.value.isCapturing) - return innerCaptures - } - case .groupTransform(let group, let transform): - let innerCaptures = group.child.captureStructure - switch group.kind.value { - case .capture: - return .atom(type: AnyType(transform.resultType)) + innerCaptures - case .namedCapture(let name): - return .atom(name: name.value, type: AnyType(transform.resultType)) - + innerCaptures - default: - return innerCaptures - } + case let .alternation(a): + return CaptureStructure(alternating: a.children) + + case let .concatenation(c): + return CaptureStructure(concatenating: c.children) + + case let .group(g): + return CaptureStructure( + grouping: g.child, as: g.kind.value) + + case .groupTransform(let g, let transform): + return CaptureStructure( + grouping: g.child, + as: g.kind.value, + withTransform: transform) + case .conditional(let c): - // A conditional's capture structure is effectively that of an alternation - // between the true and false branches. However the condition may also - // have captures in the case of a group condition. - var captures = CaptureStructure.empty - switch c.condition.kind { - case .group(let g): - captures = captures + AST.Node.group(g).captureStructure - default: - break - } - let branchCaptures = c.trueBranch.captureStructure + - c.falseBranch.captureStructure - return captures + branchCaptures.map(CaptureStructure.optional) - - case .quantification(let quantification): - return quantification.child.captureStructure.map( - quantification.amount.value == .zeroOrOne - ? CaptureStructure.optional - : CaptureStructure.array) + return CaptureStructure( + condition: c.condition.kind, + trueBranch: c.trueBranch, + falseBranch: c.falseBranch) + + case .quantification(let q): + return CaptureStructure( + quantifying: q.child, amount: q.amount.value) + case .absentFunction(let abs): - // Only the child of an expression absent function is relevant, as the - // other expressions don't actually get matched against. - switch abs.kind { - case .expression(_, _, let child): - return child.captureStructure - case .clearer, .repeater, .stopper: - return .empty - } + return CaptureStructure(absent: abs.kind) + case .quote, .trivia, .atom, .customCharacterClass, .empty: return .empty } diff --git a/Sources/_MatchingEngine/Regex/TreeProtocols.swift b/Sources/_MatchingEngine/Regex/TreeProtocols.swift index 7f1ccb5f7..5e9770ca6 100644 --- a/Sources/_MatchingEngine/Regex/TreeProtocols.swift +++ b/Sources/_MatchingEngine/Regex/TreeProtocols.swift @@ -2,6 +2,8 @@ public protocol _TreeNode { var children: [Self]? { get } + + var captureStructure: CaptureStructure { get } } extension _TreeNode { diff --git a/Sources/_StringProcessing/RegexDSL/DSLTree.swift b/Sources/_StringProcessing/RegexDSL/DSLTree.swift index e5f426c3d..ab35ea588 100644 --- a/Sources/_StringProcessing/RegexDSL/DSLTree.swift +++ b/Sources/_StringProcessing/RegexDSL/DSLTree.swift @@ -33,6 +33,8 @@ extension DSLTree { case group(AST.Group.Kind, Node) /// (?(cond) true-branch | false-branch) + /// + /// TODO: Consider splitting off grouped conditions, or have our own kind case conditional( AST.Conditional.Condition.Kind, Node, Node) @@ -59,6 +61,8 @@ extension DSLTree { case regexLiteral(AST.Node) // TODO: What should we do here? + /// + /// TODO: Consider splitting off expression functions, or have our own kind case absentFunction(AST.AbsentFunction) // MARK: - Tree conversions @@ -422,3 +426,54 @@ extension DSLTree.Node { return self.children?.any(\.hasCapture) ?? false } } + +extension DSLTree { + var captureStructure: CaptureStructure { + root.captureStructure + } +} +extension DSLTree.Node { + var captureStructure: CaptureStructure { + switch self { + case let .alternation(children): + return CaptureStructure(alternating: children) + + case let .concatenation(children): + return CaptureStructure(concatenating: children) + + case let .group(kind, child): + return CaptureStructure(grouping: child, as: kind) + + case let .groupTransform(kind, child, transform): + return CaptureStructure( + grouping: child, as: kind, withTransform: transform) + + case let .conditional(cond, trueBranch, falseBranch): + return CaptureStructure( + condition: cond, + trueBranch: trueBranch, + falseBranch: falseBranch) + + case let .quantification(amount, _, child): + return CaptureStructure( + quantifying: child, amount: amount) + + case let .regexLiteral(re): + return re.captureStructure + + case let .absentFunction(abs): + return CaptureStructure(absent: abs.kind) + + case let .convertedRegexLiteral(n, _): + return n.captureStructure + + case .consumerValidator: + // FIXME: This is where we make a capture! + return .empty + + case .customCharacterClass, .atom, .trivia, .empty, + .quotedLiteral, .consumer, .characterPredicate: + return .empty + } + } +} From eb6a39ce37de1e8ea5690e2beba2faae059f8d40 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 1 Feb 2022 17:06:24 -0700 Subject: [PATCH 5/7] DSLTree hooked up to legacy VMs --- .../_StringProcessing/CharacterClass.swift | 95 +++++++++++++++++++ .../Legacy/LegacyCompile.swift | 67 +++++++------ Sources/_StringProcessing/RegexDSL/Core.swift | 6 +- .../_StringProcessing/RegexDSL/DSLTree.swift | 9 +- 4 files changed, 143 insertions(+), 34 deletions(-) diff --git a/Sources/_StringProcessing/CharacterClass.swift b/Sources/_StringProcessing/CharacterClass.swift index 92b2a76b9..e282afe5d 100644 --- a/Sources/_StringProcessing/CharacterClass.swift +++ b/Sources/_StringProcessing/CharacterClass.swift @@ -323,6 +323,22 @@ extension AST.Node { } } +extension DSLTree.Node { + var characterClass: CharacterClass? { + switch self { + case let .customCharacterClass(ccc): + return ccc.modelCharacterClass + case let .atom(a): + return a.characterClass + case .characterPredicate: + // FIXME: Do we make one from this? + return nil + default: + return nil + } + } +} + extension CharacterClass { public func withMatchLevel( _ level: CharacterClass.MatchLevel @@ -333,6 +349,17 @@ extension CharacterClass { } } +extension DSLTree.Atom { + var characterClass: CharacterClass? { + switch self { + case let .unconverted(a): + return a.characterClass + + default: return nil + } + } +} + extension AST.Atom { var characterClass: CharacterClass? { switch kind { @@ -389,6 +416,74 @@ extension AST.Atom.EscapedBuiltin { } } +extension DSLTree.CustomCharacterClass { + // TODO: Refactor a bit, and... can we drop this type? + var modelCharacterClass: CharacterClass? { + var result = + Array() + for m in members { + switch m { + case let .atom(a): + if let cc = a.characterClass { + result.append(.characterClass(cc)) + } else if let c = a.literalCharacterValue { + result.append(.character(c)) + } else { + return nil + } + case let .range(low, high): + guard let lhs = low.literalCharacterValue, + let rhs = high.literalCharacterValue + else { + return nil + } + result.append(.range(lhs...rhs)) + + case let .custom(ccc): + guard let cc = ccc.modelCharacterClass else { + return nil + } + result.append(.characterClass(cc)) + + case let .intersection(lhs, rhs): + guard let lhs = lhs.modelCharacterClass, + let rhs = rhs.modelCharacterClass + else { + return nil + } + result.append(.setOperation( + lhs: .characterClass(lhs), + op: .intersection, + rhs: .characterClass(rhs))) + + case let .subtraction(lhs, rhs): + guard let lhs = lhs.modelCharacterClass, + let rhs = rhs.modelCharacterClass + else { + return nil + } + result.append(.setOperation( + lhs: .characterClass(lhs), + op: .subtraction, + rhs: .characterClass(rhs))) + + case let .symmetricDifference(lhs, rhs): + guard let lhs = lhs.modelCharacterClass, + let rhs = rhs.modelCharacterClass + else { + return nil + } + result.append(.setOperation( + lhs: .characterClass(lhs), + op: .symmetricDifference, + rhs: .characterClass(rhs))) + } + } + let cc = CharacterClass.custom(result) + return isInverted ? cc.inverted : cc + } +} + extension AST.CustomCharacterClass { /// The model character class for this custom character class. var modelCharacterClass: CharacterClass? { diff --git a/Sources/_StringProcessing/Legacy/LegacyCompile.swift b/Sources/_StringProcessing/Legacy/LegacyCompile.swift index 21942e0a8..49009b3f7 100644 --- a/Sources/_StringProcessing/Legacy/LegacyCompile.swift +++ b/Sources/_StringProcessing/Legacy/LegacyCompile.swift @@ -13,6 +13,12 @@ import _MatchingEngine func compile( _ ast: AST, options: REOptions = .none +) throws -> RECode { + try compile(ast.dslTree, options: options) +} + +func compile( + _ ast: DSLTree, options: REOptions = .none ) throws -> RECode { var currentLabel = 0 func createLabel() -> RECode.Instruction { @@ -20,8 +26,7 @@ func compile( return .label(currentLabel) } var instructions = RECode.InstructionList() - func compileNode(_ ast: AST.Node) throws { - + func compileNode(_ ast: DSLTree.Node) throws { if let cc = ast.characterClass { instructions.append(.characterClass(cc)) return @@ -30,12 +35,12 @@ func compile( switch ast { case .trivia, .empty: return - case .quote(let s): - s.literal.forEach { instructions.append(.character($0)) } + case let .quotedLiteral(s): + s.forEach { instructions.append(.character($0)) } return - case .atom(let a): - switch a.kind { + case let .atom(a): + switch a { case .char(let c): instructions.append(.character(c)) return @@ -46,37 +51,36 @@ func compile( instructions.append(.any) return default: - throw unsupported("Unsupported: \(a._dumpBase)") + throw unsupported("Unsupported: \(a)") } - case .group(let g): - switch g.kind.value { + case let .group(kind, child): + switch kind { case .nonCapture: instructions.append(.beginGroup) - try compileNode(g.child) + try compileNode(child) instructions.append(.endGroup) return case .capture: instructions.append(.beginCapture) - try compileNode(g.child) + try compileNode(child) instructions.append(.endCapture()) return default: - throw unsupported("Unsupported group \(g.kind.value) \(g)") + throw unsupported("Unsupported group \(kind)") } - case let .groupTransform(g, transform: t) where g.kind.value == .capture: + case let .groupTransform(kind, child, transform) where kind == .capture: instructions.append(.beginCapture) - try compileNode(g.child) - instructions.append(.endCapture(transform: t)) + try compileNode(child) + instructions.append(.endCapture(transform: transform)) return - case .groupTransform(let g, _): - throw unsupported("Unsupported group \(g)") + case let .groupTransform(kind, _, _): + throw unsupported("Unsupported group transform \(kind)") - case .concatenation(let concat): - let children = concat.children + case let .concatenation(children): let childrenHaveCaptures = children.any(\.hasCapture) if childrenHaveCaptures { instructions.append(.beginGroup) @@ -87,9 +91,8 @@ func compile( } return - case .quantification(let quant): - let child = quant.child - switch (quant.amount.value, quant.kind.value) { + case let .quantification(amount, kind, child): + switch (amount, kind) { case (.zeroOrMore, .eager): // a* ==> L_START, , a, goto L_START, L_DONE let childHasCaptures = child.hasCapture @@ -221,10 +224,10 @@ func compile( } return default: - throw unsupported("Unsupported: \(quant._dumpBase)") + throw unsupported("Unsupported: \((amount, kind))") } - case .alternation(let alt): + case let .alternation(children): // a|b ==> , a, goto L_DONE, L_B, b, L_DONE // a|b|c ==> , a, goto L_DONE, // L_B, , b, goto L_DONE, L_C, c, L_DONE @@ -237,7 +240,6 @@ func compile( // E.g. `a` falls-through to the rest of the program and the // other cases branch back. // - let children = alt.children assert(!children.isEmpty) guard children.count > 1 else { return try compileNode(children[0]) @@ -258,16 +260,25 @@ func compile( return case .conditional: - throw unsupported(ast.renderAsCanonical()) + throw unsupported("Conditionals") case .absentFunction: - throw unsupported(ast.renderAsCanonical()) + throw unsupported("Absent functions") case .customCharacterClass: fatalError("unreachable") - case .atom(let a) where a.characterClass != nil: + case let .atom(a) where a.characterClass != nil: fatalError("unreachable") + + case let .convertedRegexLiteral(node, _): + try compileNode(node) + + case .characterPredicate, .consumer, .consumerValidator: + throw unsupported("DSL extensions") + + case let .regexLiteral(re): + try compileNode(re.dslTreeNode) } } diff --git a/Sources/_StringProcessing/RegexDSL/Core.swift b/Sources/_StringProcessing/RegexDSL/Core.swift index 99e99da7d..bcdf96c5d 100644 --- a/Sources/_StringProcessing/RegexDSL/Core.swift +++ b/Sources/_StringProcessing/RegexDSL/Core.swift @@ -64,10 +64,7 @@ public struct Regex: RegexProtocol { /// The legacy `RECode` for execution with a legacy VM. lazy private(set) var legacyLoweredProgram: RECode = { do { - guard let ast = tree.ast else { - throw "Extended support unavailable in legacy VM" - } - return try compile(ast) + return try compile(tree) } catch { fatalError("Regex engine internal error: \(String(describing: error))") } @@ -182,6 +179,7 @@ extension RegexProtocol { } return RegexMatch(range: range, match: convertedMatch) } + let executor = Executor(program: regex.program.loweredProgram) guard let result = executor.execute( input: input, in: inputRange, mode: mode diff --git a/Sources/_StringProcessing/RegexDSL/DSLTree.swift b/Sources/_StringProcessing/RegexDSL/DSLTree.swift index ab35ea588..05b345bf8 100644 --- a/Sources/_StringProcessing/RegexDSL/DSLTree.swift +++ b/Sources/_StringProcessing/RegexDSL/DSLTree.swift @@ -417,9 +417,14 @@ extension DSLTree { extension DSLTree.Node { var hasCapture: Bool { switch self { - case .group(let k, _) where k.isCapturing, - .groupTransform(let k, _, _) where k.isCapturing: + case let .group(k, _) where k.isCapturing, + let .groupTransform(k, _, _) where k.isCapturing: return true + case let .convertedRegexLiteral(n, re): + assert(n.hasCapture == re.hasCapture) + return n.hasCapture + case let .regexLiteral(re): + return re.hasCapture default: break } From 30875afac8e610ff8821525381ef3535240d6f0e Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 1 Feb 2022 17:32:49 -0700 Subject: [PATCH 6/7] WIP: Update for main, some tests failing --- Sources/_StringProcessing/CharacterClass.swift | 7 +++++++ .../_StringProcessing/ConsumerInterface.swift | 18 +++++++++++++++--- Sources/_StringProcessing/PrintAsPattern.swift | 6 +++--- .../_StringProcessing/RegexDSL/DSLTree.swift | 11 +++++++---- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Sources/_StringProcessing/CharacterClass.swift b/Sources/_StringProcessing/CharacterClass.swift index e282afe5d..334f38167 100644 --- a/Sources/_StringProcessing/CharacterClass.swift +++ b/Sources/_StringProcessing/CharacterClass.swift @@ -477,6 +477,13 @@ extension DSLTree.CustomCharacterClass { lhs: .characterClass(lhs), op: .symmetricDifference, rhs: .characterClass(rhs))) + + case let .quotedLiteral(s): + // Decompose quoted literal into literal characters. + result += s.map { .character($0) } + + case .trivia: + break } } let cc = CharacterClass.custom(result) diff --git a/Sources/_StringProcessing/ConsumerInterface.swift b/Sources/_StringProcessing/ConsumerInterface.swift index 85499048b..74fb247d3 100644 --- a/Sources/_StringProcessing/ConsumerInterface.swift +++ b/Sources/_StringProcessing/ConsumerInterface.swift @@ -37,10 +37,9 @@ struct Unsupported: Error, CustomStringConvertible { func unsupported( _ s: String, file: StaticString = #file, - line: Int = #line + line: UInt = #line ) -> Unsupported { - return Unsupported( - message: s, file: String(describing: file), line: line) + return Unsupported(s, file: file, line: line) } struct Unreachable: Error, CustomStringConvertible { @@ -289,6 +288,19 @@ extension DSLTree.CustomCharacterClass.Member { } return rhs(input, bounds) } + case .quotedLiteral(let s): + return { input, bounds in + guard input[bounds].starts(with: s) else { + return nil + } + // TODO: Don't double count + return input.index(bounds.lowerBound, offsetBy: s.count) + } + case .trivia: + // TODO: Should probably strip this earlier... + return { _, bounds in + return bounds.lowerBound + } } } diff --git a/Sources/_StringProcessing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift index 44599e781..79d410517 100644 --- a/Sources/_StringProcessing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -197,12 +197,12 @@ extension PrettyPrinter { } else { print(" // TODO: Atom \(a) ") } - case .quote(let q): - print("// TODO: quote \(q.literal._quoted) in custom character classes (should we split it?)") + case .quotedLiteral(let s): + print("// TODO: quote \(s._quoted) in custom character classes (should we split it?)") case .trivia(let t): // TODO: We might want to output comments... _ = t -case .symmetricDifference, .intersection, .subtraction: + case .symmetricDifference, .intersection, .subtraction: print("// TODO: Set operation: \(member)") } } diff --git a/Sources/_StringProcessing/RegexDSL/DSLTree.swift b/Sources/_StringProcessing/RegexDSL/DSLTree.swift index 05b345bf8..5f42033d2 100644 --- a/Sources/_StringProcessing/RegexDSL/DSLTree.swift +++ b/Sources/_StringProcessing/RegexDSL/DSLTree.swift @@ -99,6 +99,10 @@ extension DSLTree { case range(Atom, Atom) case custom(CustomCharacterClass) + case quotedLiteral(String) + + case trivia(String) + indirect case intersection(CustomCharacterClass, CustomCharacterClass) indirect case subtraction(CustomCharacterClass, CustomCharacterClass) indirect case symmetricDifference(CustomCharacterClass, CustomCharacterClass) @@ -321,10 +325,7 @@ extension AST.CustomCharacterClass { return .atom(a.dslTreeAtom) case let .quote(q): - // TODO: Probably should flatten instead of nest - return .custom(.init( - members: q.literal.map { .atom(.char($0)) }, - isInverted: false)) + return .quotedLiteral(q.literal) case let .setOperation(lhs, op, rhs): let lhs = DSLTree.CustomCharacterClass( @@ -342,6 +343,8 @@ extension AST.CustomCharacterClass { case .symmetricDifference: return .symmetricDifference(lhs, rhs) } + case let .trivia(t): + return .trivia(t.contents) } } From 3b9916631cbca01809d0b80ef434c0ce557d9d50 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 1 Feb 2022 17:37:32 -0700 Subject: [PATCH 7/7] WIP: bug fix --- Sources/_StringProcessing/ConsumerInterface.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/_StringProcessing/ConsumerInterface.swift b/Sources/_StringProcessing/ConsumerInterface.swift index 74fb247d3..1feb83410 100644 --- a/Sources/_StringProcessing/ConsumerInterface.swift +++ b/Sources/_StringProcessing/ConsumerInterface.swift @@ -290,11 +290,10 @@ extension DSLTree.CustomCharacterClass.Member { } case .quotedLiteral(let s): return { input, bounds in - guard input[bounds].starts(with: s) else { + guard s.contains(input[bounds.lowerBound]) else { return nil } - // TODO: Don't double count - return input.index(bounds.lowerBound, offsetBy: s.count) + return input.index(after: bounds.lowerBound) } case .trivia: // TODO: Should probably strip this earlier...